summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.rubocop.yml4
-rw-r--r--CHANGELOG.md8
-rw-r--r--CONTRIBUTING.md198
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--GITLAB_PAGES_VERSION2
-rw-r--r--GITLAB_SHELL_VERSION2
-rw-r--r--Gemfile4
-rw-r--r--Gemfile.lock9
-rw-r--r--Gemfile.rails5.lock9
-rw-r--r--app/assets/images/koding-logo.svg8
-rw-r--r--app/assets/javascripts/blob_edit/blob_bundle.js4
-rw-r--r--app/assets/javascripts/blob_edit/edit_blob.js8
-rw-r--r--app/assets/javascripts/boards/components/issue_card_inner.vue10
-rw-r--r--app/assets/javascripts/boards/components/modal/list.vue10
-rw-r--r--app/assets/javascripts/boards/components/modal/lists_dropdown.vue6
-rw-r--r--app/assets/javascripts/boards/components/project_select.vue30
-rw-r--r--app/assets/javascripts/clusters/clusters_bundle.js10
-rw-r--r--app/assets/javascripts/clusters/clusters_index.js5
-rw-r--r--app/assets/javascripts/clusters/components/applications.vue2
-rw-r--r--app/assets/javascripts/cycle_analytics/components/banner.vue11
-rw-r--r--app/assets/javascripts/diffs/components/compare_versions_dropdown.vue2
-rw-r--r--app/assets/javascripts/diffs/components/diff_file_header.vue10
-rw-r--r--app/assets/javascripts/diffs/store/modules/diff_state.js4
-rw-r--r--app/assets/javascripts/dirty_submit/dirty_submit_collection.js13
-rw-r--r--app/assets/javascripts/dirty_submit/dirty_submit_factory.js9
-rw-r--r--app/assets/javascripts/dirty_submit/dirty_submit_form.js82
-rw-r--r--app/assets/javascripts/dismissable_callout.js27
-rw-r--r--app/assets/javascripts/environments/components/environment_actions.vue8
-rw-r--r--app/assets/javascripts/environments/components/environment_item.vue34
-rw-r--r--app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue13
-rw-r--r--app/assets/javascripts/jobs/components/job_app.vue12
-rw-r--r--app/assets/javascripts/jobs/components/job_log_controllers.vue2
-rw-r--r--app/assets/javascripts/jobs/components/sidebar.vue5
-rw-r--r--app/assets/javascripts/jobs/components/stages_dropdown.vue21
-rw-r--r--app/assets/javascripts/jobs/job_details_bundle.js8
-rw-r--r--app/assets/javascripts/jobs/store/actions.js11
-rw-r--r--app/assets/javascripts/jobs/store/getters.js4
-rw-r--r--app/assets/javascripts/jobs/store/mutations.js13
-rw-r--r--app/assets/javascripts/jobs/store/state.js4
-rw-r--r--app/assets/javascripts/lib/ace.js1
-rw-r--r--app/assets/javascripts/lib/utils/ace_utils.js6
-rw-r--r--app/assets/javascripts/main.js1
-rw-r--r--app/assets/javascripts/merge_conflicts/components/diff_file_editor.js3
-rw-r--r--app/assets/javascripts/notes/components/diff_with_note.vue1
-rw-r--r--app/assets/javascripts/notes/components/note_form.vue14
-rw-r--r--app/assets/javascripts/pages/groups/edit/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/index.js6
-rw-r--r--app/assets/javascripts/pages/root/index.js5
-rw-r--r--app/assets/javascripts/pages/users/user_overview_block.js15
-rw-r--r--app/assets/javascripts/pages/users/user_tabs.js29
-rw-r--r--app/assets/javascripts/performance_bar/components/performance_bar_app.vue15
-rw-r--r--app/assets/javascripts/persistent_user_callout.js34
-rw-r--r--app/assets/javascripts/right_sidebar.js2
-rw-r--r--app/assets/javascripts/settings_panels.js5
-rw-r--r--app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue26
-rw-r--r--app/assets/javascripts/vue_shared/components/icon.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/issue/issue_warning.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/system_note.vue2
-rw-r--r--app/assets/stylesheets/framework/blocks.scss10
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss16
-rw-r--r--app/assets/stylesheets/framework/mixins.scss9
-rw-r--r--app/assets/stylesheets/framework/variables.scss1
-rw-r--r--app/assets/stylesheets/pages/boards.scss3
-rw-r--r--app/assets/stylesheets/pages/cycle_analytics.scss2
-rw-r--r--app/assets/stylesheets/pages/diff.scss16
-rw-r--r--app/assets/stylesheets/pages/environments.scss1
-rw-r--r--app/assets/stylesheets/pages/groups.scss2
-rw-r--r--app/assets/stylesheets/pages/issuable.scss4
-rw-r--r--app/assets/stylesheets/pages/settings.scss4
-rw-r--r--app/assets/stylesheets/performance_bar.scss4
-rw-r--r--app/controllers/application_controller.rb4
-rw-r--r--app/controllers/koding_controller.rb17
-rw-r--r--app/controllers/projects/clusters/applications_controller.rb36
-rw-r--r--app/controllers/projects/clusters_controller.rb10
-rw-r--r--app/controllers/users_controller.rb4
-rw-r--r--app/finders/branches_finder.rb41
-rw-r--r--app/finders/projects_finder.rb27
-rw-r--r--app/helpers/application_settings_helper.rb3
-rw-r--r--app/helpers/blob_helper.rb2
-rw-r--r--app/helpers/dashboard_helper.rb23
-rw-r--r--app/helpers/preferences_helper.rb36
-rw-r--r--app/helpers/projects_helper.rb16
-rw-r--r--app/helpers/sorting_helper.rb14
-rw-r--r--app/models/application_setting.rb8
-rw-r--r--app/models/blob.rb2
-rw-r--r--app/models/concerns/blob_like.rb2
-rw-r--r--app/models/deployment.rb11
-rw-r--r--app/models/environment.rb2
-rw-r--r--app/models/project.rb15
-rw-r--r--app/models/repository.rb18
-rw-r--r--app/models/user.rb2
-rw-r--r--app/models/user_callout.rb3
-rw-r--r--app/presenters/project_presenter.rb52
-rw-r--r--app/serializers/build_details_entity.rb3
-rw-r--r--app/serializers/issue_entity.rb2
-rw-r--r--app/serializers/merge_request_widget_entity.rb2
-rw-r--r--app/services/applications/create_service.rb1
-rw-r--r--app/services/clusters/applications/create_service.rb68
-rw-r--r--app/services/clusters/applications/schedule_installation_service.rb10
-rw-r--r--app/services/clusters/create_service.rb34
-rw-r--r--app/services/clusters/update_service.rb8
-rw-r--r--app/views/admin/application_settings/_koding.html.haml22
-rw-r--r--app/views/admin/application_settings/show.html.haml12
-rw-r--r--app/views/admin/applications/show.html.haml2
-rw-r--r--app/views/admin/groups/_form.html.haml4
-rw-r--r--app/views/dashboard/activity.html.haml3
-rw-r--r--app/views/dashboard/groups/index.html.haml3
-rw-r--r--app/views/dashboard/issues.html.haml3
-rw-r--r--app/views/dashboard/merge_requests.html.haml3
-rw-r--r--app/views/dashboard/projects/index.html.haml3
-rw-r--r--app/views/dashboard/projects/starred.html.haml3
-rw-r--r--app/views/dashboard/todos/index.html.haml3
-rw-r--r--app/views/devise/shared/_omniauth_box.html.haml2
-rw-r--r--app/views/doorkeeper/applications/show.html.haml2
-rw-r--r--app/views/explore/groups/index.html.haml5
-rw-r--r--app/views/explore/projects/index.html.haml3
-rw-r--r--app/views/explore/projects/starred.html.haml3
-rw-r--r--app/views/explore/projects/trending.html.haml3
-rw-r--r--app/views/groups/edit.html.haml24
-rw-r--r--app/views/groups/new.html.haml2
-rw-r--r--app/views/groups/settings/_advanced.html.haml20
-rw-r--r--app/views/groups/settings/_general.html.haml48
-rw-r--r--app/views/groups/settings/_lfs.html.haml15
-rw-r--r--app/views/groups/settings/_permissions.html.haml37
-rw-r--r--app/views/groups/settings/_two_factor_auth.html.haml16
-rw-r--r--app/views/groups/show.html.haml2
-rw-r--r--app/views/koding/index.html.haml6
-rw-r--r--app/views/layouts/koding.html.haml5
-rw-r--r--app/views/layouts/nav/_breadcrumbs.html.haml1
-rw-r--r--app/views/layouts/nav/_dashboard.html.haml1
-rw-r--r--app/views/layouts/nav/sidebar/_project.html.haml2
-rw-r--r--app/views/projects/_home_panel.html.haml2
-rw-r--r--app/views/projects/buttons/_koding.html.haml3
-rw-r--r--app/views/projects/clusters/_banner.html.haml4
-rw-r--r--app/views/projects/clusters/_gcp_signup_offer_banner.html.haml4
-rw-r--r--app/views/projects/deploy_tokens/_form.html.haml10
-rw-r--r--app/views/projects/deploy_tokens/_index.html.haml2
-rw-r--r--app/views/projects/deploy_tokens/_new_deploy_token.html.haml6
-rw-r--r--app/views/projects/jobs/show.html.haml4
-rw-r--r--app/views/projects/project_members/_new_project_member.html.haml4
-rw-r--r--app/views/projects/project_members/_team.html.haml2
-rw-r--r--app/views/shared/_allow_request_access.html.haml6
-rw-r--r--app/views/shared/_old_visibility_level.html.haml6
-rw-r--r--app/views/shared/_visibility_level.html.haml30
-rw-r--r--app/views/shared/projects/_list.html.haml3
-rw-r--r--app/views/shared/snippets/_form.html.haml2
-rw-r--r--changelogs/unreleased/22311-fix-duplicated-key-in-license-management-job.yml5
-rw-r--r--changelogs/unreleased/48684-sort-projects-by-stars-in-groups.yml4
-rw-r--r--changelogs/unreleased/48889-message-for-were-merged-into.yml5
-rw-r--r--changelogs/unreleased/49417-improve-settings-pages-design-by-prioritizing-content-group-settings.yml5
-rw-r--r--changelogs/unreleased/50185-fix-broken-file-name-navigation.yml5
-rw-r--r--changelogs/unreleased/51958-fix-mr-discussion-loading.yml5
-rw-r--r--changelogs/unreleased/52361-fix-file-tree-mobile.yml5
-rw-r--r--changelogs/unreleased/52421-show-canary-no-canary-in-the-performance-bar.yml5
-rw-r--r--changelogs/unreleased/52472-pipeline-endpoint-json.yml5
-rw-r--r--changelogs/unreleased/52519-runners-link.yml5
-rw-r--r--changelogs/unreleased/52532-unable-to-toggle-issuable-sidebar-out-of-collapsed-state.yml5
-rw-r--r--changelogs/unreleased/52564-personal-projects-pagination-in-profile-overview-tab-is-broken.yml5
-rw-r--r--changelogs/unreleased/52570-erased-block.yml5
-rw-r--r--changelogs/unreleased/52608-sidebar.yml5
-rw-r--r--changelogs/unreleased/52614-update-job-started-check.yml5
-rw-r--r--changelogs/unreleased/52618-incorrect-stage-being-shown-in-side-bar-of-job-view-api.yml5
-rw-r--r--changelogs/unreleased/52669-fixes-quick-actions-preview.yml5
-rw-r--r--changelogs/unreleased/bvl-merge-base-multiple-revisions.yml5
-rw-r--r--changelogs/unreleased/da-fix-does-not-import-projects-over-ssh.yml5
-rw-r--r--changelogs/unreleased/enable-frozen-string-lib-gitlab.yml5
-rw-r--r--changelogs/unreleased/even-more-frozen-string-lib.yml5
-rw-r--r--changelogs/unreleased/feature-improved-branch-filter-sorting.yml6
-rw-r--r--changelogs/unreleased/fl-update-svgs.yml5
-rw-r--r--changelogs/unreleased/gt-update-application-copy-secret-to-clipboard-data.yml5
-rw-r--r--changelogs/unreleased/replace-i-to-icons-in-vue-components.yml5
-rw-r--r--changelogs/unreleased/sh-remove-koding.yml5
-rw-r--r--changelogs/unreleased/zj-remove-linguist.yml5
-rw-r--r--config/routes.rb3
-rw-r--r--config/unicorn.rb.example4
-rw-r--r--config/unicorn.rb.example.development4
-rw-r--r--db/post_migrate/20181013005024_remove_koding_from_application_settings.rb17
-rw-r--r--db/schema.rb4
-rw-r--r--doc/README.md2
-rw-r--r--doc/administration/gitaly/index.md6
-rw-r--r--doc/administration/integration/koding.md246
-rw-r--r--doc/administration/integration/plantuml.md4
-rw-r--r--doc/administration/job_artifacts.md3
-rw-r--r--doc/api/events.md4
-rw-r--r--doc/api/repositories.md2
-rw-r--r--doc/api/settings.md10
-rw-r--r--doc/ci/examples/laravel_with_gitlab_and_envoy/index.md12
-rw-r--r--doc/ci/examples/php.md2
-rw-r--r--doc/ci/pipelines.md4
-rw-r--r--doc/ci/triggers/README.md7
-rw-r--r--doc/ci/yaml/README.md4
-rw-r--r--doc/development/README.md3
-rw-r--r--doc/development/code_review.md16
-rw-r--r--doc/development/contributing/community_roles.md6
-rw-r--r--doc/development/contributing/design.md33
-rw-r--r--doc/development/contributing/index.md208
-rw-r--r--doc/development/contributing/issue_workflow.md42
-rw-r--r--doc/development/contributing/merge_request_workflow.md30
-rw-r--r--doc/development/contributing/style_guides.md40
-rw-r--r--doc/development/documentation/index.md4
-rw-r--r--doc/development/feature_flags.md31
-rw-r--r--doc/development/new_fe_guide/index.md4
-rw-r--r--doc/development/new_fe_guide/modules/dirty_submit.md23
-rw-r--r--doc/development/new_fe_guide/modules/index.md5
-rw-r--r--doc/install/installation.md2
-rw-r--r--doc/policy/maintenance.md3
-rw-r--r--doc/update/11.3-to-11.4.md4
-rw-r--r--doc/user/discussions/index.md2
-rw-r--r--doc/user/group/index.md1
-rw-r--r--[-rwxr-xr-x]doc/user/project/img/issue_boards_core.pngbin61230 -> 61230 bytes
-rw-r--r--[-rwxr-xr-x]doc/user/project/img/issue_boards_premium.pngbin72434 -> 72434 bytes
-rw-r--r--doc/user/project/img/koding_build-in-progress.pngbin21937 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_build-logs.pngbin91364 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_build-success.pngbin73005 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_commit-koding.yml.pngbin86023 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_different-stack-on-mr-try.pngbin93404 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_edit-on-ide.pngbin90638 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_enable-koding.pngbin20291 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_landing.pngbin80985 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_open-gitlab-from-koding.pngbin10851 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_run-in-ide.pngbin22178 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_run-mr-in-ide.pngbin93780 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_set-up-ide.pngbin54062 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_stack-import.pngbin137582 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_start-build.pngbin27925 -> 0 bytes
-rw-r--r--doc/user/project/koding.md131
-rw-r--r--doc/user/project/merge_requests/cherry_pick_changes.md8
-rw-r--r--doc/user/project/merge_requests/img/merge_request_diff_file_navigation.pngbin112288 -> 111544 bytes
-rw-r--r--doc/user/project/merge_requests/index.md6
-rw-r--r--doc/user/project/repository/branches/img/branch_filter_search_box.pngbin0 -> 83225 bytes
-rw-r--r--doc/user/project/repository/branches/index.md18
-rw-r--r--doc/user/project/repository/index.md5
-rw-r--r--doc/user/reserved_names.md1
-rw-r--r--lib/api/repositories.rb9
-rw-r--r--lib/api/settings.rb4
-rw-r--r--lib/generators/rails/post_deployment_migration/post_deployment_migration_generator.rb2
-rw-r--r--lib/gitaly/server.rb2
-rw-r--r--lib/gitlab/auth/activity.rb2
-rw-r--r--lib/gitlab/auth/database/authentication.rb2
-rw-r--r--lib/gitlab/auth/ip_rate_limiter.rb2
-rw-r--r--lib/gitlab/auth/ldap/access.rb2
-rw-r--r--lib/gitlab/auth/ldap/adapter.rb2
-rw-r--r--lib/gitlab/auth/ldap/auth_hash.rb2
-rw-r--r--lib/gitlab/auth/ldap/authentication.rb2
-rw-r--r--lib/gitlab/auth/ldap/config.rb2
-rw-r--r--lib/gitlab/auth/ldap/dn.rb1
-rw-r--r--lib/gitlab/auth/ldap/ldap_connection_error.rb2
-rw-r--r--lib/gitlab/auth/ldap/person.rb2
-rw-r--r--lib/gitlab/auth/ldap/user.rb2
-rw-r--r--lib/gitlab/auth/o_auth/auth_hash.rb2
-rw-r--r--lib/gitlab/auth/o_auth/authentication.rb2
-rw-r--r--lib/gitlab/auth/o_auth/identity_linker.rb2
-rw-r--r--lib/gitlab/auth/o_auth/provider.rb2
-rw-r--r--lib/gitlab/auth/o_auth/session.rb2
-rw-r--r--lib/gitlab/auth/o_auth/user.rb2
-rw-r--r--lib/gitlab/auth/omniauth_identity_linker_base.rb2
-rw-r--r--lib/gitlab/auth/request_authenticator.rb2
-rw-r--r--lib/gitlab/auth/result.rb5
-rw-r--r--lib/gitlab/auth/saml/auth_hash.rb2
-rw-r--r--lib/gitlab/auth/saml/config.rb2
-rw-r--r--lib/gitlab/auth/saml/identity_linker.rb2
-rw-r--r--lib/gitlab/auth/saml/user.rb2
-rw-r--r--lib/gitlab/auth/too_many_ips.rb2
-rw-r--r--lib/gitlab/auth/unique_ips_limiter.rb2
-rw-r--r--lib/gitlab/auth/user_access_denied_reason.rb2
-rw-r--r--lib/gitlab/auth/user_auth_finders.rb2
-rw-r--r--lib/gitlab/badge/base.rb2
-rw-r--r--lib/gitlab/badge/coverage/metadata.rb2
-rw-r--r--lib/gitlab/badge/coverage/report.rb2
-rw-r--r--lib/gitlab/badge/coverage/template.rb2
-rw-r--r--lib/gitlab/badge/metadata.rb2
-rw-r--r--lib/gitlab/badge/pipeline/metadata.rb2
-rw-r--r--lib/gitlab/badge/pipeline/status.rb2
-rw-r--r--lib/gitlab/badge/pipeline/template.rb2
-rw-r--r--lib/gitlab/badge/template.rb2
-rw-r--r--lib/gitlab/bare_repository_import/importer.rb7
-rw-r--r--lib/gitlab/bare_repository_import/repository.rb7
-rw-r--r--lib/gitlab/bitbucket_import/importer.rb2
-rw-r--r--lib/gitlab/bitbucket_import/project_creator.rb2
-rw-r--r--lib/gitlab/bitbucket_server_import/project_creator.rb2
-rw-r--r--lib/gitlab/blob_helper.rb145
-rw-r--r--lib/gitlab/cache/ci/project_pipeline_status.rb2
-rw-r--r--lib/gitlab/cache/request_cache.rb2
-rw-r--r--lib/gitlab/checks/change_access.rb2
-rw-r--r--lib/gitlab/checks/commit_check.rb2
-rw-r--r--lib/gitlab/checks/force_push.rb2
-rw-r--r--lib/gitlab/checks/lfs_integrity.rb2
-rw-r--r--lib/gitlab/checks/matching_merge_request.rb2
-rw-r--r--lib/gitlab/checks/post_push_message.rb2
-rw-r--r--lib/gitlab/checks/project_created.rb2
-rw-r--r--lib/gitlab/checks/project_moved.rb2
-rw-r--r--lib/gitlab/ci/templates/Android.gitlab-ci.yml40
-rw-r--r--lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml4
-rw-r--r--lib/gitlab/conflict/file.rb1
-rw-r--r--lib/gitlab/file_detector.rb1
-rw-r--r--lib/gitlab/git/blob.rb8
-rw-r--r--lib/gitlab/git/blob_snippet.rb34
-rw-r--r--lib/gitlab/git/repository.rb4
-rw-r--r--lib/gitlab/gon_helper.rb15
-rw-r--r--lib/gitlab/language_data.rb33
-rw-r--r--lib/gitlab/path_regex.rb1
-rw-r--r--lib/google_api/auth.rb2
-rw-r--r--lib/google_api/cloud_platform/client.rb2
-rw-r--r--lib/haml_lint/inline_javascript.rb5
-rw-r--r--lib/json_web_token/rsa_token.rb2
-rw-r--r--lib/json_web_token/token.rb2
-rw-r--r--lib/mattermost/client.rb2
-rw-r--r--lib/mattermost/command.rb2
-rw-r--r--lib/mattermost/error.rb2
-rw-r--r--lib/mattermost/session.rb2
-rw-r--r--lib/mattermost/team.rb2
-rw-r--r--lib/microsoft_teams/activity.rb2
-rw-r--r--lib/microsoft_teams/notifier.rb2
-rw-r--r--lib/object_storage/direct_upload.rb2
-rw-r--r--lib/omni_auth/strategies/bitbucket.rb2
-rw-r--r--lib/omni_auth/strategies/jwt.rb2
-rw-r--r--lib/peek/rblineprof/custom_controller_helpers.rb6
-rw-r--r--lib/peek/views/gitaly.rb2
-rw-r--r--lib/peek/views/host.rb7
-rw-r--r--lib/rouge/formatters/html_gitlab.rb2
-rw-r--r--lib/rouge/plugins/common_mark.rb2
-rw-r--r--lib/rspec_flaky/config.rb2
-rw-r--r--lib/rspec_flaky/example.rb2
-rw-r--r--lib/rspec_flaky/flaky_example.rb2
-rw-r--r--lib/rspec_flaky/flaky_examples_collection.rb2
-rw-r--r--lib/rspec_flaky/listener.rb2
-rw-r--r--lib/rspec_flaky/report.rb2
-rw-r--r--lib/system_check/app/active_users_check.rb2
-rw-r--r--lib/system_check/app/database_config_exists_check.rb2
-rw-r--r--lib/system_check/app/git_config_check.rb2
-rw-r--r--lib/system_check/app/git_user_default_ssh_config_check.rb2
-rw-r--r--lib/system_check/app/git_version_check.rb2
-rw-r--r--lib/system_check/app/gitlab_config_exists_check.rb2
-rw-r--r--lib/system_check/app/gitlab_config_up_to_date_check.rb2
-rw-r--r--lib/system_check/app/init_script_exists_check.rb2
-rw-r--r--lib/system_check/app/init_script_up_to_date_check.rb2
-rw-r--r--lib/system_check/app/log_writable_check.rb2
-rw-r--r--lib/system_check/app/migrations_are_up_check.rb2
-rw-r--r--lib/system_check/app/orphaned_group_members_check.rb2
-rw-r--r--lib/system_check/app/projects_have_namespace_check.rb2
-rw-r--r--lib/system_check/app/redis_version_check.rb2
-rw-r--r--lib/system_check/app/ruby_version_check.rb2
-rw-r--r--lib/system_check/app/tmp_writable_check.rb2
-rw-r--r--lib/system_check/app/uploads_directory_exists_check.rb2
-rw-r--r--lib/system_check/app/uploads_path_permission_check.rb2
-rw-r--r--lib/system_check/app/uploads_path_tmp_permission_check.rb2
-rw-r--r--lib/system_check/base_check.rb2
-rw-r--r--lib/system_check/helpers.rb2
-rw-r--r--lib/system_check/incoming_email/foreman_configured_check.rb2
-rw-r--r--lib/system_check/incoming_email/imap_authentication_check.rb2
-rw-r--r--lib/system_check/incoming_email/initd_configured_check.rb2
-rw-r--r--lib/system_check/incoming_email/mail_room_running_check.rb2
-rw-r--r--lib/system_check/orphans/namespace_check.rb2
-rw-r--r--lib/system_check/orphans/repository_check.rb2
-rw-r--r--lib/system_check/simple_executor.rb2
-rw-r--r--locale/ar_SA/gitlab.po12
-rw-r--r--locale/bg/gitlab.po12
-rw-r--r--locale/ca_ES/gitlab.po12
-rw-r--r--locale/cs_CZ/gitlab.po12
-rw-r--r--locale/da_DK/gitlab.po12
-rw-r--r--locale/de/gitlab.po12
-rw-r--r--locale/en/gitlab.po3
-rw-r--r--locale/eo/gitlab.po12
-rw-r--r--locale/es/gitlab.po12
-rw-r--r--locale/et_EE/gitlab.po12
-rw-r--r--locale/fil_PH/gitlab.po12
-rw-r--r--locale/fr/gitlab.po12
-rw-r--r--locale/gitlab.pot85
-rw-r--r--locale/gl_ES/gitlab.po12
-rw-r--r--locale/he_IL/gitlab.po12
-rw-r--r--locale/id_ID/gitlab.po12
-rw-r--r--locale/it/gitlab.po12
-rw-r--r--locale/ja/gitlab.po12
-rw-r--r--locale/ko/gitlab.po12
-rw-r--r--locale/mn_MN/gitlab.po12
-rw-r--r--locale/nb_NO/gitlab.po12
-rw-r--r--locale/nl_NL/gitlab.po12
-rw-r--r--locale/pl_PL/gitlab.po12
-rw-r--r--locale/pt_BR/gitlab.po12
-rw-r--r--locale/ro_RO/gitlab.po12
-rw-r--r--locale/ru/gitlab.po12
-rw-r--r--locale/sq_AL/gitlab.po12
-rw-r--r--locale/tr_TR/gitlab.po12
-rw-r--r--locale/uk/gitlab.po12
-rw-r--r--locale/zh_CN/gitlab.po12
-rw-r--r--locale/zh_HK/gitlab.po12
-rw-r--r--locale/zh_TW/gitlab.po12
-rw-r--r--package.json2
-rw-r--r--qa/qa.rb17
-rw-r--r--qa/qa/factory/resource/deploy_token.rb48
-rw-r--r--qa/qa/page/README.md38
-rw-r--r--qa/qa/page/component/clone_panel.rb4
-rw-r--r--qa/qa/page/component/users_select.rb14
-rw-r--r--qa/qa/page/dashboard/groups.rb6
-rw-r--r--qa/qa/page/dashboard/projects.rb2
-rw-r--r--qa/qa/page/file/form.rb6
-rw-r--r--qa/qa/page/file/shared/commit_message.rb2
-rw-r--r--qa/qa/page/file/show.rb6
-rw-r--r--qa/qa/page/group/new.rb10
-rw-r--r--qa/qa/page/group/show.rb2
-rw-r--r--qa/qa/page/issuable/sidebar.rb4
-rw-r--r--qa/qa/page/layout/banner.rb2
-rw-r--r--qa/qa/page/main/login.rb9
-rw-r--r--qa/qa/page/main/menu.rb6
-rw-r--r--qa/qa/page/main/oauth.rb2
-rw-r--r--qa/qa/page/merge_request/show.rb6
-rw-r--r--qa/qa/page/profile/menu.rb8
-rw-r--r--qa/qa/page/profile/personal_access_tokens.rb8
-rw-r--r--qa/qa/page/project/activity.rb2
-rw-r--r--qa/qa/page/project/fork/new.rb2
-rw-r--r--qa/qa/page/project/import/github.rb12
-rw-r--r--qa/qa/page/project/issue/index.rb2
-rw-r--r--qa/qa/page/project/issue/new.rb6
-rw-r--r--qa/qa/page/project/issue/show.rb10
-rw-r--r--qa/qa/page/project/job/show.rb6
-rw-r--r--qa/qa/page/project/menu.rb35
-rw-r--r--qa/qa/page/project/new.rb16
-rw-r--r--qa/qa/page/project/operations/kubernetes/add.rb2
-rw-r--r--qa/qa/page/project/operations/kubernetes/add_existing.rb10
-rw-r--r--qa/qa/page/project/operations/kubernetes/index.rb2
-rw-r--r--qa/qa/page/project/operations/kubernetes/show.rb8
-rw-r--r--qa/qa/page/project/pipeline/index.rb2
-rw-r--r--qa/qa/page/project/pipeline/show.rb10
-rw-r--r--qa/qa/page/project/settings/advanced.rb6
-rw-r--r--qa/qa/page/project/settings/ci_cd.rb10
-rw-r--r--qa/qa/page/project/settings/common.rb2
-rw-r--r--qa/qa/page/project/settings/deploy_keys.rb12
-rw-r--r--qa/qa/page/project/settings/deploy_tokens.rb64
-rw-r--r--qa/qa/page/project/settings/members.rb27
-rw-r--r--qa/qa/page/project/settings/repository.rb6
-rw-r--r--qa/qa/page/project/settings/runners.rb6
-rw-r--r--qa/qa/page/project/settings/secret_variables.rb10
-rw-r--r--qa/qa/page/project/show.rb8
-rw-r--r--qa/qa/page/project/wiki/edit.rb6
-rw-r--r--qa/qa/page/project/wiki/new.rb12
-rw-r--r--qa/qa/page/project/wiki/show.rb2
-rw-r--r--qa/qa/runtime/browser.rb4
-rw-r--r--qa/qa/runtime/env.rb4
-rw-r--r--qa/qa/scenario/test/integration/instance_saml.rb13
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb17
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb27
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb23
-rw-r--r--qa/qa/vendor/saml_idp/page/base.rb14
-rw-r--r--qa/qa/vendor/saml_idp/page/login.rb19
-rw-r--r--qa/spec/page/base_spec.rb6
-rw-r--r--qa/spec/page/view_spec.rb4
-rw-r--r--qa/spec/scenario/test/integration/instance_saml_spec.rb9
-rw-r--r--rubocop/cop/qa/element_with_pattern.rb39
-rw-r--r--rubocop/qa_helpers.rb11
-rw-r--r--rubocop/rubocop.rb1
-rw-r--r--spec/controllers/application_controller_spec.rb26
-rw-r--r--spec/controllers/projects/jobs_controller_spec.rb4
-rw-r--r--spec/controllers/projects/merge_requests/conflicts_controller_spec.rb1
-rw-r--r--spec/features/groups/group_settings_spec.rb2
-rw-r--r--spec/features/groups/share_lock_spec.rb4
-rw-r--r--spec/features/groups/show_spec.rb21
-rw-r--r--spec/features/groups_spec.rb5
-rw-r--r--spec/features/projects/jobs_spec.rb75
-rw-r--r--spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb35
-rw-r--r--spec/features/security/dashboard_access_spec.rb14
-rw-r--r--spec/features/uploads/user_uploads_avatar_to_group_spec.rb2
-rw-r--r--spec/features/users/overview_spec.rb31
-rw-r--r--spec/finders/branches_finder_spec.rb33
-rw-r--r--spec/fixtures/api/schemas/job/job_details.json6
-rw-r--r--spec/fixtures/valid.po3
-rw-r--r--spec/helpers/preferences_helper_spec.rb7
-rw-r--r--spec/javascripts/.eslintrc.yml2
-rw-r--r--spec/javascripts/awards_handler_spec.js16
-rw-r--r--spec/javascripts/behaviors/quick_submit_spec.js2
-rw-r--r--spec/javascripts/bootstrap_jquery_spec.js2
-rw-r--r--spec/javascripts/datetime_utility_spec.js6
-rw-r--r--spec/javascripts/diffs/components/diff_file_header_spec.js15
-rw-r--r--spec/javascripts/diffs/components/diff_file_spec.js8
-rw-r--r--spec/javascripts/diffs/components/diff_line_gutter_content_spec.js2
-rw-r--r--spec/javascripts/diffs/components/inline_diff_view_spec.js4
-rw-r--r--spec/javascripts/dirty_submit/dirty_submit_collection_spec.js25
-rw-r--r--spec/javascripts/dirty_submit/dirty_submit_factory_spec.js18
-rw-r--r--spec/javascripts/dirty_submit/dirty_submit_form_spec.js21
-rw-r--r--spec/javascripts/dirty_submit/helper.js31
-rw-r--r--spec/javascripts/emoji_spec.js38
-rw-r--r--spec/javascripts/environments/environments_app_spec.js14
-rw-r--r--spec/javascripts/filtered_search/dropdown_utils_spec.js2
-rw-r--r--spec/javascripts/filtered_search/filtered_search_token_keys_spec.js14
-rw-r--r--spec/javascripts/fixtures/groups.rb10
-rw-r--r--spec/javascripts/gl_dropdown_spec.js4
-rw-r--r--spec/javascripts/graphs/stat_graph_contributors_util_spec.js2
-rw-r--r--spec/javascripts/groups/components/group_item_spec.js2
-rw-r--r--spec/javascripts/groups/components/groups_spec.js2
-rw-r--r--spec/javascripts/groups/components/item_stats_spec.js10
-rw-r--r--spec/javascripts/groups/components/item_stats_value_spec.js4
-rw-r--r--spec/javascripts/groups/store/groups_store_spec.js12
-rw-r--r--spec/javascripts/image_diff/helpers/comment_indicator_helper_spec.js2
-rw-r--r--spec/javascripts/jobs/components/job_app_spec.js9
-rw-r--r--spec/javascripts/jobs/components/job_log_controllers_spec.js1
-rw-r--r--spec/javascripts/jobs/components/sidebar_spec.js4
-rw-r--r--spec/javascripts/jobs/components/stages_dropdown_spec.js20
-rw-r--r--spec/javascripts/jobs/store/actions_spec.js17
-rw-r--r--spec/javascripts/jobs/store/getters_spec.js10
-rw-r--r--spec/javascripts/jobs/store/mutations_spec.js27
-rw-r--r--spec/javascripts/lib/utils/common_utils_spec.js3
-rw-r--r--spec/javascripts/line_highlighter_spec.js18
-rw-r--r--spec/javascripts/new_branch_spec.js24
-rw-r--r--spec/javascripts/notes/components/note_form_spec.js1
-rw-r--r--spec/javascripts/notes_spec.js6
-rw-r--r--spec/javascripts/reports/components/report_section_spec.js1
-rw-r--r--spec/javascripts/right_sidebar_spec.js32
-rw-r--r--spec/javascripts/search_autocomplete_spec.js6
-rw-r--r--spec/javascripts/settings_panels_spec.js30
-rw-r--r--spec/javascripts/syntax_highlight_spec.js1
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_memory_usage_spec.js2
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js10
-rw-r--r--spec/javascripts/vue_shared/components/memory_graph_spec.js4
-rw-r--r--spec/lib/gitlab/bitbucket_import/project_creator_spec.rb4
-rw-r--r--spec/lib/gitlab/blob_helper_spec.rb125
-rw-r--r--spec/lib/gitlab/ci/status/pipeline/factory_spec.rb68
-rw-r--r--spec/lib/gitlab/conflict/file_spec.rb5
-rw-r--r--spec/lib/gitlab/file_detector_spec.rb4
-rw-r--r--spec/lib/gitlab/git/blob_snippet_spec.rb19
-rw-r--r--spec/lib/gitlab/gon_helper_spec.rb32
-rw-r--r--spec/lib/gitlab/language_data_spec.rb22
-rw-r--r--spec/models/deployment_spec.rb23
-rw-r--r--spec/models/project_spec.rb61
-rw-r--r--spec/models/repository_spec.rb25
-rw-r--r--spec/presenters/project_presenter_spec.rb31
-rw-r--r--spec/requests/api/repositories_spec.rb4
-rw-r--r--spec/requests/api/settings_spec.rb15
-rw-r--r--spec/routing/routing_spec.rb7
-rw-r--r--spec/rubocop/cop/qa/element_with_pattern_spec.rb50
-rw-r--r--spec/rubocop/qa_helpers_spec.rb37
-rw-r--r--spec/services/applications/create_service_spec.rb13
-rw-r--r--spec/services/clusters/applications/create_service_spec.rb71
-rw-r--r--spec/services/clusters/applications/schedule_installation_service_spec.rb7
-rw-r--r--spec/services/clusters/create_service_spec.rb2
-rw-r--r--spec/services/clusters/update_service_spec.rb2
-rw-r--r--spec/services/projects/destroy_service_spec.rb23
-rw-r--r--spec/services/projects/import_service_spec.rb2
-rw-r--r--spec/support/features/issuable_quick_actions_shared_examples.rb9
-rw-r--r--spec/support/helpers/test_request_helpers.rb11
-rw-r--r--spec/support/shared_examples/dirty_submit_form_shared_examples.rb24
-rwxr-xr-xvendor/languages.yml5488
-rw-r--r--yarn.lock8
542 files changed, 8993 insertions, 2431 deletions
diff --git a/.rubocop.yml b/.rubocop.yml
index 242e7615211..0f4018326a1 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -50,7 +50,8 @@ Style/FrozenStringLiteralComment:
- 'danger/**/*'
- 'db/**/*'
- 'ee/**/*'
- - 'lib/**/*'
+ - 'lib/gitlab/**/*'
+ - 'lib/tasks/**/*'
- 'qa/**/*'
- 'rubocop/**/*'
- 'scripts/**/*'
@@ -84,6 +85,7 @@ Naming/FileName:
- EE
- JSON
- LDAP
+ - SAML
- IO
- HMAC
- QA
diff --git a/CHANGELOG.md b/CHANGELOG.md
index dcc2c01931d..43691af1877 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,14 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
+## 11.3.5 (2018-10-15)
+
+### Fixed (2 changes)
+
+- Fix loading issue on some merge request discussion. !21982
+- Fix project deletion when there is a export available. !22276
+
+
## 11.3.3 (2018-10-04)
- No changes.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d2d385dff8f..b33ef79558e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -64,228 +64,56 @@ As of July 2018, all the documentation for contributing to the GitLab project ha
## Contribute to GitLab
-Thank you for your interest in contributing to GitLab. This guide details how
-to contribute to GitLab in a way that is easy for everyone.
-
-For a first-time step-by-step guide to the contribution process, please see
-["Contributing to GitLab"](https://about.gitlab.com/contributing/).
-
-Looking for something to work on? Look for issues in the [Backlog (Accepting merge requests) milestone](#i-want-to-contribute).
-
-GitLab comes in two flavors, GitLab Community Edition (CE) our free and open
-source edition, and GitLab Enterprise Edition (EE) which is our commercial
-edition. Throughout this guide you will see references to CE and EE for
-abbreviation.
-
-To get an overview of GitLab community membership including those that would be reviewing or merging your contributions, please visit [the community roles page](doc/development/contributing/community_roles.md).
-
-If you want to know how the GitLab [core team]
-operates please see [the GitLab contributing process](PROCESS.md).
-
-[GitLab Inc engineers should refer to the engineering workflow document](https://about.gitlab.com/handbook/engineering/workflow/)
+This [documentation](doc/development/contributing/index.md#contribute-to-gitlab) has been moved.
## Security vulnerability disclosure
-Please report suspected security vulnerabilities in private to
-`support@gitlab.com`, also see the
-[disclosure section on the GitLab.com website](https://about.gitlab.com/disclosure/).
-Please do **NOT** create publicly viewable issues for suspected security
-vulnerabilities.
+This [documentation](doc/development/contributing/index.md#security-vulnerability-disclosure) has been moved.
## Code of Conduct
-### Our Pledge
-
-In the interest of fostering an open and welcoming environment, we as
-contributors and maintainers pledge to making participation in our project and
-our community a harassment-free experience for everyone, regardless of age, body
-size, disability, ethnicity, sex characteristics, gender identity and expression,
-level of experience, education, socio-economic status, nationality, personal
-appearance, race, religion, or sexual identity and orientation.
-
-### Our Standards
-
-Examples of behavior that contributes to creating a positive environment
-include:
-
-* Using welcoming and inclusive language
-* Being respectful of differing viewpoints and experiences
-* Gracefully accepting constructive criticism
-* Focusing on what is best for the community
-* Showing empathy towards other community members
-
-Examples of unacceptable behavior by participants include:
-
-* The use of sexualized language or imagery and unwelcome sexual attention or
- advances
-* Trolling, insulting/derogatory comments, and personal or political attacks
-* Public or private harassment
-* Publishing others' private information, such as a physical or electronic
- address, without explicit permission
-* Other conduct which could reasonably be considered inappropriate in a
- professional setting
-
-### Our Responsibilities
-
-Project maintainers are responsible for clarifying the standards of acceptable
-behavior and are expected to take appropriate and fair corrective action in
-response to any instances of unacceptable behavior.
-
-Project maintainers have the right and responsibility to remove, edit, or
-reject comments, commits, code, wiki edits, issues, and other contributions
-that are not aligned to this Code of Conduct, or to ban temporarily or
-permanently any contributor for other behaviors that they deem inappropriate,
-threatening, offensive, or harmful.
-
-### Scope
-
-This Code of Conduct applies both within project spaces and in public spaces
-when an individual is representing the project or its community. Examples of
-representing a project or community include using an official project e-mail
-address, posting via an official social media account, or acting as an appointed
-representative at an online or offline event. Representation of a project may be
-further defined and clarified by project maintainers.
-
-### Enforcement
-
-Instances of abusive, harassing, or otherwise unacceptable behavior may be
-reported by contacting the project team at conduct@gitlab.com. All
-complaints will be reviewed and investigated and will result in a response that
-is deemed necessary and appropriate to the circumstances. The project team is
-obligated to maintain confidentiality with regard to the reporter of an incident.
-Further details of specific enforcement policies may be posted separately.
-
-Project maintainers who do not follow or enforce the Code of Conduct in good
-faith may face temporary or permanent repercussions as determined by other
-members of the project's leadership.
-
-### Attribution
-
-This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
-available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
-
-[homepage]: https://www.contributor-covenant.org
+This [documentation](doc/development/contributing/index.md#code-of-conduct) has been moved.
## Closing policy for issues and merge requests
-GitLab is a popular open source project and the capacity to deal with issues
-and merge requests is limited. Out of respect for our volunteers, issues and
-merge requests not in line with the guidelines listed in this document may be
-closed without notice.
-
-Please treat our volunteers with courtesy and respect, it will go a long way
-towards getting your issue resolved.
-
-Issues and merge requests should be in English and contain appropriate language
-for audiences of all ages.
-
-If a contributor is no longer actively working on a submitted merge request
-we can decide that the merge request will be finished by one of our
-[Merge request coaches][team] or close the merge request. We make this decision
-based on how important the change is for our product vision. If a Merge request
-coach is going to finish the merge request we assign the
-~"coach will finish" label.
+This [documentation](doc/development/contributing/index.md#closing-policy-for-issues-and-merge-requests) has been moved.
## Helping others
-Please help other GitLab users when you can.
-The methods people will use to seek help can be found on the [getting help page][getting-help].
-
-Sign up for the mailing list, answer GitLab questions on StackOverflow or
-respond in the IRC channel. You can also sign up on [CodeTriage][codetriage] to help with
-the remaining issues on the GitHub issue tracker.
+This [documentation](doc/development/contributing/index.md#helping-others) has been moved.
## I want to contribute!
-If you want to contribute to GitLab, [issues in the Backlog (Accepting merge requests)](https://gitlab.com/gitlab-org/gitlab-ce/issues?scope=all&utf8=✓&state=opened&assignee_id=0&milestone_title=Backlog%20(Accepting%20merge%20requests))
-are a great place to start. Issues with a lower weight (1 or 2) are deemed
-suitable for beginners. These issues will be of reasonable size and challenge,
-for anyone to start contributing to GitLab. If you have any questions or need help visit [Getting Help](https://about.gitlab.com/getting-help/#discussion) to
-learn how to communicate with GitLab. If you're looking for a Gitter or Slack channel
-please consider we favor
-[asynchronous communication](https://about.gitlab.com/handbook/communication/#internal-communication) over real time communication. Thanks for your contribution!
+This [documentation](doc/development/contributing/index.md#i-want-to-contribute) has been moved.
## Contribution Flow
-When contributing to GitLab, your merge request is subject to review by merge request maintainers of a particular specialty.
-
-When you submit code to GitLab, we really want it to get merged, but there will be times when it will not be merged.
-
-When maintainers are reading through a merge request they may request guidance from other maintainers. If merge request maintainers conclude that the code should not be merged, our reasons will be fully disclosed. If it has been decided that the code quality is not up to GitLab’s standards, the merge request maintainer will refer the author to our docs and code style guides, and provide some guidance.
-
-Sometimes style guides will be followed but the code will lack structural integrity, or the maintainer will have reservations about the code’s overall quality. When there is a reservation the maintainer will inform the author and provide some guidance. The author may then choose to update the merge request. Once the merge request has been updated and reassigned to the maintainer, they will review the code again. Once the code has been resubmitted any number of times, the maintainer may choose to close the merge request with a summary of why it will not be merged, as well as some guidance. If the merge request is closed the maintainer will be open to discussion as to how to improve the code so it can be approved in the future.
-
-GitLab will do its best to review community contributions as quickly as possible. Specially appointed developers review community contributions daily. You may take a look at the [team page](https://about.gitlab.com/team/) for the merge request coach who specializes in the type of code you have written and mention them in the merge request. For example, if you have written some JavaScript in your code then you should mention the frontend merge request coach. If your code has multiple disciplines you may mention multiple merge request coaches.
-
-GitLab receives a lot of community contributions, so if your code has not been reviewed within 4 days of its initial submission feel free to re-mention the appropriate merge request coach.
-
-When submitting code to GitLab, you may feel that your contribution requires the aid of an external library. If your code includes an external library please provide a link to the library, as well as reasons for including it.
-
-When your code contains more than 500 changes, any major breaking changes, or an external library, `@mention` a maintainer in the merge request. If you are not sure who to mention, the reviewer will add one early in the merge request process.
-
-[core team]: https://about.gitlab.com/core-team/
-[team]: https://about.gitlab.com/team/
-[getting-help]: https://about.gitlab.com/getting-help/
-[codetriage]: http://www.codetriage.com/gitlabhq/gitlabhq
-[accepting-mrs-weight]: https://gitlab.com/gitlab-org/gitlab-ce/issues?assignee_id=0&label_name[]=Accepting%20Merge%20Requests&sort=weight_asc
-[ce-tracker]: https://gitlab.com/gitlab-org/gitlab-ce/issues
-[ee-tracker]: https://gitlab.com/gitlab-org/gitlab-ee/issues
-[google-group]: https://groups.google.com/forum/#!forum/gitlabhq
-[stackoverflow]: https://stackoverflow.com/questions/tagged/gitlab
-[fpl]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=feature+proposal
-[accepting-mrs-ce]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=Accepting+Merge+Requests
-[accepting-mrs-ee]: https://gitlab.com/gitlab-org/gitlab-ee/issues?label_name=Accepting+Merge+Requests
-[gitlab-mr-tracker]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests
-[gdk]: https://gitlab.com/gitlab-org/gitlab-development-kit
-[git-squash]: https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits
-[closed-merge-requests]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests?assignee_id=&label_name=&milestone_id=&scope=&sort=&state=closed
-[definition-of-done]: http://guide.agilealliance.org/guide/definition-of-done.html
-[contributor-covenant]: http://contributor-covenant.org
-[rss-source]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#source-code-layout
-[rss-naming]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#naming
-[changelog]: doc/development/changelog.md "Generate a changelog entry"
-[doc-guidelines]: doc/development/documentation/index.md "Documentation guidelines"
-[js-styleguide]: doc/development/fe_guide/style_guide_js.md "JavaScript styleguide"
-[scss-styleguide]: doc/development/fe_guide/style_guide_scss.md "SCSS styleguide"
-[newlines-styleguide]: doc/development/newlines_styleguide.md "Newlines styleguide"
-[UX Guide for GitLab]: http://docs.gitlab.com/ce/development/ux_guide/
-[license-finder-doc]: doc/development/licensing.md
-[GitLab Inc engineering workflow]: https://about.gitlab.com/handbook/engineering/workflow/#labelling-issues
-[polling-etag]: https://docs.gitlab.com/ce/development/polling.html
-[testing]: doc/development/testing_guide/index.md
-[us-english]: https://en.wikipedia.org/wiki/American_English
-
+This [documentation](doc/development/contributing/index.md) has been moved.
## Workflow labels
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
### Type labels
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
### Subject labels
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
### Team labels
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
### Release Scoping labels
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
### Priority labels
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
### Severity labels
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
@@ -294,17 +122,14 @@ This [documentation](doc/development/contributing/issue_workflow.md) has been mo
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
### Label for community contributors
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
## Implement design & UI elements
This [documentation](doc/development/contributing/design.md) has been moved.
-
## Issue tracker
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
@@ -313,7 +138,6 @@ This [documentation](doc/development/contributing/issue_workflow.md) has been mo
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
### Feature proposals
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
@@ -322,32 +146,26 @@ This [documentation](doc/development/contributing/issue_workflow.md) has been mo
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
### Issue weight
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
### Regression issues
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
### Technical and UX debt
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
### Stewardship
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
## Merge requests
This [documentation](doc/development/contributing/merge_request_workflow.md) has been moved.
-
### Merge request guidelines
This [documentation](doc/development/contributing/merge_request_workflow.md) has been moved.
@@ -357,12 +175,10 @@ This [documentation](doc/development/contributing/merge_request_workflow.md) has
This [documentation](doc/development/contributing/merge_request_workflow.md) has been moved.
-
## Definition of done
This [documentation](doc/development/contributing/merge_request_workflow.md) has been moved.
-
## Style guides
This [documentation](doc/development/contributing/design.md) has been moved.
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index b1fa68e5df9..33e061fe7a0 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-0.125.0
+0.125.1
diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION
index 9084fa2f716..6085e946503 100644
--- a/GITLAB_PAGES_VERSION
+++ b/GITLAB_PAGES_VERSION
@@ -1 +1 @@
-1.1.0
+1.2.1
diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION
index d127a0ff9f1..9da0a092a0d 100644
--- a/GITLAB_SHELL_VERSION
+++ b/GITLAB_SHELL_VERSION
@@ -1 +1 @@
-8.3.3
+8.4.0 \ No newline at end of file
diff --git a/Gemfile b/Gemfile
index ecbfba0827d..6772abeb49d 100644
--- a/Gemfile
+++ b/Gemfile
@@ -83,9 +83,6 @@ gem 'net-ldap'
# Only used to compute wiki page slugs
gem 'gitlab-gollum-lib', '~> 4.2', require: false
-# Language detection
-gem 'github-linguist', '~> 5.3.3', require: 'linguist'
-
# API
gem 'grape', '~> 1.1'
gem 'grape-entity', '~> 0.7.1'
@@ -146,6 +143,7 @@ gem 'rouge', '~> 3.1'
gem 'truncato', '~> 0.7.9'
gem 'bootstrap_form', '~> 2.7.0'
gem 'nokogiri', '~> 1.8.2'
+gem 'escape_utils', '~> 1.1'
# Calendar rendering
gem 'icalendar'
diff --git a/Gemfile.lock b/Gemfile.lock
index f995d92abf0..bd95f417caa 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -277,11 +277,6 @@ GEM
gitaly-proto (0.118.1)
google-protobuf (~> 3.1)
grpc (~> 1.10)
- github-linguist (5.3.3)
- charlock_holmes (~> 0.7.5)
- escape_utils (~> 1.1.0)
- mime-types (>= 1.19)
- rugged (>= 0.25.1)
github-markup (1.7.0)
gitlab-flowdock-git-hook (1.0.1)
flowdock (~> 0.7)
@@ -1006,6 +1001,7 @@ DEPENDENCIES
ed25519 (~> 1.2)
email_reply_trimmer (~> 0.1)
email_spec (~> 2.2.0)
+ escape_utils (~> 1.1)
factory_bot_rails (~> 4.8.2)
faraday (~> 0.12)
fast_blank
@@ -1028,7 +1024,6 @@ DEPENDENCIES
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.3)
gitaly-proto (~> 0.118.1)
- github-linguist (~> 5.3.3)
github-markup (~> 1.7.0)
gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-gollum-lib (~> 4.2)
@@ -1187,4 +1182,4 @@ DEPENDENCIES
wikicloth (= 0.8.1)
BUNDLED WITH
- 1.16.4
+ 1.16.6
diff --git a/Gemfile.rails5.lock b/Gemfile.rails5.lock
index 52f9b0ccd55..8aebf78924f 100644
--- a/Gemfile.rails5.lock
+++ b/Gemfile.rails5.lock
@@ -280,11 +280,6 @@ GEM
gitaly-proto (0.118.1)
google-protobuf (~> 3.1)
grpc (~> 1.10)
- github-linguist (5.3.3)
- charlock_holmes (~> 0.7.5)
- escape_utils (~> 1.1.0)
- mime-types (>= 1.19)
- rugged (>= 0.25.1)
github-markup (1.7.0)
gitlab-flowdock-git-hook (1.0.1)
flowdock (~> 0.7)
@@ -1015,6 +1010,7 @@ DEPENDENCIES
ed25519 (~> 1.2)
email_reply_trimmer (~> 0.1)
email_spec (~> 2.2.0)
+ escape_utils (~> 1.1)
factory_bot_rails (~> 4.8.2)
faraday (~> 0.12)
fast_blank
@@ -1037,7 +1033,6 @@ DEPENDENCIES
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.3)
gitaly-proto (~> 0.118.1)
- github-linguist (~> 5.3.3)
github-markup (~> 1.7.0)
gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-gollum-lib (~> 4.2)
@@ -1196,4 +1191,4 @@ DEPENDENCIES
wikicloth (= 0.8.1)
BUNDLED WITH
- 1.16.4
+ 1.16.6
diff --git a/app/assets/images/koding-logo.svg b/app/assets/images/koding-logo.svg
deleted file mode 100644
index ad89d684d94..00000000000
--- a/app/assets/images/koding-logo.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 14">
- <g fill="#d6d7d9">
- <path d="M8.7 0L5.3.3l3.2 6.8-3.2 6.6 3.5.3L12 6.9z"/>
- <ellipse cx="1.7" cy="11.1" rx="1.7" ry="1.7"/>
- <ellipse cx="1.7" cy="5.6" rx="1.7" ry="1.7"/>
- </g>
-</svg> \ No newline at end of file
diff --git a/app/assets/javascripts/blob_edit/blob_bundle.js b/app/assets/javascripts/blob_edit/blob_bundle.js
index 4e4598870fa..3cc89ff1955 100644
--- a/app/assets/javascripts/blob_edit/blob_bundle.js
+++ b/app/assets/javascripts/blob_edit/blob_bundle.js
@@ -13,11 +13,11 @@ export default () => {
if (editBlobForm.length) {
const urlRoot = editBlobForm.data('relativeUrlRoot');
const assetsPath = editBlobForm.data('assetsPrefix');
- const blobLanguage = editBlobForm.data('blobLanguage');
+ const filePath = editBlobForm.data('blobFilename')
const currentAction = $('.js-file-title').data('currentAction');
const projectId = editBlobForm.data('project-id');
- new EditBlob(`${urlRoot}${assetsPath}`, blobLanguage, currentAction, projectId);
+ new EditBlob(`${urlRoot}${assetsPath}`, filePath, currentAction, projectId);
new NewCommitForm(editBlobForm);
}
diff --git a/app/assets/javascripts/blob_edit/edit_blob.js b/app/assets/javascripts/blob_edit/edit_blob.js
index ec2b130ab7d..6e19548eed2 100644
--- a/app/assets/javascripts/blob_edit/edit_blob.js
+++ b/app/assets/javascripts/blob_edit/edit_blob.js
@@ -5,6 +5,7 @@ import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash';
import { __ } from '~/locale';
import TemplateSelectorMediator from '../blob/file_template_mediator';
+import getModeByFileExtension from '~/lib/utils/ace_utils';
export default class EditBlob {
constructor(assetsPath, aceMode, currentAction, projectId) {
@@ -14,9 +15,10 @@ export default class EditBlob {
this.initFileSelectors(currentAction, projectId);
}
- configureAceEditor(aceMode, assetsPath) {
+ configureAceEditor(filePath, assetsPath) {
ace.config.set('modePath', `${assetsPath}/ace`);
ace.config.loadModule('ace/ext/searchbox');
+ ace.config.loadModule('ace/ext/modelist');
this.editor = ace.edit('editor');
@@ -25,8 +27,8 @@ export default class EditBlob {
this.editor.focus();
- if (aceMode) {
- this.editor.getSession().setMode(`ace/mode/${aceMode}`);
+ if (filePath) {
+ this.editor.getSession().setMode(getModeByFileExtension(filePath));
}
}
diff --git a/app/assets/javascripts/boards/components/issue_card_inner.vue b/app/assets/javascripts/boards/components/issue_card_inner.vue
index 28956c2f3c5..aa98f35786e 100644
--- a/app/assets/javascripts/boards/components/issue_card_inner.vue
+++ b/app/assets/javascripts/boards/components/issue_card_inner.vue
@@ -1,5 +1,6 @@
<script>
import $ from 'jquery';
+ import Icon from '~/vue_shared/components/icon.vue';
import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import eventHub from '../eventhub';
import tooltip from '../../vue_shared/directives/tooltip';
@@ -8,6 +9,7 @@
export default {
components: {
UserAvatarLink,
+ Icon,
},
directives: {
tooltip,
@@ -140,11 +142,11 @@
<div>
<div class="board-card-header">
<h4 class="board-card-title">
- <i
+ <icon
v-if="issue.confidential"
- class="fa fa-eye-slash confidential-icon"
- aria-hidden="true"
- ></i>
+ name="eye-slash"
+ class="confidential-icon"
+ />
<a
:href="issue.path"
:title="issue.title"
diff --git a/app/assets/javascripts/boards/components/modal/list.vue b/app/assets/javascripts/boards/components/modal/list.vue
index a58b5afe970..c93fd9f415c 100644
--- a/app/assets/javascripts/boards/components/modal/list.vue
+++ b/app/assets/javascripts/boards/components/modal/list.vue
@@ -1,4 +1,5 @@
<script>
+ import Icon from '~/vue_shared/components/icon.vue';
import bp from '../../../breakpoints';
import ModalStore from '../../stores/modal_store';
import IssueCardInner from '../issue_card_inner.vue';
@@ -6,6 +7,7 @@
export default {
components: {
IssueCardInner,
+ Icon,
},
props: {
issueLinkBase: {
@@ -147,13 +149,13 @@
:issue="issue"
:issue-link-base="issueLinkBase"
:root-path="rootPath"/>
- <span
+ <icon
v-if="issue.selected"
:aria-label="'Issue #' + issue.id + ' selected'"
+ name="mobile-issue-close"
aria-checked="true"
- class="issue-card-selected text-center">
- <i class="fa fa-check"></i>
- </span>
+ class="issue-card-selected text-center"
+ />
</div>
</div>
</div>
diff --git a/app/assets/javascripts/boards/components/modal/lists_dropdown.vue b/app/assets/javascripts/boards/components/modal/lists_dropdown.vue
index 4622fd28220..3baac08d411 100644
--- a/app/assets/javascripts/boards/components/modal/lists_dropdown.vue
+++ b/app/assets/javascripts/boards/components/modal/lists_dropdown.vue
@@ -1,11 +1,13 @@
<script>
import { Link } from '@gitlab-org/gitlab-ui';
+import Icon from '~/vue_shared/components/icon.vue';
import ModalStore from '../../stores/modal_store';
import boardsStore from '../../stores/boards_store';
export default {
components: {
'gl-link': Link,
+ Icon,
},
data() {
return {
@@ -35,7 +37,9 @@ export default {
class="dropdown-label-box">
</span>
{{ selected.title }}
- <i class="fa fa-chevron-down"></i>
+ <icon
+ name="chevron-down"
+ />
</button>
<div class="dropdown-menu dropdown-menu-selectable dropdown-menu-drop-up">
<ul>
diff --git a/app/assets/javascripts/boards/components/project_select.vue b/app/assets/javascripts/boards/components/project_select.vue
index d4676914e02..4e8fe16160a 100644
--- a/app/assets/javascripts/boards/components/project_select.vue
+++ b/app/assets/javascripts/boards/components/project_select.vue
@@ -1,11 +1,15 @@
<script>
import $ from 'jquery';
import _ from 'underscore';
+import Icon from '~/vue_shared/components/icon.vue';
import eventHub from '../eventhub';
import Api from '../../api';
export default {
name: 'BoardProjectSelect',
+ components: {
+ Icon,
+ },
props: {
groupId: {
type: Number,
@@ -78,11 +82,9 @@ export default {
aria-expanded="false"
>
{{ selectedProjectName }}
- <i
- class="fa fa-chevron-down"
- aria-hidden="true"
- >
- </i>
+ <icon
+ name="chevron-down"
+ />
</button>
<div class="dropdown-menu dropdown-menu-selectable dropdown-menu-full-width">
<div class="dropdown-title">
@@ -92,12 +94,11 @@ export default {
type="button"
class="dropdown-title-button dropdown-menu-close"
>
- <i
- aria-hidden="true"
+ <icon
+ name="merge-request-close-m"
data-hidden="true"
- class="fa fa-times dropdown-menu-close-icon"
- >
- </i>
+ class="dropdown-menu-close-icon"
+ />
</button>
</div>
<div class="dropdown-input">
@@ -106,12 +107,11 @@ export default {
type="search"
placeholder="Search projects"
/>
- <i
- aria-hidden="true"
+ <icon
+ name="search"
+ class="dropdown-input-search"
data-hidden="true"
- class="fa fa-search dropdown-input-search"
- >
- </i>
+ />
</div>
<div class="dropdown-content"></div>
<div class="dropdown-loading">
diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js
index 65e7cee7039..ebf76af5966 100644
--- a/app/assets/javascripts/clusters/clusters_bundle.js
+++ b/app/assets/javascripts/clusters/clusters_bundle.js
@@ -1,6 +1,6 @@
import Visibility from 'visibilityjs';
import Vue from 'vue';
-import PersistentUserCallout from '../persistent_user_callout';
+import initDismissableCallout from '~/dismissable_callout';
import { s__, sprintf } from '../locale';
import Flash from '../flash';
import Poll from '../lib/utils/poll';
@@ -62,7 +62,7 @@ export default class Clusters {
this.showTokenButton = document.querySelector('.js-show-cluster-token');
this.tokenField = document.querySelector('.js-cluster-token');
- Clusters.initDismissableCallout();
+ initDismissableCallout('.js-cluster-security-warning');
initSettingsPanels();
setupToggleButtons(document.querySelector('.js-cluster-enable-toggle-area'));
this.initApplications();
@@ -105,12 +105,6 @@ export default class Clusters {
});
}
- static initDismissableCallout() {
- const callout = document.querySelector('.js-cluster-security-warning');
-
- if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new
- }
-
addListeners() {
if (this.showTokenButton) this.showTokenButton.addEventListener('click', this.showToken);
eventHub.$on('installApplication', this.installApplication);
diff --git a/app/assets/javascripts/clusters/clusters_index.js b/app/assets/javascripts/clusters/clusters_index.js
index e32d507d1f7..789c8360124 100644
--- a/app/assets/javascripts/clusters/clusters_index.js
+++ b/app/assets/javascripts/clusters/clusters_index.js
@@ -1,15 +1,14 @@
import createFlash from '~/flash';
import { __ } from '~/locale';
import setupToggleButtons from '~/toggle_buttons';
-import PersistentUserCallout from '../persistent_user_callout';
+import initDismissableCallout from '~/dismissable_callout';
import ClustersService from './services/clusters_service';
export default () => {
const clusterList = document.querySelector('.js-clusters-list');
- const callout = document.querySelector('.gcp-signup-offer');
- if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new
+ initDismissableCallout('.gcp-signup-offer');
// The empty state won't have a clusterList
if (clusterList) {
diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue
index a1069985178..6e7b5eb5526 100644
--- a/app/assets/javascripts/clusters/components/applications.vue
+++ b/app/assets/javascripts/clusters/components/applications.vue
@@ -1,6 +1,6 @@
<script>
import _ from 'underscore';
-import helmInstallIllustration from '@gitlab-org/gitlab-svgs/illustrations/kubernetes-installation.svg';
+import helmInstallIllustration from '@gitlab-org/gitlab-svgs/dist/illustrations/kubernetes-installation.svg';
import elasticsearchLogo from 'images/cluster_app_logos/elasticsearch.png';
import gitlabLogo from 'images/cluster_app_logos/gitlab.png';
import helmLogo from 'images/cluster_app_logos/helm.png';
diff --git a/app/assets/javascripts/cycle_analytics/components/banner.vue b/app/assets/javascripts/cycle_analytics/components/banner.vue
index 410d4873e55..88570160f26 100644
--- a/app/assets/javascripts/cycle_analytics/components/banner.vue
+++ b/app/assets/javascripts/cycle_analytics/components/banner.vue
@@ -1,7 +1,11 @@
<script>
+ import Icon from '~/vue_shared/components/icon.vue';
import iconCycleAnalyticsSplash from 'icons/_icon_cycle_analytics_splash.svg';
export default {
+ components: {
+ Icon,
+ },
props: {
documentationLink: {
type: String,
@@ -28,10 +32,9 @@
type="button"
@click="dismissOverviewDialog"
>
- <i
- class="fa fa-times"
- aria-hidden="true">
- </i>
+ <icon
+ name="close"
+ />
</button>
<div
class="svg-container"
diff --git a/app/assets/javascripts/diffs/components/compare_versions_dropdown.vue b/app/assets/javascripts/diffs/components/compare_versions_dropdown.vue
index c3acc352d5e..f4b333f3700 100644
--- a/app/assets/javascripts/diffs/components/compare_versions_dropdown.vue
+++ b/app/assets/javascripts/diffs/components/compare_versions_dropdown.vue
@@ -115,7 +115,7 @@ export default {
<span>
{{ selectedVersionName }}
</span>
- <Icon
+ <icon
:size="12"
name="angle-down"
class="position-absolute"
diff --git a/app/assets/javascripts/diffs/components/diff_file_header.vue b/app/assets/javascripts/diffs/components/diff_file_header.vue
index 15b37243030..dcf1057eb84 100644
--- a/app/assets/javascripts/diffs/components/diff_file_header.vue
+++ b/app/assets/javascripts/diffs/components/diff_file_header.vue
@@ -20,6 +20,11 @@ export default {
Tooltip,
},
props: {
+ discussionPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
diffFile: {
type: Object,
required: true,
@@ -65,8 +70,7 @@ export default {
if (this.diffFile.submodule) {
return this.diffFile.submoduleTreeUrl || this.diffFile.submoduleLink;
}
-
- return `#${this.diffFile.fileHash}`;
+ return this.discussionPath;
},
filePath() {
if (this.diffFile.submodule) {
@@ -152,7 +156,7 @@ export default {
v-once
ref="titleWrapper"
:href="titleLink"
- class="append-right-4"
+ class="append-right-4 js-title-wrapper"
>
<file-icon
:file-name="filePath"
diff --git a/app/assets/javascripts/diffs/store/modules/diff_state.js b/app/assets/javascripts/diffs/store/modules/diff_state.js
index ae8930c8968..1c5c35071de 100644
--- a/app/assets/javascripts/diffs/store/modules/diff_state.js
+++ b/app/assets/javascripts/diffs/store/modules/diff_state.js
@@ -1,5 +1,6 @@
import Cookies from 'js-cookie';
import { getParameterValues } from '~/lib/utils/url_utility';
+import bp from '~/breakpoints';
import { INLINE_DIFF_VIEW_TYPE, DIFF_VIEW_COOKIE_NAME, MR_TREE_SHOW_KEY } from '../../constants';
const viewTypeFromQueryString = getParameterValues('view')[0];
@@ -20,6 +21,7 @@ export default () => ({
diffViewType: viewTypeFromQueryString || viewTypeFromCookie || defaultViewType,
tree: [],
treeEntries: {},
- showTreeList: storedTreeShow === null ? true : storedTreeShow === 'true',
+ showTreeList:
+ storedTreeShow === null ? bp.getBreakpointSize() !== 'xs' : storedTreeShow === 'true',
currentDiffFileId: '',
});
diff --git a/app/assets/javascripts/dirty_submit/dirty_submit_collection.js b/app/assets/javascripts/dirty_submit/dirty_submit_collection.js
new file mode 100644
index 00000000000..42b051b2270
--- /dev/null
+++ b/app/assets/javascripts/dirty_submit/dirty_submit_collection.js
@@ -0,0 +1,13 @@
+import DirtySubmitForm from './dirty_submit_form';
+
+class DirtySubmitCollection {
+ constructor(forms) {
+ this.forms = forms;
+
+ this.dirtySubmits = [];
+
+ this.forms.forEach(form => this.dirtySubmits.push(new DirtySubmitForm(form)));
+ }
+}
+
+export default DirtySubmitCollection;
diff --git a/app/assets/javascripts/dirty_submit/dirty_submit_factory.js b/app/assets/javascripts/dirty_submit/dirty_submit_factory.js
new file mode 100644
index 00000000000..95a896a7f0b
--- /dev/null
+++ b/app/assets/javascripts/dirty_submit/dirty_submit_factory.js
@@ -0,0 +1,9 @@
+import DirtySubmitCollection from './dirty_submit_collection';
+import DirtySubmitForm from './dirty_submit_form';
+
+export default function dirtySubmitFactory(formOrForms) {
+ const isCollection = formOrForms instanceof NodeList || formOrForms instanceof Array;
+ const DirtySubmitClass = isCollection ? DirtySubmitCollection : DirtySubmitForm;
+
+ return new DirtySubmitClass(formOrForms);
+}
diff --git a/app/assets/javascripts/dirty_submit/dirty_submit_form.js b/app/assets/javascripts/dirty_submit/dirty_submit_form.js
new file mode 100644
index 00000000000..5bea47f23c5
--- /dev/null
+++ b/app/assets/javascripts/dirty_submit/dirty_submit_form.js
@@ -0,0 +1,82 @@
+import _ from 'underscore';
+
+class DirtySubmitForm {
+ constructor(form) {
+ this.form = form;
+ this.dirtyInputs = [];
+ this.isDisabled = true;
+
+ this.init();
+ }
+
+ init() {
+ this.inputs = this.form.querySelectorAll('input, textarea, select');
+ this.submits = this.form.querySelectorAll('input[type=submit], button[type=submit]');
+
+ this.inputs.forEach(DirtySubmitForm.initInput);
+ this.toggleSubmission();
+
+ this.registerListeners();
+ }
+
+ registerListeners() {
+ const throttledUpdateDirtyInput = _.throttle(
+ event => this.updateDirtyInput(event),
+ DirtySubmitForm.THROTTLE_DURATION,
+ );
+ this.form.addEventListener('input', throttledUpdateDirtyInput);
+ this.form.addEventListener('submit', event => this.formSubmit(event));
+ }
+
+ updateDirtyInput(event) {
+ const input = event.target;
+
+ if (!input.dataset.dirtySubmitOriginalValue) return;
+
+ this.updateDirtyInputs(input);
+ this.toggleSubmission();
+ }
+
+ updateDirtyInputs(input) {
+ const { name } = input;
+ const isDirty =
+ input.dataset.dirtySubmitOriginalValue !== DirtySubmitForm.inputCurrentValue(input);
+ const indexOfInputName = this.dirtyInputs.indexOf(name);
+ const isExisting = indexOfInputName !== -1;
+
+ if (isDirty && !isExisting) this.dirtyInputs.push(name);
+ if (!isDirty && isExisting) this.dirtyInputs.splice(indexOfInputName, 1);
+ }
+
+ toggleSubmission() {
+ this.isDisabled = this.dirtyInputs.length === 0;
+ this.submits.forEach(element => {
+ element.disabled = this.isDisabled;
+ });
+ }
+
+ formSubmit(event) {
+ if (this.isDisabled) {
+ event.preventDefault();
+ event.stopImmediatePropagation();
+ }
+
+ return !this.isDisabled;
+ }
+
+ static initInput(element) {
+ element.dataset.dirtySubmitOriginalValue = DirtySubmitForm.inputCurrentValue(element);
+ }
+
+ static isInputCheckable(input) {
+ return input.type === 'checkbox' || input.type === 'radio';
+ }
+
+ static inputCurrentValue(input) {
+ return DirtySubmitForm.isInputCheckable(input) ? input.checked.toString() : input.value;
+ }
+}
+
+DirtySubmitForm.THROTTLE_DURATION = 500;
+
+export default DirtySubmitForm;
diff --git a/app/assets/javascripts/dismissable_callout.js b/app/assets/javascripts/dismissable_callout.js
new file mode 100644
index 00000000000..5185b019376
--- /dev/null
+++ b/app/assets/javascripts/dismissable_callout.js
@@ -0,0 +1,27 @@
+import $ from 'jquery';
+import axios from '~/lib/utils/axios_utils';
+import { __ } from '~/locale';
+import Flash from '~/flash';
+
+export default function initDismissableCallout(alertSelector) {
+ const alertEl = document.querySelector(alertSelector);
+ if (!alertEl) {
+ return;
+ }
+
+ const closeButtonEl = alertEl.getElementsByClassName('close')[0];
+ const { dismissEndpoint, featureId } = closeButtonEl.dataset;
+
+ closeButtonEl.addEventListener('click', () => {
+ axios
+ .post(dismissEndpoint, {
+ feature_name: featureId,
+ })
+ .then(() => {
+ $(alertEl).alert('close');
+ })
+ .catch(() => {
+ Flash(__('An error occurred while dismissing the alert. Refresh the page and try again.'));
+ });
+ });
+}
diff --git a/app/assets/javascripts/environments/components/environment_actions.vue b/app/assets/javascripts/environments/components/environment_actions.vue
index e1f9248bc4c..2bc168a6b02 100644
--- a/app/assets/javascripts/environments/components/environment_actions.vue
+++ b/app/assets/javascripts/environments/components/environment_actions.vue
@@ -60,11 +60,9 @@ export default {
>
<span>
<icon name="play" />
- <i
- class="fa fa-caret-down"
- aria-hidden="true"
- >
- </i>
+ <icon
+ name="chevron-down"
+ />
<gl-loading-icon v-if="isLoading" />
</span>
</button>
diff --git a/app/assets/javascripts/environments/components/environment_item.vue b/app/assets/javascripts/environments/components/environment_item.vue
index ad5d16874f3..bb9c139727e 100644
--- a/app/assets/javascripts/environments/components/environment_item.vue
+++ b/app/assets/javascripts/environments/components/environment_item.vue
@@ -4,6 +4,7 @@ import _ from 'underscore';
import tooltip from '~/vue_shared/directives/tooltip';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import { humanize } from '~/lib/utils/text_utility';
+import Icon from '~/vue_shared/components/icon.vue';
import ActionsComponent from './environment_actions.vue';
import ExternalUrlComponent from './environment_external_url.vue';
import StopComponent from './environment_stop.vue';
@@ -24,6 +25,7 @@ export default {
components: {
UserAvatarLink,
CommitComponent,
+ Icon,
ActionsComponent,
ExternalUrlComponent,
StopComponent,
@@ -448,6 +450,10 @@ export default {
this.canRetry
);
},
+
+ folderIconName() {
+ return this.model.isOpen ? 'chevron-down' : 'chevron-right';
+ },
},
methods: {
@@ -494,27 +500,15 @@ export default {
role="button"
@click="onClickFolder">
- <span class="folder-icon">
- <i
- v-show="model.isOpen"
- class="fa fa-caret-down"
- aria-hidden="true"
- >
- </i>
- <i
- v-show="!model.isOpen"
- class="fa fa-caret-right"
- aria-hidden="true"
- >
- </i>
- </span>
+ <icon
+ :name="folderIconName"
+ class="folder-icon"
+ />
- <span class="folder-icon">
- <i
- class="fa fa-folder"
- aria-hidden="true">
- </i>
- </span>
+ <icon
+ name="folder"
+ class="folder-icon"
+ />
<span>
{{ model.folderName }}
diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue b/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue
index a6a265eb3fd..14c223c61a4 100644
--- a/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue
+++ b/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue
@@ -1,10 +1,14 @@
<script>
import _ from 'underscore';
import { mapActions } from 'vuex';
+import Icon from '~/vue_shared/components/icon.vue';
import eventHub from '../event_hub';
import frequentItemsMixin from './frequent_items_mixin';
export default {
+ components: {
+ Icon,
+ },
mixins: [frequentItemsMixin],
data() {
return {
@@ -45,11 +49,10 @@ export default {
type="search"
class="form-control"
/>
- <i
+ <icon
v-if="!searchQuery"
- class="search-icon fa fa-fw fa-search"
- aria-hidden="true"
- >
- </i>
+ name="search"
+ class="search-icon"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/jobs/components/job_app.vue b/app/assets/javascripts/jobs/components/job_app.vue
index 047e55866ce..4e8d3ad24cc 100644
--- a/app/assets/javascripts/jobs/components/job_app.vue
+++ b/app/assets/javascripts/jobs/components/job_app.vue
@@ -18,7 +18,7 @@
StuckBlock,
},
props: {
- runnerHelpUrl: {
+ runnerSettingsUrl: {
type: String,
required: false,
default: null,
@@ -30,7 +30,7 @@
'headerActions',
'headerTime',
'shouldRenderCalloutMessage',
- 'jobHasStarted',
+ 'shouldRenderTriggeredLabel',
'hasEnvironment',
'isJobStuck',
'hasTrace',
@@ -58,7 +58,7 @@
:user="job.user"
:actions="headerActions"
:has-sidebar-button="true"
- :should-render-triggered-label="jobHasStarted"
+ :should-render-triggered-label="shouldRenderTriggeredLabel"
:item-name="__('Job')"
/>
</div>
@@ -76,7 +76,7 @@
class="js-job-stuck"
:has-no-runners-for-project="job.runners.available"
:tags="job.tags"
- :runners-path="runnerHelpUrl"
+ :runners-path="runnerSettingsUrl"
/>
<environments-block
@@ -87,8 +87,8 @@
/>
<erased-block
- v-if="job.erased"
- class="js-job-erased"
+ v-if="job.erased_at"
+ class="js-job-erased-block"
:user="job.erased_by"
:erased-at="job.erased_at"
/>
diff --git a/app/assets/javascripts/jobs/components/job_log_controllers.vue b/app/assets/javascripts/jobs/components/job_log_controllers.vue
index 35d40c6898e..cc885ea8e1b 100644
--- a/app/assets/javascripts/jobs/components/job_log_controllers.vue
+++ b/app/assets/javascripts/jobs/components/job_log_controllers.vue
@@ -65,7 +65,7 @@ export default {
};
</script>
<template>
- <div class="top-bar">
+ <div class="top-bar affix js-top-bar">
<!-- truncate information -->
<div class="js-truncated-info truncated-info d-none d-sm-block float-left">
<template v-if="isTraceSizeVisible">
diff --git a/app/assets/javascripts/jobs/components/sidebar.vue b/app/assets/javascripts/jobs/components/sidebar.vue
index 7f0f301d72a..8f3c6aced23 100644
--- a/app/assets/javascripts/jobs/components/sidebar.vue
+++ b/app/assets/javascripts/jobs/components/sidebar.vue
@@ -36,7 +36,7 @@ export default {
},
},
computed: {
- ...mapState(['job', 'isLoading', 'stages', 'jobs']),
+ ...mapState(['job', 'isLoading', 'stages', 'jobs', 'selectedStage']),
coverage() {
return `${this.job.coverage}%`;
},
@@ -110,7 +110,7 @@ export default {
</script>
<template>
<aside
- class="right-sidebar right-sidebar-expanded build-sidebar"
+ class="js-build-sidebar right-sidebar right-sidebar-expanded build-sidebar"
data-offset-top="101"
data-spy="affix"
>
@@ -276,6 +276,7 @@ export default {
<stages-dropdown
:stages="stages"
:pipeline="job.pipeline"
+ :selected-stage="selectedStage"
@requestSidebarStageDropdown="fetchJobsForStage"
/>
diff --git a/app/assets/javascripts/jobs/components/stages_dropdown.vue b/app/assets/javascripts/jobs/components/stages_dropdown.vue
index 34d47b3a3bb..e5e1d56e287 100644
--- a/app/assets/javascripts/jobs/components/stages_dropdown.vue
+++ b/app/assets/javascripts/jobs/components/stages_dropdown.vue
@@ -2,7 +2,6 @@
import _ from 'underscore';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import Icon from '~/vue_shared/components/icon.vue';
-import { __ } from '~/locale';
export default {
components: {
@@ -18,30 +17,20 @@ export default {
type: Array,
required: true,
},
+ selectedStage: {
+ type: String,
+ required: true,
+ },
},
- data() {
- return {
- selectedStage: this.stages.length > 0 ? this.stages[0].name : __('More'),
- };
- },
+
computed: {
hasRef() {
return !_.isEmpty(this.pipeline.ref);
},
},
- watch: {
- // When the component is initially mounted it may start with an empty stages array.
- // Once the prop is updated, we set the first stage as the selected one
- stages(newVal) {
- if (newVal.length) {
- this.selectedStage = newVal[0].name;
- }
- },
- },
methods: {
onStageClick(stage) {
this.$emit('requestSidebarStageDropdown', stage);
- this.selectedStage = stage.name;
},
},
};
diff --git a/app/assets/javascripts/jobs/job_details_bundle.js b/app/assets/javascripts/jobs/job_details_bundle.js
index 3eb75e72506..15cd79b1c50 100644
--- a/app/assets/javascripts/jobs/job_details_bundle.js
+++ b/app/assets/javascripts/jobs/job_details_bundle.js
@@ -9,8 +9,7 @@ import createStore from './store';
export default () => {
const { dataset } = document.getElementById('js-job-details-vue');
- // eslint-disable-next-line no-new
- new Job();
+
const store = createStore();
store.dispatch('setJobEndpoint', dataset.endpoint);
@@ -33,7 +32,7 @@ export default () => {
props: {
isLoading: this.isLoading,
job: this.job,
- runnerHelpUrl: dataset.runnerHelpUrl,
+ runnerSettingsUrl: dataset.runnerSettingsUrl,
},
});
},
@@ -71,4 +70,7 @@ export default () => {
});
},
});
+
+ // eslint-disable-next-line no-new
+ new Job();
};
diff --git a/app/assets/javascripts/jobs/store/actions.js b/app/assets/javascripts/jobs/store/actions.js
index 298367c9342..d0040161dc3 100644
--- a/app/assets/javascripts/jobs/store/actions.js
+++ b/app/assets/javascripts/jobs/store/actions.js
@@ -139,10 +139,12 @@ export const fetchStages = ({ state, dispatch }) => {
dispatch('requestStages');
axios
- .get(state.job.pipeline.path)
+ .get(`${state.job.pipeline.path}.json`)
.then(({ data }) => {
+ // Set selected stage
dispatch('receiveStagesSuccess', data.details.stages);
- dispatch('fetchJobsForStage', data.details.stages[0]);
+ const selectedStage = data.details.stages.find(stage => stage.name === state.selectedStage);
+ dispatch('fetchJobsForStage', selectedStage);
})
.catch(() => dispatch('receiveStagesError'));
};
@@ -156,11 +158,12 @@ export const receiveStagesError = ({ commit }) => {
/**
* Jobs list on sidebar - depend on stages dropdown
*/
-export const requestJobsForStage = ({ commit }) => commit(types.REQUEST_JOBS_FOR_STAGE);
+export const requestJobsForStage = ({ commit }, stage) =>
+ commit(types.REQUEST_JOBS_FOR_STAGE, stage);
// On stage click, set selected stage + fetch job
export const fetchJobsForStage = ({ dispatch }, stage) => {
- dispatch('requestJobsForStage');
+ dispatch('requestJobsForStage', stage);
axios
.get(stage.dropdown_path, {
diff --git a/app/assets/javascripts/jobs/store/getters.js b/app/assets/javascripts/jobs/store/getters.js
index afe5f88b292..9f4f372e3d2 100644
--- a/app/assets/javascripts/jobs/store/getters.js
+++ b/app/assets/javascripts/jobs/store/getters.js
@@ -22,10 +22,10 @@ export const shouldRenderCalloutMessage = state =>
!_.isEmpty(state.job.status) && !_.isEmpty(state.job.callout_message);
/**
- * When job has not started the key will be `false`
+ * When job has not started the key will be null
* When job started the key will be a string with a date.
*/
-export const jobHasStarted = state => !(state.job.started === false);
+export const shouldRenderTriggeredLabel = state => _.isString(state.job.started);
export const hasEnvironment = state => !_.isEmpty(state.job.deployment_status);
diff --git a/app/assets/javascripts/jobs/store/mutations.js b/app/assets/javascripts/jobs/store/mutations.js
index c3f2359fa4d..f00e06e1a6c 100644
--- a/app/assets/javascripts/jobs/store/mutations.js
+++ b/app/assets/javascripts/jobs/store/mutations.js
@@ -53,6 +53,16 @@ export default {
state.isLoading = false;
state.hasError = false;
state.job = job;
+
+ /**
+ * We only update it on the first request
+ * The dropdown can be changed by the user
+ * after the first request,
+ * and we do not want to hijack that
+ */
+ if (state.selectedStage === 'More' && job.stage) {
+ state.selectedStage = job.stage;
+ }
},
[types.RECEIVE_JOB_ERROR](state) {
state.isLoading = false;
@@ -81,8 +91,9 @@ export default {
state.stages = [];
},
- [types.REQUEST_JOBS_FOR_STAGE](state) {
+ [types.REQUEST_JOBS_FOR_STAGE](state, stage) {
state.isLoadingJobs = true;
+ state.selectedStage = stage.name;
},
[types.RECEIVE_JOBS_FOR_STAGE_SUCCESS](state, jobs) {
state.isLoadingJobs = false;
diff --git a/app/assets/javascripts/jobs/store/state.js b/app/assets/javascripts/jobs/store/state.js
index 509cb69a5d3..afbc959bb71 100644
--- a/app/assets/javascripts/jobs/store/state.js
+++ b/app/assets/javascripts/jobs/store/state.js
@@ -1,3 +1,5 @@
+import { __ } from '~/locale';
+
export default () => ({
jobEndpoint: null,
traceEndpoint: null,
@@ -34,7 +36,7 @@ export default () => ({
// sidebar dropdown
isLoadingStages: false,
isLoadingJobs: false,
- selectedStage: null,
+ selectedStage: __('More'),
stages: [],
jobs: [],
});
diff --git a/app/assets/javascripts/lib/ace.js b/app/assets/javascripts/lib/ace.js
index 9cdc0309503..e90b3d2eec7 100644
--- a/app/assets/javascripts/lib/ace.js
+++ b/app/assets/javascripts/lib/ace.js
@@ -1,3 +1,4 @@
/*= require ace/ace */
+/*= require ace/ext-modelist */
/*= require ace/ext-searchbox */
/*= require ./ace/ace_config_paths */
diff --git a/app/assets/javascripts/lib/utils/ace_utils.js b/app/assets/javascripts/lib/utils/ace_utils.js
new file mode 100644
index 00000000000..efc4b2a8d94
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/ace_utils.js
@@ -0,0 +1,6 @@
+/* global ace */
+
+export default function getModeByFileExtension(path) {
+ const modelist = ace.require("ace/ext/modelist");
+ return modelist.getModeForPath(path).mode;
+};
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index e8aac51a299..a88b575ad99 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -202,7 +202,6 @@ document.addEventListener('DOMContentLoaded', () => {
$('.navbar-toggler').on('click', () => {
$('.header-content').toggleClass('menu-expanded');
- gl.lazyLoader.loadCheck();
});
// Show/hide comments on diff
diff --git a/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js b/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js
index 425b806e9d6..a62ebe23646 100644
--- a/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js
+++ b/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js
@@ -5,6 +5,7 @@ import Vue from 'vue';
import axios from '~/lib/utils/axios_utils';
import flash from '~/flash';
import { __ } from '~/locale';
+import getModeByFileExtension from '~/lib/utils/ace_utils';
(global => {
global.mergeConflicts = global.mergeConflicts || {};
@@ -72,7 +73,7 @@ import { __ } from '~/locale';
this.fileLoaded = true;
this.editor = ace.edit(content);
this.editor.$blockScrolling = Infinity; // Turn off annoying warning
- this.editor.getSession().setMode(`ace/mode/${data.blob_ace_mode}`);
+ this.editor.getSession().setMode(getModeByFileExtension(data.new_path));
this.editor.on('change', () => {
this.saveDiffResolution();
});
diff --git a/app/assets/javascripts/notes/components/diff_with_note.vue b/app/assets/javascripts/notes/components/diff_with_note.vue
index 353aa790743..d9e99603238 100644
--- a/app/assets/javascripts/notes/components/diff_with_note.vue
+++ b/app/assets/javascripts/notes/components/diff_with_note.vue
@@ -94,6 +94,7 @@ export default {
class="diff-file file-holder"
>
<diff-file-header
+ :discussion-path="discussion.discussionPath"
:diff-file="diffFile"
:can-current-user-fork="false"
:discussions-expanded="isDiscussionsExpanded"
diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue
index 33998394a69..38c43e5fe08 100644
--- a/app/assets/javascripts/notes/components/note_form.vue
+++ b/app/assets/javascripts/notes/components/note_form.vue
@@ -102,6 +102,18 @@ export default {
},
methods: {
...mapActions(['toggleResolveNote']),
+ shouldToggleResolved(shouldResolve, beforeSubmitDiscussionState) {
+ // shouldBeResolved() checks the actual resolution state,
+ // considering batchComments (EEP), if applicable/enabled.
+ const newResolvedStateAfterUpdate =
+ this.shouldBeResolved && this.shouldBeResolved(shouldResolve);
+
+ const shouldToggleState =
+ newResolvedStateAfterUpdate !== undefined &&
+ beforeSubmitDiscussionState !== newResolvedStateAfterUpdate;
+
+ return shouldResolve || shouldToggleState;
+ },
handleUpdate(shouldResolve) {
const beforeSubmitDiscussionState = this.discussionResolved;
this.isSubmitting = true;
@@ -109,7 +121,7 @@ export default {
this.$emit('handleFormUpdate', this.updatedNoteBody, this.$refs.editNoteForm, () => {
this.isSubmitting = false;
- if (shouldResolve) {
+ if (this.shouldToggleResolved(shouldResolve, beforeSubmitDiscussionState)) {
this.resolveHandler(beforeSubmitDiscussionState);
}
});
diff --git a/app/assets/javascripts/pages/groups/edit/index.js b/app/assets/javascripts/pages/groups/edit/index.js
index 002b2279fcc..d0bce857029 100644
--- a/app/assets/javascripts/pages/groups/edit/index.js
+++ b/app/assets/javascripts/pages/groups/edit/index.js
@@ -2,6 +2,7 @@ import groupAvatar from '~/group_avatar';
import TransferDropdown from '~/groups/transfer_dropdown';
import initConfirmDangerModal from '~/confirm_danger_modal';
import initSettingsPanels from '~/settings_panels';
+import dirtySubmitFactory from '~/dirty_submit/dirty_submit_factory';
import mountBadgeSettings from '~/pages/shared/mount_badge_settings';
import { GROUP_BADGE } from '~/badges/constants';
@@ -10,5 +11,8 @@ document.addEventListener('DOMContentLoaded', () => {
new TransferDropdown(); // eslint-disable-line no-new
initConfirmDangerModal();
initSettingsPanels();
+ dirtySubmitFactory(
+ document.querySelectorAll('.js-general-settings-form, .js-general-permissions-form'),
+ );
mountBadgeSettings(GROUP_BADGE);
});
diff --git a/app/assets/javascripts/pages/projects/index.js b/app/assets/javascripts/pages/projects/index.js
index b0345b4e50d..5659e13981a 100644
--- a/app/assets/javascripts/pages/projects/index.js
+++ b/app/assets/javascripts/pages/projects/index.js
@@ -1,5 +1,5 @@
+import initDismissableCallout from '~/dismissable_callout';
import initGkeDropdowns from '~/projects/gke_cluster_dropdowns';
-import PersistentUserCallout from '../../persistent_user_callout';
import Project from './project';
import ShortcutsNavigation from '../../behaviors/shortcuts/shortcuts_navigation';
@@ -12,9 +12,7 @@ document.addEventListener('DOMContentLoaded', () => {
];
if (newClusterViews.indexOf(page) > -1) {
- const callout = document.querySelector('.gcp-signup-offer');
- if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new
-
+ initDismissableCallout('.gcp-signup-offer');
initGkeDropdowns();
}
diff --git a/app/assets/javascripts/pages/root/index.js b/app/assets/javascripts/pages/root/index.js
deleted file mode 100644
index 09f8185d3b5..00000000000
--- a/app/assets/javascripts/pages/root/index.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// if the "projects dashboard" is a user's default dashboard, when they visit the
-// instance root index, the dashboard will be served by the root controller instead
-// of a dashboard controller. The root index redirects for all other default dashboards.
-
-import '../dashboard/projects/index';
diff --git a/app/assets/javascripts/pages/users/user_overview_block.js b/app/assets/javascripts/pages/users/user_overview_block.js
index 0009419cd0c..2ed177be558 100644
--- a/app/assets/javascripts/pages/users/user_overview_block.js
+++ b/app/assets/javascripts/pages/users/user_overview_block.js
@@ -1,10 +1,15 @@
import axios from '~/lib/utils/axios_utils';
+const DEFAULT_LIMIT = 20;
+
export default class UserOverviewBlock {
constructor(options = {}) {
this.container = options.container;
this.url = options.url;
- this.limit = options.limit || 20;
+ this.requestParams = {
+ limit: DEFAULT_LIMIT,
+ ...options.requestParams,
+ };
this.loadData();
}
@@ -15,9 +20,7 @@ export default class UserOverviewBlock {
axios
.get(this.url, {
- params: {
- limit: this.limit,
- },
+ params: this.requestParams,
})
.then(({ data }) => this.render(data))
.catch(() => loadingEl.classList.add('hide'));
@@ -34,7 +37,9 @@ export default class UserOverviewBlock {
if (count && count > 0) {
document.querySelector(`${this.container} .js-view-all`).classList.remove('hide');
} else {
- document.querySelector(`${this.container} .nothing-here-block`).classList.add('text-left', 'p-0');
+ document
+ .querySelector(`${this.container} .nothing-here-block`)
+ .classList.add('text-left', 'p-0');
}
loadingEl.classList.add('hide');
diff --git a/app/assets/javascripts/pages/users/user_tabs.js b/app/assets/javascripts/pages/users/user_tabs.js
index 23b0348a99f..1de9945baad 100644
--- a/app/assets/javascripts/pages/users/user_tabs.js
+++ b/app/assets/javascripts/pages/users/user_tabs.js
@@ -182,18 +182,22 @@ export default class UserTabs {
this.loadActivityCalendar('overview');
- UserTabs.renderMostRecentBlocks('#js-overview .activities-block', 5);
- UserTabs.renderMostRecentBlocks('#js-overview .projects-block', 10);
+ UserTabs.renderMostRecentBlocks('#js-overview .activities-block', {
+ requestParams: { limit: 5 },
+ });
+ UserTabs.renderMostRecentBlocks('#js-overview .projects-block', {
+ requestParams: { limit: 10, skip_pagination: true },
+ });
this.loaded.overview = true;
}
- static renderMostRecentBlocks(container, limit) {
+ static renderMostRecentBlocks(container, options) {
// eslint-disable-next-line no-new
new UserOverviewBlock({
container,
url: $(`${container} .overview-content-list`).data('href'),
- limit,
+ ...options,
});
}
@@ -216,7 +220,12 @@ export default class UserTabs {
let calendarHint = '';
if (action === 'activity') {
- calendarHint = sprintf(__('Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})'), { utcFormatted });
+ calendarHint = sprintf(
+ __(
+ 'Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})',
+ ),
+ { utcFormatted },
+ );
} else if (action === 'overview') {
calendarHint = __('Issues, merge requests, pushes and comments.');
}
@@ -224,7 +233,15 @@ export default class UserTabs {
$calendarWrap.find('.calendar-hint').text(calendarHint);
// eslint-disable-next-line no-new
- new ActivityCalendar('.tab-pane.active .js-contrib-calendar', '.tab-pane.active .user-calendar-activities', data, calendarActivitiesPath, utcOffset, 0, monthsAgo);
+ new ActivityCalendar(
+ '.tab-pane.active .js-contrib-calendar',
+ '.tab-pane.active .user-calendar-activities',
+ data,
+ calendarActivitiesPath,
+ utcOffset,
+ 0,
+ monthsAgo,
+ );
})
.catch(() => flash(__('There was an error loading users activity calendar.')));
}
diff --git a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
index 1522e2227e4..300d453c174 100644
--- a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
+++ b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
@@ -1,5 +1,6 @@
<script>
import $ from 'jquery';
+import { glEmojiTag } from '~/emoji';
import detailedMetric from './detailed_metric.vue';
import requestSelector from './request_selector.vue';
@@ -64,6 +65,16 @@ export default {
lineProfileModal() {
return $('#modal-peek-line-profile');
},
+ hasHost() {
+ return this.currentRequest && this.currentRequest.details && this.currentRequest.details.host;
+ },
+ birdEmoji() {
+ if (this.hasHost && this.currentRequest.details.host.canary) {
+ return glEmojiTag('baby_chick');
+ }
+
+ return '';
+ },
},
mounted() {
this.currentRequest = this.requestId;
@@ -93,9 +104,11 @@ export default {
class="view"
>
<span
- v-if="currentRequest.details"
+ v-if="hasHost"
class="current-host"
+ :class="{ 'canary' : currentRequest.details.host.canary }"
>
+ <span v-html="birdEmoji"></span>
{{ currentRequest.details.host.hostname }}
</span>
</div>
diff --git a/app/assets/javascripts/persistent_user_callout.js b/app/assets/javascripts/persistent_user_callout.js
deleted file mode 100644
index 1e34e74a152..00000000000
--- a/app/assets/javascripts/persistent_user_callout.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import axios from './lib/utils/axios_utils';
-import { __ } from './locale';
-import Flash from './flash';
-
-export default class PersistentUserCallout {
- constructor(container) {
- const { dismissEndpoint, featureId } = container.dataset;
- this.container = container;
- this.dismissEndpoint = dismissEndpoint;
- this.featureId = featureId;
-
- this.init();
- }
-
- init() {
- const closeButton = this.container.querySelector('.js-close');
- closeButton.addEventListener('click', event => this.dismiss(event));
- }
-
- dismiss(event) {
- event.preventDefault();
-
- axios
- .post(this.dismissEndpoint, {
- feature_name: this.featureId,
- })
- .then(() => {
- this.container.remove();
- })
- .catch(() => {
- Flash(__('An error occurred while dismissing the alert. Refresh the page and try again.'));
- });
- }
-}
diff --git a/app/assets/javascripts/right_sidebar.js b/app/assets/javascripts/right_sidebar.js
index 64f3dde5be7..6b3753f7966 100644
--- a/app/assets/javascripts/right_sidebar.js
+++ b/app/assets/javascripts/right_sidebar.js
@@ -57,8 +57,6 @@ Sidebar.prototype.sidebarToggleClicked = function (e, triggered) {
$allGutterToggleIcons.removeClass('fa-angle-double-left').addClass('fa-angle-double-right');
$('aside.right-sidebar').removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded');
$('.layout-page').removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded');
-
- if (gl.lazyLoader) gl.lazyLoader.loadCheck();
}
$this.attr('data-original-title', tooltipLabel);
diff --git a/app/assets/javascripts/settings_panels.js b/app/assets/javascripts/settings_panels.js
index 37b4a2a4c63..b38421bdf1c 100644
--- a/app/assets/javascripts/settings_panels.js
+++ b/app/assets/javascripts/settings_panels.js
@@ -1,7 +1,8 @@
import $ from 'jquery';
+import { __ } from './locale';
function expandSection($section) {
- $section.find('.js-settings-toggle').text('Collapse');
+ $section.find('.js-settings-toggle:not(.js-settings-toggle-trigger-only)').text(__('Collapse'));
$section.find('.settings-content').off('scroll.expandSection').scrollTop(0);
$section.addClass('expanded');
if (!$section.hasClass('no-animate')) {
@@ -11,7 +12,7 @@ function expandSection($section) {
}
function closeSection($section) {
- $section.find('.js-settings-toggle').text('Expand');
+ $section.find('.js-settings-toggle:not(.js-settings-toggle-trigger-only)').text(__('Expand'));
$section.find('.settings-content').on('scroll.expandSection', () => expandSection($section));
$section.removeClass('expanded');
if (!$section.hasClass('no-animate')) {
diff --git a/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue b/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue
index ab7fab7e5ca..cdff4105335 100644
--- a/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue
+++ b/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue
@@ -102,7 +102,6 @@ export default {
>
<icon
:name="lockIcon"
- aria-hidden="true"
class="sidebar-item-icon is-active"
/>
</div>
@@ -134,7 +133,6 @@ export default {
<icon
:size="16"
name="lock"
- aria-hidden="true"
class="sidebar-item-icon inline is-active"
/>
{{ __('Locked') }}
@@ -147,7 +145,6 @@ export default {
<icon
:size="16"
name="lock-open"
- aria-hidden="true"
class="sidebar-item-icon inline"
/>
{{ __('Unlocked') }}
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
index 8184ef33022..c19b67f00fa 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
@@ -162,18 +162,20 @@
<span class="label-branch">
<a :href="mr.targetBranchPath">{{ mr.targetBranch }}</a>
</span>
- with
- <a
- :href="mr.mergeCommitPath"
- class="commit-sha js-mr-merged-commit-sha"
- v-text="mr.shortMergeCommitSha"
- >
- </a>
- <clipboard-button
- :title="__('Copy commit SHA to clipboard')"
- :text="mr.mergeCommitSha"
- css-class="btn-default btn-transparent btn-clipboard js-mr-merged-copy-sha"
- />
+ <template v-if="mr.mergeCommitSha">
+ with
+ <a
+ :href="mr.mergeCommitPath"
+ class="commit-sha js-mr-merged-commit-sha"
+ v-text="mr.shortMergeCommitSha"
+ >
+ </a>
+ <clipboard-button
+ :title="__('Copy commit SHA to clipboard')"
+ :text="mr.mergeCommitSha"
+ css-class="btn-default btn-transparent btn-clipboard js-mr-merged-copy-sha"
+ />
+ </template>
</p>
<p v-if="mr.sourceBranchRemoved">
{{ s__("mrWidget|The source branch has been removed") }}
diff --git a/app/assets/javascripts/vue_shared/components/icon.vue b/app/assets/javascripts/vue_shared/components/icon.vue
index 5e0e7315e99..fc80e89d505 100644
--- a/app/assets/javascripts/vue_shared/components/icon.vue
+++ b/app/assets/javascripts/vue_shared/components/icon.vue
@@ -105,6 +105,7 @@ export default {
:x="x"
:y="y"
:tabindex="tabIndex"
+ aria-hidden="true"
>
<use v-bind="{ 'xlink:href':spriteHref }"/>
</svg>
diff --git a/app/assets/javascripts/vue_shared/components/issue/issue_warning.vue b/app/assets/javascripts/vue_shared/components/issue/issue_warning.vue
index ca8ce554588..62f1ab27c1e 100644
--- a/app/assets/javascripts/vue_shared/components/issue/issue_warning.vue
+++ b/app/assets/javascripts/vue_shared/components/issue/issue_warning.vue
@@ -37,7 +37,6 @@
:name="warningIcon"
:size="16"
class="icon inline"
- aria-hidden="true"
/>
<span v-if="isLockedAndConfidential">
diff --git a/app/assets/javascripts/vue_shared/components/notes/system_note.vue b/app/assets/javascripts/vue_shared/components/notes/system_note.vue
index 2122d0a508e..de3c7a80365 100644
--- a/app/assets/javascripts/vue_shared/components/notes/system_note.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/system_note.vue
@@ -109,7 +109,7 @@ export default {
class="system-note-commit-list-toggler flex-row"
@click="expanded = !expanded"
>
- <Icon
+ <icon
:name="toggleIcon"
:size="8"
class="append-right-5"
diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss
index 7145a76db6d..f26b1fddae5 100644
--- a/app/assets/stylesheets/framework/blocks.scss
+++ b/app/assets/stylesheets/framework/blocks.scss
@@ -283,18 +283,20 @@
.dismiss-button {
position: absolute;
- right: 6px;
- top: 6px;
+ right: $gl-padding-8;
+ top: $gl-padding-8;
cursor: pointer;
- color: $blue-300;
+ color: $blue-500;
z-index: 1;
border: 0;
background-color: transparent;
+ padding: $gl-padding-8;
+ line-height: 0;
&:hover,
&:focus {
border: 0;
- color: $blue-400;
+ color: $blue-700;
}
}
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index 8603714f709..cdfad30e7ca 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -144,6 +144,13 @@
top: 11px;
right: 8px;
}
+
+ .ic-chevron-down {
+ position: absolute;
+ top: $gl-padding-8;
+ right: $gl-padding-8;
+ color: $gray-darkest;
+ }
}
@mixin dropdown-item-hover {
@@ -561,6 +568,10 @@
top: -1px;
}
+.dropdown-menu-close-icon {
+ vertical-align: middle;
+}
+
.dropdown-menu-back {
left: 7px;
top: 2px;
@@ -572,9 +583,10 @@
padding: 0 10px;
.fa,
- .input-icon {
+ .input-icon,
+ .ic-search {
position: absolute;
- top: 10px;
+ top: $gl-padding-8;
right: 20px;
color: $dropdown-input-fa-color;
font-size: 12px;
diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss
index be41dbfc61f..1c84baf68ed 100644
--- a/app/assets/stylesheets/framework/mixins.scss
+++ b/app/assets/stylesheets/framework/mixins.scss
@@ -12,6 +12,15 @@
max-width: $max-width;
}
+/**
+ * Mixin for fixed width container
+ */
+@mixin fixed-width-container {
+ max-width: $limited-layout-width - ($gl-padding * 2);
+ margin-left: auto;
+ margin-right: auto;
+}
+
/*
* Mixin for markdown tables
*/
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index b7a95f604b8..0fde6e18cc7 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -605,6 +605,7 @@ $perf-bar-development: #4c1210;
$perf-bar-bucket-bg: #111;
$perf-bar-bucket-box-shadow-from: rgba($white-light, 0.2);
$perf-bar-bucket-box-shadow-to: rgba($black, 0.25);
+$perf-bar-canary-text: $orange-400;
/*
Issuable warning
diff --git a/app/assets/stylesheets/pages/boards.scss b/app/assets/stylesheets/pages/boards.scss
index b3c5c693824..54fbd40cece 100644
--- a/app/assets/stylesheets/pages/boards.scss
+++ b/app/assets/stylesheets/pages/boards.scss
@@ -305,8 +305,7 @@
}
.confidential-icon {
- position: relative;
- top: 1px;
+ vertical-align: text-top;
margin-right: 5px;
}
}
diff --git a/app/assets/stylesheets/pages/cycle_analytics.scss b/app/assets/stylesheets/pages/cycle_analytics.scss
index f0228768b5a..ec2108b15be 100644
--- a/app/assets/stylesheets/pages/cycle_analytics.scss
+++ b/app/assets/stylesheets/pages/cycle_analytics.scss
@@ -21,7 +21,7 @@
}
}
- svg {
+ .svg-container svg {
width: 136px;
height: 136px;
}
diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss
index 17b02c6e31e..cba5324ce53 100644
--- a/app/assets/stylesheets/pages/diff.scss
+++ b/app/assets/stylesheets/pages/diff.scss
@@ -1046,3 +1046,19 @@
left: auto;
line-height: 0;
}
+
+@media (max-width: map-get($grid-breakpoints, md)-1) {
+ .diffs .files {
+ @include fixed-width-container;
+ flex-direction: column;
+
+ .diff-tree-list {
+ width: 100%;
+ }
+
+ .tree-list-holder {
+ max-height: calc(50px + 50vh);
+ padding-right: 0;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss
index 79984c1a546..19a36061c45 100644
--- a/app/assets/stylesheets/pages/environments.scss
+++ b/app/assets/stylesheets/pages/environments.scss
@@ -90,6 +90,7 @@
margin-right: 3px;
color: $gl-text-color-secondary;
display: inline-block;
+ vertical-align: text-top;
.fa:nth-child(1) {
margin-right: 3px;
diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss
index fe792a53b44..f0cb81e0bc3 100644
--- a/app/assets/stylesheets/pages/groups.scss
+++ b/app/assets/stylesheets/pages/groups.scss
@@ -191,7 +191,7 @@
}
}
- svg {
+ .svg-container svg {
width: 62px;
height: 50px;
}
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 62a9f97caa9..00b06aea898 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -1,8 +1,6 @@
// Limit MR description for side-by-side diff view
.fixed-width-container {
- max-width: $limited-layout-width - ($gl-padding * 2);
- margin-left: auto;
- margin-right: auto;
+ @include fixed-width-container;
}
.issuable-warning-icon {
diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss
index dbf8692d69b..ccfa4e00a5b 100644
--- a/app/assets/stylesheets/pages/settings.scss
+++ b/app/assets/stylesheets/pages/settings.scss
@@ -42,6 +42,10 @@
margin-top: 0;
}
+ .settings-title {
+ cursor: pointer;
+ }
+
button {
position: absolute;
top: 20px;
diff --git a/app/assets/stylesheets/performance_bar.scss b/app/assets/stylesheets/performance_bar.scss
index 59fdbf31fe9..9c01a2f8bda 100644
--- a/app/assets/stylesheets/performance_bar.scss
+++ b/app/assets/stylesheets/performance_bar.scss
@@ -68,6 +68,10 @@
}
}
+ .current-host.canary {
+ color: $perf-bar-canary-text;
+ }
+
strong {
color: $white-light;
}
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index bbeaeb7694e..eeabcc0c9bb 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -12,7 +12,9 @@ class ApplicationController < ActionController::Base
include WorkhorseHelper
include EnforcesTwoFactorAuthentication
include WithPerformanceBar
- include InvalidUTF8ErrorHandler
+ # this can be removed after switching to rails 5
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/51908
+ include InvalidUTF8ErrorHandler unless Gitlab.rails5?
before_action :authenticate_sessionless_user!
before_action :authenticate_user!
diff --git a/app/controllers/koding_controller.rb b/app/controllers/koding_controller.rb
deleted file mode 100644
index 72aa9d4f17f..00000000000
--- a/app/controllers/koding_controller.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class KodingController < ApplicationController
- before_action :check_integration!
- layout 'koding'
-
- def index
- path = File.join(Rails.root, 'doc/user/project/koding.md')
- @markdown = File.read(path)
- end
-
- private
-
- def check_integration!
- render_404 unless Gitlab::CurrentSettings.koding_enabled?
- end
-end
diff --git a/app/controllers/projects/clusters/applications_controller.rb b/app/controllers/projects/clusters/applications_controller.rb
index c356f8d2987..bcea96bce94 100644
--- a/app/controllers/projects/clusters/applications_controller.rb
+++ b/app/controllers/projects/clusters/applications_controller.rb
@@ -2,31 +2,20 @@
class Projects::Clusters::ApplicationsController < Projects::ApplicationController
before_action :cluster
- before_action :application_class, only: [:create]
before_action :authorize_read_cluster!
before_action :authorize_create_cluster!, only: [:create]
- # rubocop: disable CodeReuse/ActiveRecord
def create
- application = @application_class.find_or_initialize_by(cluster: @cluster)
-
- if application.has_attribute?(:hostname)
- application.hostname = params[:hostname]
- end
-
- if application.respond_to?(:oauth_application)
- application.oauth_application = create_oauth_application(application)
- end
-
- application.save!
-
- Clusters::Applications::ScheduleInstallationService.new(project, current_user).execute(application)
+ Clusters::Applications::CreateService
+ .new(@cluster, current_user, create_cluster_application_params)
+ .execute(request)
head :no_content
+ rescue Clusters::Applications::CreateService::InvalidApplicationError
+ render_404
rescue StandardError
head :bad_request
end
- # rubocop: enable CodeReuse/ActiveRecord
private
@@ -34,18 +23,7 @@ class Projects::Clusters::ApplicationsController < Projects::ApplicationControll
@cluster ||= project.clusters.find(params[:id]) || render_404
end
- def application_class
- @application_class ||= Clusters::Cluster::APPLICATIONS[params[:application]] || render_404
- end
-
- def create_oauth_application(application)
- oauth_application_params = {
- name: params[:application],
- redirect_uri: application.callback_url,
- scopes: 'api read_user openid',
- owner: current_user
- }
-
- Applications::CreateService.new(current_user, oauth_application_params).execute(request)
+ def create_cluster_application_params
+ params.permit(:application, :hostname)
end
end
diff --git a/app/controllers/projects/clusters_controller.rb b/app/controllers/projects/clusters_controller.rb
index bcdbf48bb35..62adc66fb09 100644
--- a/app/controllers/projects/clusters_controller.rb
+++ b/app/controllers/projects/clusters_controller.rb
@@ -40,7 +40,7 @@ class Projects::ClustersController < Projects::ApplicationController
def update
Clusters::UpdateService
- .new(project, current_user, update_params)
+ .new(current_user, update_params)
.execute(cluster)
if cluster.valid?
@@ -73,8 +73,8 @@ class Projects::ClustersController < Projects::ApplicationController
def create_gcp
@gcp_cluster = ::Clusters::CreateService
- .new(project, current_user, create_gcp_cluster_params)
- .execute(token_in_session)
+ .new(current_user, create_gcp_cluster_params)
+ .execute(project: project, access_token: token_in_session)
if @gcp_cluster.persisted?
redirect_to project_cluster_path(project, @gcp_cluster)
@@ -89,8 +89,8 @@ class Projects::ClustersController < Projects::ApplicationController
def create_user
@user_cluster = ::Clusters::CreateService
- .new(project, current_user, create_user_cluster_params)
- .execute(token_in_session)
+ .new(current_user, create_user_cluster_params)
+ .execute(project: project, access_token: token_in_session)
if @user_cluster.persisted?
redirect_to project_cluster_path(project, @user_cluster)
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index d16240af404..5b70c69d7f4 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -56,10 +56,12 @@ class UsersController < ApplicationController
def projects
load_projects
+ skip_pagination = Gitlab::Utils.to_boolean(params[:skip_pagination])
+
respond_to do |format|
format.html { render 'show' }
format.json do
- pager_json("shared/projects/_list", @projects.count, projects: @projects)
+ pager_json("shared/projects/_list", @projects.count, projects: @projects, skip_pagination: skip_pagination)
end
end
end
diff --git a/app/finders/branches_finder.rb b/app/finders/branches_finder.rb
index 970efa79dfb..45d5591e81b 100644
--- a/app/finders/branches_finder.rb
+++ b/app/finders/branches_finder.rb
@@ -7,8 +7,9 @@ class BranchesFinder
end
def execute
- branches = @repository.branches_sorted_by(sort)
- filter_by_name(branches)
+ branches = repository.branches_sorted_by(sort)
+ branches = by_search(branches)
+ branches
end
private
@@ -23,11 +24,39 @@ class BranchesFinder
@params[:sort].presence || 'name'
end
- def filter_by_name(branches)
- if search
- branches.select { |branch| branch.name.upcase.include?(search.upcase) }
+ def by_search(branches)
+ return branches unless search
+
+ case search
+ when ->(v) { v.starts_with?('^') }
+ filter_branches_with_prefix(branches, search.slice(1..-1).upcase)
+ when ->(v) { v.ends_with?('$') }
+ filter_branches_with_suffix(branches, search.chop.upcase)
else
- branches
+ matches = filter_branches_by_name(branches, search.upcase)
+ set_exact_match_as_first_result(matches, search)
end
end
+
+ def filter_branches_with_prefix(branches, prefix)
+ branches.select { |branch| branch.name.upcase.starts_with?(prefix) }
+ end
+
+ def filter_branches_with_suffix(branches, suffix)
+ branches.select { |branch| branch.name.upcase.ends_with?(suffix) }
+ end
+
+ def filter_branches_by_name(branches, term)
+ branches.select { |branch| branch.name.upcase.include?(term) }
+ end
+
+ def set_exact_match_as_first_result(matches, term)
+ exact_match_index = find_exact_match_index(matches, term)
+ matches.insert(0, matches.delete_at(exact_match_index)) if exact_match_index
+ matches
+ end
+
+ def find_exact_match_index(matches, term)
+ matches.index { |branch| branch.name.casecmp(term) == 0 }
+ end
end
diff --git a/app/finders/projects_finder.rb b/app/finders/projects_finder.rb
index c2404412006..6ececcd4152 100644
--- a/app/finders/projects_finder.rb
+++ b/app/finders/projects_finder.rb
@@ -42,17 +42,7 @@ class ProjectsFinder < UnionFinder
init_collection
end
- collection = by_ids(collection)
- collection = by_personal(collection)
- collection = by_starred(collection)
- collection = by_trending(collection)
- collection = by_visibilty_level(collection)
- collection = by_tags(collection)
- collection = by_search(collection)
- collection = by_archived(collection)
- collection = by_custom_attributes(collection)
- collection = by_deleted_status(collection)
-
+ collection = filter_projects(collection)
sort(collection)
end
@@ -66,6 +56,21 @@ class ProjectsFinder < UnionFinder
end
end
+ # EE would override this to add more filters
+ def filter_projects(collection)
+ collection = by_ids(collection)
+ collection = by_personal(collection)
+ collection = by_starred(collection)
+ collection = by_trending(collection)
+ collection = by_visibilty_level(collection)
+ collection = by_tags(collection)
+ collection = by_search(collection)
+ collection = by_archived(collection)
+ collection = by_custom_attributes(collection)
+ collection = by_deleted_status(collection)
+ collection
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def collection_with_user
if owned_projects?
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index d6753e46165..0c9f69b6714 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -7,7 +7,6 @@ module ApplicationSettingsHelper
:gravatar_enabled?,
:password_authentication_enabled_for_web?,
:akismet_enabled?,
- :koding_enabled?,
to: :'Gitlab::CurrentSettings.current_application_settings'
def user_oauth_applications?
@@ -155,8 +154,6 @@ module ApplicationSettingsHelper
:housekeeping_incremental_repack_period,
:html_emails_enabled,
:import_sources,
- :koding_enabled,
- :koding_url,
:max_artifacts_size,
:max_attachment_size,
:max_pages_size,
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 883e5ddff57..8d58c86b7a4 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -195,7 +195,7 @@ module BlobHelper
{
'relative-url-root' => Rails.application.config.relative_url_root,
'assets-prefix' => Gitlab::Application.config.assets.prefix,
- 'blob-language' => @blob && @blob.language.try(:ace_mode),
+ 'blob-filename' => @blob && @blob.path,
'project-id' => project.id
}
end
diff --git a/app/helpers/dashboard_helper.rb b/app/helpers/dashboard_helper.rb
index 33c53021c11..463f4145bdd 100644
--- a/app/helpers/dashboard_helper.rb
+++ b/app/helpers/dashboard_helper.rb
@@ -21,29 +21,6 @@ module DashboardHelper
links.any? { |link| dashboard_nav_link?(link) }
end
- def controller_action_to_child_dashboards(controller = controller_name, action = action_name)
- case "#{controller}##{action}"
- when 'projects#index', 'root#index', 'projects#starred', 'projects#trending'
- %w(projects stars)
- when 'dashboard#activity'
- %w(starred_project_activity project_activity)
- when 'groups#index'
- %w(groups)
- when 'todos#index'
- %w(todos)
- when 'dashboard#issues'
- %w(issues)
- when 'dashboard#merge_requests'
- %w(merge_requests)
- else
- []
- end
- end
-
- def user_default_dashboard?(user = current_user)
- controller_action_to_child_dashboards.any? {|dashboard| dashboard == user.dashboard }
- end
-
private
def get_dashboard_nav_links
diff --git a/app/helpers/preferences_helper.rb b/app/helpers/preferences_helper.rb
index ff9842d4cd9..f4f46b0fe96 100644
--- a/app/helpers/preferences_helper.rb
+++ b/app/helpers/preferences_helper.rb
@@ -18,22 +18,20 @@ module PreferencesHelper
groups: _("Your Groups"),
todos: _("Your Todos"),
issues: _("Assigned Issues"),
- merge_requests: _("Assigned Merge Requests")
+ merge_requests: _("Assigned Merge Requests"),
+ operations: _("Operations Dashboard")
}.with_indifferent_access.freeze
# Returns an Array usable by a select field for more user-friendly option text
def dashboard_choices
- defined = User.dashboards
+ dashboards = User.dashboards.keys
- if defined.size != DASHBOARD_CHOICES.size
- # Ensure that anyone adding new options updates this method too
- raise "`User` defines #{defined.size} dashboard choices," \
- " but `DASHBOARD_CHOICES` defined #{DASHBOARD_CHOICES.size}."
- else
- defined.map do |key, _|
- # Use `fetch` so `KeyError` gets raised when a key is missing
- [DASHBOARD_CHOICES.fetch(key), key]
- end
+ validate_dashboard_choices!(dashboards)
+ dashboards -= excluded_dashboard_choices
+
+ dashboards.map do |key|
+ # Use `fetch` so `KeyError` gets raised when a key is missing
+ [DASHBOARD_CHOICES.fetch(key), key]
end
end
@@ -52,4 +50,20 @@ module PreferencesHelper
def user_color_scheme
Gitlab::ColorSchemes.for_user(current_user).css_class
end
+
+ private
+
+ # Ensure that anyone adding new options updates `DASHBOARD_CHOICES` too
+ def validate_dashboard_choices!(user_dashboards)
+ if user_dashboards.size != DASHBOARD_CHOICES.size
+ raise "`User` defines #{user_dashboards.size} dashboard choices," \
+ " but `DASHBOARD_CHOICES` defined #{DASHBOARD_CHOICES.size}."
+ end
+ end
+
+ # List of dashboard choice to be excluded from CE.
+ # EE would override this.
+ def excluded_dashboard_choices
+ ['operations']
+ end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 0016f89db5c..d9713f9c9b0 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -388,22 +388,6 @@ module ProjectsHelper
end
end
- def koding_project_url(project = nil, branch = nil, sha = nil)
- if project
- import_path = "/Home/Stacks/import"
-
- repo = project.full_path
- branch ||= project.default_branch
- sha ||= project.commit.short_id
-
- path = "#{import_path}?repo=#{repo}&branch=#{branch}&sha=#{sha}"
-
- return URI.join(Gitlab::CurrentSettings.koding_url, path).to_s
- end
-
- Gitlab::CurrentSettings.koding_url
- end
-
def project_wiki_path_with_version(proj, page, version, is_newest)
url_params = is_newest ? {} : { version_id: version }
project_wiki_path(proj, page, url_params)
diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb
index 53bd43d4861..8ed2a2ec9f4 100644
--- a/app/helpers/sorting_helper.rb
+++ b/app/helpers/sorting_helper.rb
@@ -48,15 +48,21 @@ module SortingHelper
def groups_sort_options_hash
{
- sort_value_name => sort_title_name,
- sort_value_name_desc => sort_title_name_desc,
+ sort_value_name => sort_title_name,
+ sort_value_name_desc => sort_title_name_desc,
sort_value_recently_created => sort_title_recently_created,
- sort_value_oldest_created => sort_title_oldest_created,
+ sort_value_oldest_created => sort_title_oldest_created,
sort_value_recently_updated => sort_title_recently_updated,
- sort_value_oldest_updated => sort_title_oldest_updated
+ sort_value_oldest_updated => sort_title_oldest_updated
}
end
+ def subgroups_sort_options_hash
+ groups_sort_options_hash.merge(
+ sort_value_most_stars => sort_title_most_stars
+ )
+ end
+
def admin_groups_sort_options_hash
groups_sort_options_hash.merge(
sort_value_largest_group => sort_title_largest_group
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 23131af1b7d..b66ec0ffab6 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -33,6 +33,8 @@ class ApplicationSetting < ActiveRecord::Base
ignore_column :circuitbreaker_storage_timeout
ignore_column :circuitbreaker_access_retries
ignore_column :circuitbreaker_check_interval
+ ignore_column :koding_url
+ ignore_column :koding_enabled
cache_markdown_field :sign_in_text
cache_markdown_field :help_page_text
@@ -100,10 +102,6 @@ class ApplicationSetting < ActiveRecord::Base
presence: true,
if: :unique_ips_limit_enabled
- validates :koding_url,
- presence: true,
- if: :koding_enabled
-
validates :plantuml_url,
presence: true,
if: :plantuml_enabled
@@ -252,8 +250,6 @@ class ApplicationSetting < ActiveRecord::Base
housekeeping_gc_period: 200,
housekeeping_incremental_repack_period: 10,
import_sources: Settings.gitlab['import_sources'],
- koding_enabled: false,
- koding_url: nil,
max_artifacts_size: Settings.artifacts['max_size'],
max_attachment_size: Settings.gitlab['max_attachment_size'],
mirror_available: true,
diff --git a/app/models/blob.rb b/app/models/blob.rb
index acc64ffca67..31a839274b5 100644
--- a/app/models/blob.rb
+++ b/app/models/blob.rb
@@ -162,7 +162,7 @@ class Blob < SimpleDelegator
if stored_externally?
if rich_viewer
rich_viewer.binary?
- elsif Linguist::Language.find_by_extension(name).any?
+ elsif known_extension?
false
elsif _mime_type
_mime_type.binary?
diff --git a/app/models/concerns/blob_like.rb b/app/models/concerns/blob_like.rb
index e96fefe81c4..f20f01486a5 100644
--- a/app/models/concerns/blob_like.rb
+++ b/app/models/concerns/blob_like.rb
@@ -2,7 +2,7 @@
module BlobLike
extend ActiveSupport::Concern
- include Linguist::BlobHelper
+ include Gitlab::BlobHelper
def id
raise NotImplementedError
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index 6962b54441b..62dc0f2cbeb 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -19,6 +19,17 @@ class Deployment < ActiveRecord::Base
after_create :create_ref
after_create :invalidate_cache
+ scope :for_environment, -> (environment) { where(environment_id: environment) }
+
+ def self.last_for_environment(environment)
+ ids = self
+ .for_environment(environment)
+ .select('MAX(id) AS id')
+ .group(:environment_id)
+ .map(&:id)
+ find(ids)
+ end
+
def commit
project.commit(sha)
end
diff --git a/app/models/environment.rb b/app/models/environment.rb
index 309bd4f37c9..0816c395185 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -48,6 +48,8 @@ class Environment < ActiveRecord::Base
order(Gitlab::Database.nulls_first_order("(#{max_deployment_id_sql})", 'ASC'))
end
scope :in_review_folder, -> { where(environment_type: "review") }
+ scope :for_name, -> (name) { where(name: name) }
+ scope :for_project, -> (project) { where(project_id: project) }
state_machine :state, initial: :available do
event :start do
diff --git a/app/models/project.rb b/app/models/project.rb
index 05e14c578b5..b80e41e4a96 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -49,8 +49,11 @@ class Project < ActiveRecord::Base
attachments: 2
}.freeze
- # Valids ports to import from
- VALID_IMPORT_PORTS = [22, 80, 443].freeze
+ VALID_IMPORT_PORTS = [80, 443].freeze
+ VALID_IMPORT_PROTOCOLS = %w(http https git).freeze
+
+ VALID_MIRROR_PORTS = [22, 80, 443].freeze
+ VALID_MIRROR_PROTOCOLS = %w(http https ssh git).freeze
cache_markdown_field :description, pipeline: :description
@@ -305,10 +308,10 @@ class Project < ActiveRecord::Base
validates :namespace, presence: true
validates :name, uniqueness: { scope: :namespace_id }
- validates :import_url, url: { protocols: %w(http https ssh git),
+ validates :import_url, url: { protocols: ->(project) { project.persisted? ? VALID_MIRROR_PROTOCOLS : VALID_IMPORT_PROTOCOLS },
+ ports: ->(project) { project.persisted? ? VALID_MIRROR_PORTS : VALID_IMPORT_PORTS },
allow_localhost: false,
- enforce_user: true,
- ports: VALID_IMPORT_PORTS }, if: [:external_import?, :import_url_changed?]
+ enforce_user: true }, if: [:external_import?, :import_url_changed?]
validates :star_count, numericality: { greater_than_or_equal_to: 0 }
validate :check_limit, on: :create
validate :check_repository_path_availability, on: :update, if: ->(project) { project.renamed? }
@@ -1789,7 +1792,7 @@ class Project < ActiveRecord::Base
return unless export_file_exists?
import_export_upload.remove_export_file!
- import_export_upload.save
+ import_export_upload.save unless import_export_upload.destroyed?
end
def export_file_exists?
diff --git a/app/models/repository.rb b/app/models/repository.rb
index a3a3ce179fc..6ce480c32c4 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -36,7 +36,7 @@ class Repository
# For example, for entry `:commit_count` there's a method called `commit_count` which
# stores its data in the `commit_count` cache key.
CACHED_METHODS = %i(size commit_count rendered_readme contribution_guide
- changelog license_blob license_key gitignore koding_yml
+ changelog license_blob license_key gitignore
gitlab_ci_yml branch_names tag_names branch_count
tag_count avatar exists? root_ref has_visible_content?
issue_template_names merge_request_template_names xcode_project?).freeze
@@ -53,7 +53,6 @@ class Repository
license: %i(license_blob license_key license),
contributing: :contribution_guide,
gitignore: :gitignore,
- koding: :koding_yml,
gitlab_ci: :gitlab_ci_yml,
avatar: :avatar,
issue_template: :issue_template_names,
@@ -619,11 +618,6 @@ class Repository
end
cache_method :gitignore
- def koding_yml
- file_on_head(:koding)
- end
- cache_method :koding_yml
-
def gitlab_ci_yml
file_on_head(:gitlab_ci)
end
@@ -881,10 +875,12 @@ class Repository
delegate :merged_branch_names, to: :raw_repository
- def merge_base(first_commit_id, second_commit_id)
- first_commit_id = commit(first_commit_id).try(:id) || first_commit_id
- second_commit_id = commit(second_commit_id).try(:id) || second_commit_id
- raw_repository.merge_base(first_commit_id, second_commit_id)
+ def merge_base(*commits_or_ids)
+ commit_ids = commits_or_ids.map do |commit_or_id|
+ commit_or_id.is_a?(::Commit) ? commit_or_id.id : commit_or_id
+ end
+
+ raw_repository.merge_base(*commit_ids)
end
def ancestor?(ancestor_id, descendant_id)
diff --git a/app/models/user.rb b/app/models/user.rb
index 8a7acfb73b1..a0665518cf5 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -217,7 +217,7 @@ class User < ActiveRecord::Base
# User's Dashboard preference
# Note: When adding an option, it MUST go on the end of the array.
- enum dashboard: [:projects, :stars, :project_activity, :starred_project_activity, :groups, :todos, :issues, :merge_requests]
+ enum dashboard: [:projects, :stars, :project_activity, :starred_project_activity, :groups, :todos, :issues, :merge_requests, :operations]
# User's Project preference
# Note: When adding an option, it MUST go on the end of the array.
diff --git a/app/models/user_callout.rb b/app/models/user_callout.rb
index 2c0e8659fc1..1cd05cf3aac 100644
--- a/app/models/user_callout.rb
+++ b/app/models/user_callout.rb
@@ -6,8 +6,7 @@ class UserCallout < ActiveRecord::Base
enum feature_name: {
gke_cluster_integration: 1,
gcp_signup_offer: 2,
- cluster_security_warning: 3,
- gold_trial: 4
+ cluster_security_warning: 3
}
validates :user, presence: true
diff --git a/app/presenters/project_presenter.rb b/app/presenters/project_presenter.rb
index d2434d96fd7..79cd3606aec 100644
--- a/app/presenters/project_presenter.rb
+++ b/app/presenters/project_presenter.rb
@@ -36,8 +36,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
contribution_guide_anchor_data,
autodevops_anchor_data(show_auto_devops_callout: show_auto_devops_callout),
kubernetes_cluster_anchor_data,
- gitlab_ci_anchor_data,
- koding_anchor_data
+ gitlab_ci_anchor_data
].compact.reject { |item| item.enabled }
end
@@ -125,43 +124,6 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
add_special_file_path(file_name: 'README.md')
end
- def add_koding_stack_path
- project_new_blob_path(
- project,
- default_branch || 'master',
- file_name: '.koding.yml',
- commit_message: "Add Koding stack script",
- content: <<-CONTENT.strip_heredoc
- provider:
- aws:
- access_key: '${var.aws_access_key}'
- secret_key: '${var.aws_secret_key}'
- resource:
- aws_instance:
- #{project.path}-vm:
- instance_type: t2.nano
- user_data: |-
-
- # Created by GitLab UI for :>
-
- echo _KD_NOTIFY_@Installing Base packages...@
-
- apt-get update -y
- apt-get install git -y
-
- echo _KD_NOTIFY_@Cloning #{project.name}...@
-
- export KODING_USER=${var.koding_user_username}
- export REPO_URL=#{root_url}${var.koding_queryString_repo}.git
- export BRANCH=${var.koding_queryString_branch}
-
- sudo -i -u $KODING_USER git clone $REPO_URL -b $BRANCH
-
- echo _KD_NOTIFY_@#{project.name} cloned.@
- CONTENT
- )
- end
-
def license_short_name
license = repository.license
license&.nickname || license&.name || 'LICENSE'
@@ -310,14 +272,6 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
end
end
- def koding_anchor_data
- if current_user && can_current_user_push_code? && koding_enabled? && repository.koding_yml.blank?
- AnchorData.new(false,
- _('Set up Koding'),
- add_koding_stack_path)
- end
- end
-
def tags_to_show
project.tag_list.take(MAX_TAGS_TO_SHOW) # rubocop: disable CodeReuse/ActiveRecord
end
@@ -363,8 +317,4 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
branch_name: branch_name
)
end
-
- def koding_enabled?
- Gitlab::CurrentSettings.koding_enabled?
- end
end
diff --git a/app/serializers/build_details_entity.rb b/app/serializers/build_details_entity.rb
index 3d508a9a407..066a5b1885c 100644
--- a/app/serializers/build_details_entity.rb
+++ b/app/serializers/build_details_entity.rb
@@ -4,11 +4,12 @@ class BuildDetailsEntity < JobEntity
expose :coverage, :erased_at, :duration
expose :tag_list, as: :tags
expose :has_trace?, as: :has_trace
+ expose :stage
expose :user, using: UserEntity
expose :runner, using: RunnerEntity
expose :pipeline, using: PipelineEntity
- expose :deployment_status, if: -> (*) { build.has_environment? } do
+ expose :deployment_status, if: -> (*) { build.starts_environment? } do
expose :deployment_status, as: :status
expose :persisted_environment, as: :environment, with: EnvironmentEntity
diff --git a/app/serializers/issue_entity.rb b/app/serializers/issue_entity.rb
index 16a477c92fa..c3f7d4651fb 100644
--- a/app/serializers/issue_entity.rb
+++ b/app/serializers/issue_entity.rb
@@ -42,6 +42,6 @@ class IssueEntity < IssuableEntity
end
expose :preview_note_path do |issue|
- preview_markdown_path(issue.project, quick_actions_target_type: 'Issue', quick_actions_target_id: issue.id)
+ preview_markdown_path(issue.project, quick_actions_target_type: 'Issue', quick_actions_target_id: issue.iid)
end
end
diff --git a/app/serializers/merge_request_widget_entity.rb b/app/serializers/merge_request_widget_entity.rb
index 380e8804f51..9ec24f799ef 100644
--- a/app/serializers/merge_request_widget_entity.rb
+++ b/app/serializers/merge_request_widget_entity.rb
@@ -222,7 +222,7 @@ class MergeRequestWidgetEntity < IssuableEntity
end
expose :preview_note_path do |merge_request|
- preview_markdown_path(merge_request.project, quick_actions_target_type: 'MergeRequest', quick_actions_target_id: merge_request.id)
+ preview_markdown_path(merge_request.project, quick_actions_target_type: 'MergeRequest', quick_actions_target_id: merge_request.iid)
end
expose :merge_commit_path do |merge_request|
diff --git a/app/services/applications/create_service.rb b/app/services/applications/create_service.rb
index 3d88c4f064e..b6c30da4d3a 100644
--- a/app/services/applications/create_service.rb
+++ b/app/services/applications/create_service.rb
@@ -9,6 +9,7 @@ module Applications
end
# rubocop: enable CodeReuse/ActiveRecord
+ # EE would override and use `request` arg
def execute(request)
Doorkeeper::Application.create(@params)
end
diff --git a/app/services/clusters/applications/create_service.rb b/app/services/clusters/applications/create_service.rb
new file mode 100644
index 00000000000..55f917798de
--- /dev/null
+++ b/app/services/clusters/applications/create_service.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Applications
+ class CreateService
+ InvalidApplicationError = Class.new(StandardError)
+
+ attr_reader :cluster, :current_user, :params
+
+ def initialize(cluster, user, params = {})
+ @cluster = cluster
+ @current_user = user
+ @params = params.dup
+ end
+
+ def execute(request)
+ create_application.tap do |application|
+ if application.has_attribute?(:hostname)
+ application.hostname = params[:hostname]
+ end
+
+ if application.respond_to?(:oauth_application)
+ application.oauth_application = create_oauth_application(application, request)
+ end
+
+ application.save!
+
+ Clusters::Applications::ScheduleInstallationService.new(application).execute
+ end
+ end
+
+ private
+
+ def create_application
+ builder.call(@cluster)
+ end
+
+ def builder
+ builders[application_name] || raise(InvalidApplicationError, "invalid application: #{application_name}")
+ end
+
+ def builders
+ {
+ "helm" => -> (cluster) { cluster.application_helm || cluster.build_application_helm },
+ "ingress" => -> (cluster) { cluster.application_ingress || cluster.build_application_ingress },
+ "prometheus" => -> (cluster) { cluster.application_prometheus || cluster.build_application_prometheus },
+ "runner" => -> (cluster) { cluster.application_runner || cluster.build_application_runner },
+ "jupyter" => -> (cluster) { cluster.application_jupyter || cluster.build_application_jupyter }
+ }
+ end
+
+ def application_name
+ params[:application]
+ end
+
+ def create_oauth_application(application, request)
+ oauth_application_params = {
+ name: params[:application],
+ redirect_uri: application.callback_url,
+ scopes: 'api read_user openid',
+ owner: current_user
+ }
+
+ ::Applications::CreateService.new(current_user, oauth_application_params).execute(request)
+ end
+ end
+ end
+end
diff --git a/app/services/clusters/applications/schedule_installation_service.rb b/app/services/clusters/applications/schedule_installation_service.rb
index 4ead4f619c8..d75ba70c27e 100644
--- a/app/services/clusters/applications/schedule_installation_service.rb
+++ b/app/services/clusters/applications/schedule_installation_service.rb
@@ -2,8 +2,14 @@
module Clusters
module Applications
- class ScheduleInstallationService < ::BaseService
- def execute(application)
+ class ScheduleInstallationService
+ attr_reader :application
+
+ def initialize(application)
+ @application = application
+ end
+
+ def execute
application.make_scheduled!
ClusterInstallAppWorker.perform_async(application.name, application.id)
diff --git a/app/services/clusters/create_service.rb b/app/services/clusters/create_service.rb
index e3e0cfa462c..c6e955800af 100644
--- a/app/services/clusters/create_service.rb
+++ b/app/services/clusters/create_service.rb
@@ -1,36 +1,34 @@
# frozen_string_literal: true
module Clusters
- class CreateService < BaseService
- attr_reader :access_token
+ class CreateService
+ attr_reader :current_user, :params
- def execute(access_token = nil)
- @access_token = access_token
+ def initialize(user = nil, params = {})
+ @current_user, @params = user, params.dup
+ end
- raise ArgumentError.new(_('Instance does not support multiple Kubernetes clusters')) unless can_create_cluster?
+ def execute(project:, access_token: nil)
+ raise ArgumentError.new(_('Instance does not support multiple Kubernetes clusters')) unless can_create_cluster?(project)
- create_cluster.tap do |cluster|
+ cluster_params = params.merge(user: current_user, projects: [project])
+ cluster_params[:provider_gcp_attributes].try do |provider|
+ provider[:access_token] = access_token
+ end
+
+ create_cluster(cluster_params).tap do |cluster|
ClusterProvisionWorker.perform_async(cluster.id) if cluster.persisted?
end
end
private
- def create_cluster
+ def create_cluster(cluster_params)
Clusters::Cluster.create(cluster_params)
end
- def cluster_params
- return @cluster_params if defined?(@cluster_params)
-
- params[:provider_gcp_attributes].try do |provider|
- provider[:access_token] = access_token
- end
-
- @cluster_params = params.merge(user: current_user, projects: [project])
- end
-
- def can_create_cluster?
+ # EE would override this method
+ def can_create_cluster?(project)
project.clusters.empty?
end
end
diff --git a/app/services/clusters/update_service.rb b/app/services/clusters/update_service.rb
index 98fdeec4fb1..25d26e761b1 100644
--- a/app/services/clusters/update_service.rb
+++ b/app/services/clusters/update_service.rb
@@ -1,7 +1,13 @@
# frozen_string_literal: true
module Clusters
- class UpdateService < BaseService
+ class UpdateService
+ attr_reader :current_user, :params
+
+ def initialize(user = nil, params = {})
+ @current_user, @params = user, params.dup
+ end
+
def execute(cluster)
cluster.update(params)
end
diff --git a/app/views/admin/application_settings/_koding.html.haml b/app/views/admin/application_settings/_koding.html.haml
deleted file mode 100644
index 8b635b08abd..00000000000
--- a/app/views/admin/application_settings/_koding.html.haml
+++ /dev/null
@@ -1,22 +0,0 @@
-= form_for @application_setting, url: admin_application_settings_path(anchor: 'js-koding-settings'), html: { class: 'fieldset-form' } do |f|
- = form_errors(@application_setting)
-
- %fieldset
- .form-group
- .form-check
- = f.check_box :koding_enabled, class: 'form-check-input'
- = f.label :koding_enabled, class: 'form-check-label' do
- Enable Koding
- .form-text.text-muted
- Koding integration has been deprecated since GitLab 10.0. If you disable your Koding integration, you will not be able to enable it again.
- .form-group
- = f.label :koding_url, 'Koding URL', class: 'label-bold'
- = f.text_field :koding_url, class: 'form-control', placeholder: 'http://gitlab.your-koding-instance.com:8090'
- .form-text.text-muted
- Koding has integration enabled out of the box for the
- %strong gitlab
- team, and you need to provide that team's URL here. Learn more in the
- = succeed "." do
- = link_to "Koding administration documentation", help_page_path("administration/integration/koding")
-
- = f.submit 'Save changes', class: "btn btn-success"
diff --git a/app/views/admin/application_settings/show.html.haml b/app/views/admin/application_settings/show.html.haml
index 279db189a24..65e4723afe6 100644
--- a/app/views/admin/application_settings/show.html.haml
+++ b/app/views/admin/application_settings/show.html.haml
@@ -68,18 +68,6 @@
.settings-content
= render 'terms'
-- if koding_enabled?
- %section.settings.as-koding.no-animate#js-koding-settings{ class: ('expanded' if expanded_by_default?) }
- .settings-header
- %h4
- = _('Koding')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
- = expanded_by_default? ? _('Collapse') : _('Expand')
- %p
- = _('Online IDE integration settings.')
- .settings-content
- = render 'koding'
-
= render_if_exists 'admin/application_settings/external_authorization_service_form', expanded: expanded_by_default?
%section.settings.as-terminal.no-animate#js-terminal-settings{ class: ('expanded' if expanded_by_default?) }
diff --git a/app/views/admin/applications/show.html.haml b/app/views/admin/applications/show.html.haml
index e69143abe45..df3eeba907c 100644
--- a/app/views/admin/applications/show.html.haml
+++ b/app/views/admin/applications/show.html.haml
@@ -22,7 +22,7 @@
.input-group
%input.label.label-monospace{ id: "secret", type: "text", autocomplete: 'off', value: @application.secret, readonly: true }
.input-group-append
- = clipboard_button(target: '#application_id', title: _("Copy secret to clipboard"), class: "btn btn btn-default")
+ = clipboard_button(target: '#secret', title: _("Copy secret to clipboard"), class: "btn btn btn-default")
%tr
%td
= _('Callback URL')
diff --git a/app/views/admin/groups/_form.html.haml b/app/views/admin/groups/_form.html.haml
index 2a117c1414e..5e05568e384 100644
--- a/app/views/admin/groups/_form.html.haml
+++ b/app/views/admin/groups/_form.html.haml
@@ -10,11 +10,11 @@
.col-sm-10
= render 'shared/choose_group_avatar_button', f: f
- = render 'shared/visibility_level', f: f, visibility_level: visibility_level, can_change_visibility_level: can_change_group_visibility_level?(@group), form_model: @group
+ = render 'shared/old_visibility_level', f: f, visibility_level: visibility_level, can_change_visibility_level: can_change_group_visibility_level?(@group), form_model: @group, with_label: false
.form-group.row
.offset-sm-2.col-sm-10
- = render 'shared/allow_request_access', form: f
+ = render 'shared/allow_request_access', form: f, bold_label: true
= render 'groups/group_admin_settings', f: f
diff --git a/app/views/dashboard/activity.html.haml b/app/views/dashboard/activity.html.haml
index 3cee5841bbc..31d4b3da4f1 100644
--- a/app/views/dashboard/activity.html.haml
+++ b/app/views/dashboard/activity.html.haml
@@ -4,9 +4,6 @@
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, dashboard_projects_url(rss_url_options), title: "All activity")
-= content_for :above_breadcrumbs_content do
- = render_if_exists "shared/gold_trial_callout"
-
- page_title "Activity"
- header_title "Activity", activity_dashboard_path
diff --git a/app/views/dashboard/groups/index.html.haml b/app/views/dashboard/groups/index.html.haml
index 985928305a2..50f39f93283 100644
--- a/app/views/dashboard/groups/index.html.haml
+++ b/app/views/dashboard/groups/index.html.haml
@@ -3,9 +3,6 @@
- header_title "Groups", dashboard_groups_path
= render 'dashboard/groups_head'
-= content_for :above_breadcrumbs_content do
- = render_if_exists "shared/gold_trial_callout"
-
- if params[:filter].blank? && @groups.empty?
= render 'shared/groups/empty_state'
- else
diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml
index 91f58ddcfcc..86a21e24ac9 100644
--- a/app/views/dashboard/issues.html.haml
+++ b/app/views/dashboard/issues.html.haml
@@ -4,9 +4,6 @@
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, safe_params.merge(rss_url_options).to_h, title: "#{current_user.name} issues")
-= content_for :above_breadcrumbs_content do
- = render_if_exists "shared/gold_trial_callout"
-
.top-area
= render 'shared/issuable/nav', type: :issues, display_count: !@no_filters_set
.nav-controls
diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml
index 27f53a8d1c6..61aae31be60 100644
--- a/app/views/dashboard/merge_requests.html.haml
+++ b/app/views/dashboard/merge_requests.html.haml
@@ -2,9 +2,6 @@
- page_title _("Merge Requests")
- @breadcrumb_link = merge_requests_dashboard_path(assignee_id: current_user.id)
-= content_for :above_breadcrumbs_content do
- = render_if_exists "shared/gold_trial_callout"
-
.top-area
= render 'shared/issuable/nav', type: :merge_requests, display_count: !@no_filters_set
.nav-controls
diff --git a/app/views/dashboard/projects/index.html.haml b/app/views/dashboard/projects/index.html.haml
index f0d16936a51..deed774a4a5 100644
--- a/app/views/dashboard/projects/index.html.haml
+++ b/app/views/dashboard/projects/index.html.haml
@@ -4,9 +4,6 @@
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, dashboard_projects_url(rss_url_options), title: "All activity")
-= content_for :above_breadcrumbs_content do
- = render_if_exists "shared/gold_trial_callout"
-
- page_title "Projects"
- header_title "Projects", dashboard_projects_path
diff --git a/app/views/dashboard/projects/starred.html.haml b/app/views/dashboard/projects/starred.html.haml
index 42638b8528d..8933d9e31ff 100644
--- a/app/views/dashboard/projects/starred.html.haml
+++ b/app/views/dashboard/projects/starred.html.haml
@@ -4,9 +4,6 @@
- page_title "Starred Projects"
- header_title "Projects", dashboard_projects_path
-= content_for :above_breadcrumbs_content do
- = render_if_exists "shared/gold_trial_callout"
-
%div{ class: container_class }
= render "projects/last_push"
= render 'dashboard/projects_head'
diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml
index bbfa4cc7413..8b3974d97f8 100644
--- a/app/views/dashboard/todos/index.html.haml
+++ b/app/views/dashboard/todos/index.html.haml
@@ -2,9 +2,6 @@
- page_title "Todos"
- header_title "Todos", dashboard_todos_path
-= content_for :above_breadcrumbs_content do
- = render_if_exists "shared/gold_trial_callout"
-
- if current_user.todos.any?
.top-area
%ul.nav-links.mobile-separator.nav.nav-tabs
diff --git a/app/views/devise/shared/_omniauth_box.html.haml b/app/views/devise/shared/_omniauth_box.html.haml
index 269a3721e06..12271ee5adb 100644
--- a/app/views/devise/shared/_omniauth_box.html.haml
+++ b/app/views/devise/shared/_omniauth_box.html.haml
@@ -5,7 +5,7 @@
.d-flex.justify-content-between.flex-wrap
- providers.each do |provider|
- has_icon = provider_has_icon?(provider)
- = link_to omniauth_authorize_path(:user, provider), method: :post, class: 'btn d-flex align-items-center omniauth-btn text-left oauth-login', id: "oauth-login-#{provider}" do
+ = link_to omniauth_authorize_path(:user, provider), method: :post, class: 'btn d-flex align-items-center omniauth-btn text-left oauth-login qa-saml-login-button', id: "oauth-login-#{provider}" do
- if has_icon
= provider_image_tag(provider)
%span
diff --git a/app/views/doorkeeper/applications/show.html.haml b/app/views/doorkeeper/applications/show.html.haml
index 776bbc36ec2..cac00f9c854 100644
--- a/app/views/doorkeeper/applications/show.html.haml
+++ b/app/views/doorkeeper/applications/show.html.haml
@@ -25,7 +25,7 @@
.input-group
%input.label.label-monospace{ id: "secret", type: "text", autocomplete: 'off', value: @application.secret, readonly: true }
.input-group-append
- = clipboard_button(target: '#application_id', title: _("Copy secret to clipboard"), class: "btn btn btn-default")
+ = clipboard_button(target: '#secret', title: _("Copy secret to clipboard"), class: "btn btn btn-default")
%tr
%td
= _('Callback URL')
diff --git a/app/views/explore/groups/index.html.haml b/app/views/explore/groups/index.html.haml
index 1d8b9c5bc8f..a3eafc61d0a 100644
--- a/app/views/explore/groups/index.html.haml
+++ b/app/views/explore/groups/index.html.haml
@@ -2,9 +2,6 @@
- page_title _("Groups")
- header_title _("Groups"), dashboard_groups_path
-= content_for :above_breadcrumbs_content do
- = render_if_exists "shared/gold_trial_callout"
-
- if current_user
= render 'dashboard/groups_head'
- else
@@ -13,7 +10,7 @@
- if cookies[:explore_groups_landing_dismissed] != 'true'
.explore-groups.landing.content-block.js-explore-groups-landing.hide
- %button.dismiss-button{ type: 'button', 'aria-label' => _('Dismiss') }= icon('times')
+ %button.dismiss-button{ type: 'button', 'aria-label' => _('Dismiss') }= sprite_icon('close', size: 16)
.svg-container
= custom_icon('icon_explore_groups_splash')
.inner-content
diff --git a/app/views/explore/projects/index.html.haml b/app/views/explore/projects/index.html.haml
index 16be5791f83..452f390695c 100644
--- a/app/views/explore/projects/index.html.haml
+++ b/app/views/explore/projects/index.html.haml
@@ -2,9 +2,6 @@
- page_title _("Projects")
- header_title _("Projects"), dashboard_projects_path
-= content_for :above_breadcrumbs_content do
- = render_if_exists "shared/gold_trial_callout"
-
- if current_user
= render 'dashboard/projects_head'
- else
diff --git a/app/views/explore/projects/starred.html.haml b/app/views/explore/projects/starred.html.haml
index 16be5791f83..452f390695c 100644
--- a/app/views/explore/projects/starred.html.haml
+++ b/app/views/explore/projects/starred.html.haml
@@ -2,9 +2,6 @@
- page_title _("Projects")
- header_title _("Projects"), dashboard_projects_path
-= content_for :above_breadcrumbs_content do
- = render_if_exists "shared/gold_trial_callout"
-
- if current_user
= render 'dashboard/projects_head'
- else
diff --git a/app/views/explore/projects/trending.html.haml b/app/views/explore/projects/trending.html.haml
index 16be5791f83..452f390695c 100644
--- a/app/views/explore/projects/trending.html.haml
+++ b/app/views/explore/projects/trending.html.haml
@@ -2,9 +2,6 @@
- page_title _("Projects")
- header_title _("Projects"), dashboard_projects_path
-= content_for :above_breadcrumbs_content do
- = render_if_exists "shared/gold_trial_callout"
-
- if current_user
= render 'dashboard/projects_head'
- else
diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml
index fc17dd2d310..f3792c5e397 100644
--- a/app/views/groups/edit.html.haml
+++ b/app/views/groups/edit.html.haml
@@ -3,31 +3,31 @@
- expanded = Rails.env.test?
-%section.settings.gs-general.no-animate#js-general-settings{ class: ('expanded' if expanded) }
+%section.settings.gs-general.no-animate#js-general-settings{ class: ('expanded') }
.settings-header
- %h4
- = _('General')
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only{ role: 'button' }
+ = _('Naming, visibility')
%button.btn.js-settings-toggle{ type: 'button' }
- = expanded ? _('Collapse') : _('Expand')
+ = _('Collapse')
%p
- = _('Update your group name, description, avatar, and other general settings.')
+ = _('Update your group name, description, avatar, and visibility.')
.settings-content
= render 'groups/settings/general'
%section.settings.gs-permissions.no-animate#js-permissions-settings{ class: ('expanded' if expanded) }
.settings-header
- %h4
- = _('Permissions')
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only{ role: 'button' }
+ = _('Permissions, LFS, 2FA')
%button.btn.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
- = _('Enable or disable certain group features and choose access levels.')
+ = _('Advanced permissions, Large File Storage and Two-Factor authentication settings.')
.settings-content
= render 'groups/settings/permissions'
-%section.settings.no-animate{ class: ('expanded' if expanded) }
+%section.settings.no-animate#js-badge-settings{ class: ('expanded' if expanded) }
.settings-header
- %h4
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only{ role: 'button' }
= s_('GroupSettings|Badges')
%button.btn.js-settings-toggle{ type: 'button' }
= expanded ? 'Collapse' : 'Expand'
@@ -39,8 +39,8 @@
%section.settings.gs-advanced.no-animate#js-advanced-settings{ class: ('expanded' if expanded) }
.settings-header
- %h4
- = _('Advanced')
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only{ role: 'button' }
+ = _('Path, transfer, remove')
%button.btn.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml
index 683129fdf6e..86c5f6a7aa3 100644
--- a/app/views/groups/new.html.haml
+++ b/app/views/groups/new.html.haml
@@ -27,7 +27,7 @@
.col-sm-10
= render 'shared/choose_group_avatar_button', f: f
- = render 'shared/visibility_level', f: f, visibility_level: default_group_visibility, can_change_visibility_level: true, form_model: @group
+ = render 'shared/old_visibility_level', f: f, visibility_level: @group.visibility_level, can_change_visibility_level: can_change_group_visibility_level?(@group), form_model: @group, with_label: false
= render 'create_chat_team', f: f if Gitlab.config.mattermost.enabled
diff --git a/app/views/groups/settings/_advanced.html.haml b/app/views/groups/settings/_advanced.html.haml
index 3814d45929d..5d211d0e186 100644
--- a/app/views/groups/settings/_advanced.html.haml
+++ b/app/views/groups/settings/_advanced.html.haml
@@ -23,16 +23,6 @@
= f.submit 'Change group path', class: 'btn btn-warning'
-.sub-section
- %h4.danger-title Remove group
- = form_tag(@group, method: :delete) do
- %p
- Removing group will cause all child projects and resources to be removed.
- %br
- %strong Removed group can not be restored!
-
- = button_to 'Remove group', '#', class: 'btn btn-remove js-confirm-danger', data: { 'confirm-danger-message' => remove_group_message(@group) }
-
- if supports_nested_groups?
.sub-section
%h4.warning-title Transfer group
@@ -47,3 +37,13 @@
%li You will need to update your local repositories to point to the new location.
%li If the parent group's visibility is lower than the group current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility.
= f.submit 'Transfer group', class: 'btn btn-warning'
+
+.sub-section
+ %h4.danger-title= _('Remove group')
+ = form_tag(@group, method: :delete) do
+ %p
+ = _('Removing group will cause all child projects and resources to be removed.')
+ %br
+ %strong= _('Removed group can not be restored!')
+
+ = button_to _('Remove group'), '#', class: 'btn btn-remove js-confirm-danger', data: { 'confirm-danger-message' => remove_group_message(@group) }
diff --git a/app/views/groups/settings/_general.html.haml b/app/views/groups/settings/_general.html.haml
index 0e225fe33a5..0424ece037d 100644
--- a/app/views/groups/settings/_general.html.haml
+++ b/app/views/groups/settings/_general.html.haml
@@ -1,39 +1,33 @@
-= form_for @group, html: { multipart: true, class: 'gl-show-field-errors' }, authenticity_token: true do |f|
+= form_for @group, html: { multipart: true, class: 'gl-show-field-errors js-general-settings-form' }, authenticity_token: true do |f|
%input{ type: 'hidden', name: 'update_section', value: 'js-general-settings' }
= form_errors(@group)
%fieldset
.row
- .form-group.col-md-9
- = f.label :name, class: 'label-bold' do
- Group name
+ .form-group.col-md-5
+ = f.label :name, _('Group name'), class: 'label-bold'
= f.text_field :name, class: 'form-control'
- .form-group.col-md-3
- = f.label :id, class: 'label-bold' do
- Group ID
- = f.text_field :id, class: 'form-control', readonly: true
+ .form-group.col-md-7
+ = f.label :id, _('Group ID'), class: 'label-bold'
+ = f.text_field :id, class: 'form-control w-auto', readonly: true
- .form-group
- = f.label :description, class: 'label-bold' do
- Group description
- %span.light (optional)
- = f.text_area :description, class: 'form-control', rows: 3, maxlength: 250
+ .row.prepend-top-8
+ .form-group.col-md-9.append-bottom-0
+ = f.label :description, _('Group description (optional)'), class: 'label-bold'
+ = f.text_area :description, class: 'form-control', rows: 3, maxlength: 250
= render_if_exists 'shared/repository_size_limit_setting', form: f, type: :group
- .form-group.row
- .col-sm-12
- .avatar-container.s160
- = group_icon(@group, alt: '', class: 'avatar group-avatar s160')
- %p.light
- - if @group.avatar?
- You can change the group avatar here
- - else
- You can upload a group avatar here
- = render 'shared/choose_group_avatar_button', f: f
- - if @group.avatar?
- %hr
- = link_to _('Remove avatar'), group_avatar_path(@group.to_param), data: { confirm: _('Avatar will be removed. Are you sure?')}, method: :delete, class: 'btn btn-danger btn-inverted'
+ .form-group.prepend-top-default.append-bottom-20
+ .avatar-container.s90
+ = group_icon(@group, alt: '', class: 'avatar group-avatar s90')
+ = f.label :avatar, _('Group avatar'), class: 'label-bold d-block'
+ = render 'shared/choose_group_avatar_button', f: f
+ - if @group.avatar?
+ %hr
+ = link_to _('Remove avatar'), group_avatar_path(@group.to_param), data: { confirm: _('Avatar will be removed. Are you sure?')}, method: :delete, class: 'btn btn-danger btn-inverted'
- = f.submit 'Save group', class: 'btn btn-success'
+ = render 'shared/visibility_level', f: f, visibility_level: @group.visibility_level, can_change_visibility_level: can_change_group_visibility_level?(@group), form_model: @group
+
+ = f.submit _('Save changes'), class: 'btn btn-success mt-4 js-dirty-submit'
diff --git a/app/views/groups/settings/_lfs.html.haml b/app/views/groups/settings/_lfs.html.haml
new file mode 100644
index 00000000000..4674d561c12
--- /dev/null
+++ b/app/views/groups/settings/_lfs.html.haml
@@ -0,0 +1,15 @@
+- docs_link_url = help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs')
+- docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: docs_link_url }
+
+%h5= _('Large File Storage')
+
+%p= s_('Check the %{docs_link_start}documentation%{docs_link_end}.').html_safe % { docs_link_start: docs_link_start, docs_link_end: '</a>'.html_safe }
+
+.form-group.append-bottom-default
+ .form-check
+ = f.check_box :lfs_enabled, checked: @group.lfs_enabled?, class: 'form-check-input'
+ = f.label :lfs_enabled, class: 'form-check-label' do
+ %span
+ = _('Allow projects within this group to use Git LFS')
+ %br/
+ %span.text-muted= _('This setting can be overridden in each project.')
diff --git a/app/views/groups/settings/_permissions.html.haml b/app/views/groups/settings/_permissions.html.haml
index 8dc88ec446c..6b0a6e7ed99 100644
--- a/app/views/groups/settings/_permissions.html.haml
+++ b/app/views/groups/settings/_permissions.html.haml
@@ -1,29 +1,24 @@
-= form_for @group, html: { multipart: true, class: 'gl-show-field-errors' }, authenticity_token: true do |f|
+= form_for @group, html: { multipart: true, class: 'gl-show-field-errors js-general-permissions-form' }, authenticity_token: true do |f|
%input{ type: 'hidden', name: 'update_section', value: 'js-permissions-settings' }
= form_errors(@group)
%fieldset
- = render 'shared/visibility_level', f: f, visibility_level: @group.visibility_level, can_change_visibility_level: can_change_group_visibility_level?(@group), form_model: @group
+ %h5= _('Permissions')
+ .form-group
+ = render 'shared/allow_request_access', form: f
- .form-group.row
- .offset-sm-2.col-sm-10
- = render 'shared/allow_request_access', form: f
-
- .form-group.row
- %label.col-form-label.col-sm-2.pt-0
- = s_('GroupSettings|Share with group lock')
- .col-sm-10
- .form-check
- = f.check_box :share_with_group_lock, disabled: !can_change_share_with_group_lock?(@group), class: 'form-check-input'
- = f.label :share_with_group_lock, class: 'form-check-label' do
- %strong
- - group_link = link_to @group.name, group_path(@group)
- = s_('GroupSettings|Prevent sharing a project within %{group} with other groups').html_safe % { group: group_link }
- %br
- %span.descr= share_with_group_lock_help_text(@group)
-
- = render 'groups/group_admin_settings', f: f
+ .form-group.append-bottom-default
+ .form-check
+ = f.check_box :share_with_group_lock, disabled: !can_change_share_with_group_lock?(@group), class: 'form-check-input'
+ = f.label :share_with_group_lock, class: 'form-check-label' do
+ %span
+ - group_link = link_to @group.name, group_path(@group)
+ = s_('GroupSettings|Prevent sharing a project within %{group} with other groups').html_safe % { group: group_link }
+ %br
+ %span.descr.text-muted= share_with_group_lock_help_text(@group)
+ = render 'groups/settings/lfs', f: f
+ = render 'groups/settings/two_factor_auth', f: f
= render_if_exists 'groups/member_lock_setting', f: f, group: @group
- = f.submit 'Save group', class: 'btn btn-success'
+ = f.submit _('Save changes'), class: 'btn btn-success prepend-top-default js-dirty-submit'
diff --git a/app/views/groups/settings/_two_factor_auth.html.haml b/app/views/groups/settings/_two_factor_auth.html.haml
new file mode 100644
index 00000000000..5d3f1cbb279
--- /dev/null
+++ b/app/views/groups/settings/_two_factor_auth.html.haml
@@ -0,0 +1,16 @@
+- docs_link_url = help_page_path('security/two_factor_authentication', anchor: 'enforcing-2fa-for-all-users-in-a-group')
+- docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: docs_link_url }
+
+%h5= _('Two-factor authentication')
+
+%p= s_('Check the %{docs_link_start}documentation%{docs_link_end}.').html_safe % { docs_link_start: docs_link_start, docs_link_end: '</a>'.html_safe }
+
+.form-group
+ .form-check
+ = f.check_box :require_two_factor_authentication, class: 'form-check-input'
+ = f.label :require_two_factor_authentication, class: 'form-check-label' do
+ %span= _('Require all users in this group to setup Two-factor authentication')
+.form-group
+ = f.label :two_factor_grace_period, _('Time before enforced'), class: 'label-bold'
+ = f.text_field :two_factor_grace_period, class: 'form-control form-control-sm w-auto'
+ .form-text.text-muted= _('Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication')
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index 6a293daaf95..cc294f6a931 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -53,7 +53,7 @@
= _("Archived projects")
.nav-controls
- = render "shared/groups/dropdown"
+ = render "shared/groups/dropdown", options_hash: subgroups_sort_options_hash
.tab-content
#subgroups_and_projects.tab-pane
diff --git a/app/views/koding/index.html.haml b/app/views/koding/index.html.haml
deleted file mode 100644
index bb7f9ba7ae4..00000000000
--- a/app/views/koding/index.html.haml
+++ /dev/null
@@ -1,6 +0,0 @@
-.row-content-block.second-block.center
- %p
- = icon('circle', class: 'cgreen')
- Integration is active for
- = link_to koding_project_url, target: '_blank', rel: 'noopener noreferrer' do
- #{Gitlab::CurrentSettings.koding_url}
diff --git a/app/views/layouts/koding.html.haml b/app/views/layouts/koding.html.haml
deleted file mode 100644
index 45ccd38f687..00000000000
--- a/app/views/layouts/koding.html.haml
+++ /dev/null
@@ -1,5 +0,0 @@
-- page_title _("Koding")
-- page_description _("Koding Dashboard")
-- header_title _("Koding"), koding_path
-
-= render template: "layouts/application"
diff --git a/app/views/layouts/nav/_breadcrumbs.html.haml b/app/views/layouts/nav/_breadcrumbs.html.haml
index c35451827c8..f53bd2b5e4d 100644
--- a/app/views/layouts/nav/_breadcrumbs.html.haml
+++ b/app/views/layouts/nav/_breadcrumbs.html.haml
@@ -1,7 +1,6 @@
- container = @no_breadcrumb_container ? 'container-fluid' : container_class
- hide_top_links = @hide_top_links || false
-= yield :above_breadcrumbs_content
%nav.breadcrumbs{ role: "navigation", class: [container, @content_class] }
.breadcrumbs-container
- if defined?(@left_sidebar)
diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml
index 5e467c862ab..8f8b6b454d9 100644
--- a/app/views/layouts/nav/_dashboard.html.haml
+++ b/app/views/layouts/nav/_dashboard.html.haml
@@ -66,6 +66,7 @@
- if Gitlab::Sherlock.enabled? || can?(current_user, :read_instance_statistics)
%li.line-separator.d-none.d-sm-block
+ = render_if_exists 'dashboard/operations/nav_link'
- if can?(current_user, :read_instance_statistics)
= nav_link(controller: [:conversational_development_index, :cohorts]) do
= link_to instance_statistics_root_path, title: _('Instance Statistics'), aria: { label: _('Instance Statistics') }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
diff --git a/app/views/layouts/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml
index 48025f9bd20..3625224fbcd 100644
--- a/app/views/layouts/nav/sidebar/_project.html.haml
+++ b/app/views/layouts/nav/sidebar/_project.html.haml
@@ -309,7 +309,7 @@
%span
= _('General')
= nav_link(controller: :project_members) do
- = link_to project_project_members_path(@project), title: _('Members') do
+ = link_to project_project_members_path(@project), title: _('Members'), class: 'qa-link-members-settings' do
%span
= _('Members')
- if can_edit
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index ced6a2a0399..61ed951dea9 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -76,8 +76,6 @@
= render 'projects/buttons/download', project: @project, ref: @ref
.d-none.d-sm-inline-flex
= render 'projects/buttons/dropdown'
- .d-none.d-sm-inline-flex
- = render 'projects/buttons/koding'
.d-none.d-sm-inline-flex
= render 'shared/notifications/button', notification_setting: @notification_setting
diff --git a/app/views/projects/buttons/_koding.html.haml b/app/views/projects/buttons/_koding.html.haml
deleted file mode 100644
index e665ca61da8..00000000000
--- a/app/views/projects/buttons/_koding.html.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-- if koding_enabled? && current_user && @repository.koding_yml && @project.can_current_user_push_code?
- = link_to koding_project_url(@project), class: 'btn project-action-button inline', target: '_blank', rel: 'noopener noreferrer' do
- _('Run in IDE (Koding)')
diff --git a/app/views/projects/clusters/_banner.html.haml b/app/views/projects/clusters/_banner.html.haml
index 141314b4e4e..73cfea0ef92 100644
--- a/app/views/projects/clusters/_banner.html.haml
+++ b/app/views/projects/clusters/_banner.html.haml
@@ -9,7 +9,7 @@
= s_("ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details")
- if show_cluster_security_warning?
- .js-cluster-security-warning.alert.alert-block.alert-dismissable.bs-callout.bs-callout-warning{ data: { feature_id: UserCalloutsHelper::CLUSTER_SECURITY_WARNING, dismiss_endpoint: user_callouts_path } }
- %button.close.js-close{ type: "button" } &times;
+ .js-cluster-security-warning.alert.alert-block.alert-dismissable.bs-callout.bs-callout-warning
+ %button.close{ type: "button", data: { feature_id: UserCalloutsHelper::CLUSTER_SECURITY_WARNING, dismiss_endpoint: user_callouts_path } } &times;
= s_("ClusterIntegration|The default cluster configuration grants access to many functionalities needed to successfully build and deploy a containerised application.")
= link_to s_("More information"), help_page_path('user/project/clusters/index.md', anchor: 'security-implications')
diff --git a/app/views/projects/clusters/_gcp_signup_offer_banner.html.haml b/app/views/projects/clusters/_gcp_signup_offer_banner.html.haml
index 85d1002243b..73b11d509d3 100644
--- a/app/views/projects/clusters/_gcp_signup_offer_banner.html.haml
+++ b/app/views/projects/clusters/_gcp_signup_offer_banner.html.haml
@@ -1,6 +1,6 @@
- link = link_to(s_('ClusterIntegration|sign up'), 'https://console.cloud.google.com/freetrial?utm_campaign=2018_cpanel&utm_source=gitlab&utm_medium=referral', target: '_blank', rel: 'noopener noreferrer')
-.bs-callout.gcp-signup-offer.alert.alert-block.alert-dismissable.prepend-top-default.append-bottom-default{ role: 'alert', data: { feature_id: UserCalloutsHelper::GCP_SIGNUP_OFFER, dismiss_endpoint: user_callouts_path } }
- %button.close.js-close{ type: "button" } &times;
+.bs-callout.gcp-signup-offer.alert.alert-block.alert-dismissable.prepend-top-default.append-bottom-default{ role: 'alert' }
+ %button.close{ type: "button", data: { feature_id: UserCalloutsHelper::GCP_SIGNUP_OFFER, dismiss_endpoint: user_callouts_path } } &times;
.gcp-signup-offer--content
.gcp-signup-offer--icon.append-right-8
= sprite_icon("information", size: 16)
diff --git a/app/views/projects/deploy_tokens/_form.html.haml b/app/views/projects/deploy_tokens/_form.html.haml
index 8b7535397bc..5412fcbc9d8 100644
--- a/app/views/projects/deploy_tokens/_form.html.haml
+++ b/app/views/projects/deploy_tokens/_form.html.haml
@@ -6,24 +6,24 @@
.form-group
= f.label :name, class: 'label-bold'
- = f.text_field :name, class: 'form-control', required: true
+ = f.text_field :name, class: 'form-control qa-deploy-token-name', required: true
.form-group
= f.label :expires_at, class: 'label-bold'
- = f.text_field :expires_at, class: 'datepicker form-control', value: f.object.expires_at
+ = f.text_field :expires_at, class: 'datepicker form-control qa-deploy-token-expires-at', value: f.object.expires_at
.form-group
= f.label :scopes, class: 'label-bold'
%fieldset.form-group.form-check
- = f.check_box :read_repository, class: 'form-check-input'
+ = f.check_box :read_repository, class: 'form-check-input qa-deploy-token-read-repository'
= label_tag ("deploy_token_read_repository"), 'read_repository', class: 'label-bold form-check-label'
.text-secondary= s_('DeployTokens|Allows read-only access to the repository')
- if container_registry_enabled?(project)
%fieldset.form-group.form-check
- = f.check_box :read_registry, class: 'form-check-input'
+ = f.check_box :read_registry, class: 'form-check-input qa-deploy-token-read-registry'
= label_tag ("deploy_token_read_registry"), 'read_registry', class: 'label-bold form-check-label'
.text-secondary= s_('DeployTokens|Allows read-only access to the registry images')
.prepend-top-default
- = f.submit s_('DeployTokens|Create deploy token'), class: 'btn btn-success'
+ = f.submit s_('DeployTokens|Create deploy token'), class: 'btn btn-success qa-create-deploy-token'
diff --git a/app/views/projects/deploy_tokens/_index.html.haml b/app/views/projects/deploy_tokens/_index.html.haml
index 33faab0c510..4619522cfaf 100644
--- a/app/views/projects/deploy_tokens/_index.html.haml
+++ b/app/views/projects/deploy_tokens/_index.html.haml
@@ -1,6 +1,6 @@
- expanded = expand_deploy_tokens_section?(@new_deploy_token)
-%section.settings.no-animate#js-deploy-tokens{ class: ('expanded' if expanded) }
+%section.qa-deploy-tokens-settings.settings.no-animate#js-deploy-tokens{ class: ('expanded' if expanded) }
.settings-header
%h4= s_('DeployTokens|Deploy Tokens')
%button.btn.js-settings-toggle.qa-expand-deploy-keys{ type: 'button' }
diff --git a/app/views/projects/deploy_tokens/_new_deploy_token.html.haml b/app/views/projects/deploy_tokens/_new_deploy_token.html.haml
index 5dd9ffba074..c805ee73acc 100644
--- a/app/views/projects/deploy_tokens/_new_deploy_token.html.haml
+++ b/app/views/projects/deploy_tokens/_new_deploy_token.html.haml
@@ -1,18 +1,18 @@
-.created-deploy-token-container.info-well
+.qa-created-deploy-token-section.created-deploy-token-container.info-well
.well-segment
%h5.prepend-top-0
= s_('DeployTokens|Your New Deploy Token')
.form-group
.input-group
- = text_field_tag 'deploy-token-user', deploy_token.username, readonly: true, class: 'deploy-token-field form-control js-select-on-focus'
+ = text_field_tag 'deploy-token-user', deploy_token.username, readonly: true, class: 'deploy-token-field form-control js-select-on-focus qa-deploy-token-user'
.input-group-append
= clipboard_button(text: deploy_token.username, title: s_('DeployTokens|Copy username to clipboard'), placement: 'left')
%span.deploy-token-help-block.prepend-top-5.text-success= s_("DeployTokens|Use this username as a login.")
.form-group
.input-group
- = text_field_tag 'deploy-token', deploy_token.token, readonly: true, class: 'deploy-token-field form-control js-select-on-focus'
+ = text_field_tag 'deploy-token', deploy_token.token, readonly: true, class: 'deploy-token-field form-control js-select-on-focus qa-deploy-token'
.input-group-append
= clipboard_button(text: deploy_token.token, title: s_('DeployTokens|Copy deploy token to clipboard'), placement: 'left')
%span.deploy-token-help-block.prepend-top-5.text-danger= s_("DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again.")
diff --git a/app/views/projects/jobs/show.html.haml b/app/views/projects/jobs/show.html.haml
index a5f814b722d..02a088d338b 100644
--- a/app/views/projects/jobs/show.html.haml
+++ b/app/views/projects/jobs/show.html.haml
@@ -47,4 +47,6 @@
.js-build-options{ data: javascript_build_options }
-#js-job-details-vue{ data: { endpoint: project_job_path(@project, @build, format: :json), runner_help_url: help_page_path('ci/runners/README.html', anchor: 'setting-maximum-job-timeout-for-a-runner') } }
+#js-job-details-vue{ data: { endpoint: project_job_path(@project, @build, format: :json),
+ runner_help_url: help_page_path('ci/runners/README.html', anchor: 'setting-maximum-job-timeout-for-a-runner'),
+ runner_settings_url: project_runners_path(@build.project, anchor: 'js-runners-settings') } }
diff --git a/app/views/projects/project_members/_new_project_member.html.haml b/app/views/projects/project_members/_new_project_member.html.haml
index 517fd249f6e..5e21442bb60 100644
--- a/app/views/projects/project_members/_new_project_member.html.haml
+++ b/app/views/projects/project_members/_new_project_member.html.haml
@@ -3,7 +3,7 @@
= form_for @project_member, as: :project_member, url: project_project_members_path(@project), html: { class: 'users-project-form' } do |f|
.form-group
= label_tag :user_ids, "Select members to invite", class: "label-bold"
- = users_select_tag(:user_ids, multiple: true, class: "input-clamp", scope: :all, email_user: true, placeholder: "Search for members to update or invite")
+ = users_select_tag(:user_ids, multiple: true, class: "input-clamp qa-member-select-input", scope: :all, email_user: true, placeholder: "Search for members to update or invite")
.form-group
= label_tag :access_level, "Choose a role permission", class: "label-bold"
.select-wrapper
@@ -17,5 +17,5 @@
= label_tag :expires_at, 'Access expiration date', class: 'label-bold'
= text_field_tag :expires_at, nil, class: 'form-control js-access-expiration-date', placeholder: 'Expiration date'
%i.clear-icon.js-clear-input
- = f.submit "Add to project", class: "btn btn-success"
+ = f.submit "Add to project", class: "btn btn-success qa-add-member-button"
= link_to "Import", import_project_project_members_path(@project), class: "btn btn-default", title: "Import members from another project"
diff --git a/app/views/projects/project_members/_team.html.haml b/app/views/projects/project_members/_team.html.haml
index 0c5a187f208..9682f8ac922 100644
--- a/app/views/projects/project_members/_team.html.haml
+++ b/app/views/projects/project_members/_team.html.haml
@@ -14,5 +14,5 @@
%button.member-search-btn{ type: "submit", "aria-label" => "Submit search" }
= icon("search")
= render 'shared/members/sort_dropdown'
- %ul.content-list.members-list
+ %ul.content-list.members-list.qa-members-list
= render partial: 'shared/members/member', collection: members, as: :member
diff --git a/app/views/shared/_allow_request_access.html.haml b/app/views/shared/_allow_request_access.html.haml
index 92268e74b1e..a50f1877d08 100644
--- a/app/views/shared/_allow_request_access.html.haml
+++ b/app/views/shared/_allow_request_access.html.haml
@@ -1,6 +1,8 @@
+- label_class = local_assigns.fetch(:bold_label, false) ? 'font-weight-bold' : ''
+
.form-check
= form.check_box :request_access_enabled, class: 'form-check-input'
= form.label :request_access_enabled, class: 'form-check-label' do
- %strong Allow users to request access
+ %span{ class: label_class }= _('Allow users to request access')
%br
- %span.descr Allow users to request access if visibility is public or internal.
+ %span.text-muted= _('Allow users to request access if visibility is public or internal.')
diff --git a/app/views/shared/_old_visibility_level.html.haml b/app/views/shared/_old_visibility_level.html.haml
new file mode 100644
index 00000000000..fd576e4fbea
--- /dev/null
+++ b/app/views/shared/_old_visibility_level.html.haml
@@ -0,0 +1,6 @@
+.form-group.row
+ .col-sm-2.col-form-label
+ = _('Visibility level')
+ = link_to icon('question-circle'), help_page_path("public_access/public_access")
+ .col-sm-10
+ = render 'shared/visibility_level', f: f, visibility_level: visibility_level, can_change_visibility_level: can_change_visibility_level, form_model: form_model, with_label: with_label
diff --git a/app/views/shared/_visibility_level.html.haml b/app/views/shared/_visibility_level.html.haml
index ba37b37a3b1..2f42a877beb 100644
--- a/app/views/shared/_visibility_level.html.haml
+++ b/app/views/shared/_visibility_level.html.haml
@@ -1,17 +1,19 @@
- with_label = local_assigns.fetch(:with_label, true)
-.form-group.row.visibility-level-setting
+.form-group.visibility-level-setting
- if with_label
- = f.label :visibility_level, class: 'col-form-label col-sm-2 pt-0' do
- Visibility Level
- = link_to icon('question-circle'), help_page_path("public_access/public_access")
- %div{ :class => (with_label ? "col-sm-10" : "col-sm-12") }
- - if can_change_visibility_level
- = render('shared/visibility_radios', model_method: :visibility_level, form: f, selected_level: visibility_level, form_model: form_model)
- - else
- %div
- %span.info
- = visibility_level_icon(visibility_level)
- %strong
- = visibility_level_label(visibility_level)
- .light= visibility_level_description(visibility_level, form_model)
+ = f.label :visibility_level, _('Visibility level'), class: 'label-bold append-bottom-0'
+ %p
+ = _('Who can see this group?')
+ - visibility_docs_path = help_page_path('public_access/public_access')
+ - docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: visibility_docs_path }
+ = s_('Check the %{docs_link_start}documentation%{docs_link_end}.').html_safe % { docs_link_start: docs_link_start, docs_link_end: '</a>'.html_safe }
+ - if can_change_visibility_level
+ = render('shared/visibility_radios', model_method: :visibility_level, form: f, selected_level: visibility_level, form_model: form_model)
+ - else
+ %div
+ %span.info
+ = visibility_level_icon(visibility_level)
+ %strong
+ = visibility_level_label(visibility_level)
+ .light= visibility_level_description(visibility_level, form_model)
diff --git a/app/views/shared/projects/_list.html.haml b/app/views/shared/projects/_list.html.haml
index e1da05d8f08..06eb3d03e31 100644
--- a/app/views/shared/projects/_list.html.haml
+++ b/app/views/shared/projects/_list.html.haml
@@ -8,6 +8,7 @@
- user = local_assigns[:user]
- show_last_commit_as_description = false unless local_assigns[:show_last_commit_as_description] == true
- remote = false unless local_assigns[:remote] == true
+- skip_pagination = false unless local_assigns[:skip_pagination] == true
.js-projects-list-holder
- if any_projects?(projects)
@@ -25,6 +26,6 @@
= icon('lock fw', base: 'circle', class: 'fa-lg private-fork-icon')
%strong= pluralize(@private_forks_count, 'private fork')
%span &nbsp;you have no access to.
- = paginate_collection(projects, remote: remote)
+ = paginate_collection(projects, remote: remote) unless skip_pagination
- else
.nothing-here-block No projects found
diff --git a/app/views/shared/snippets/_form.html.haml b/app/views/shared/snippets/_form.html.haml
index 1b66d3acd40..cf9c3055499 100644
--- a/app/views/shared/snippets/_form.html.haml
+++ b/app/views/shared/snippets/_form.html.haml
@@ -14,7 +14,7 @@
= render 'shared/form_elements/description', model: @snippet, project: @project, form: f
- = render 'shared/visibility_level', f: f, visibility_level: @snippet.visibility_level, can_change_visibility_level: true, form_model: @snippet
+ = render 'shared/old_visibility_level', f: f, visibility_level: @snippet.visibility_level, can_change_visibility_level: true, form_model: @snippet, with_label: false
.file-editor
.form-group.row
diff --git a/changelogs/unreleased/22311-fix-duplicated-key-in-license-management-job.yml b/changelogs/unreleased/22311-fix-duplicated-key-in-license-management-job.yml
new file mode 100644
index 00000000000..ab64a1387d9
--- /dev/null
+++ b/changelogs/unreleased/22311-fix-duplicated-key-in-license-management-job.yml
@@ -0,0 +1,5 @@
+---
+title: "fix duplicated key in license management job auto devops gitlab ci template"
+merge_request: 22311
+author: Adam Lemanski
+type: fixed
diff --git a/changelogs/unreleased/48684-sort-projects-by-stars-in-groups.yml b/changelogs/unreleased/48684-sort-projects-by-stars-in-groups.yml
new file mode 100644
index 00000000000..01681adab24
--- /dev/null
+++ b/changelogs/unreleased/48684-sort-projects-by-stars-in-groups.yml
@@ -0,0 +1,4 @@
+---
+title: Add new sort option "most_stars" to "Group > Children" pages
+merge_request: 22121
+author: Rene Hennig
diff --git a/changelogs/unreleased/48889-message-for-were-merged-into.yml b/changelogs/unreleased/48889-message-for-were-merged-into.yml
new file mode 100644
index 00000000000..552b8826829
--- /dev/null
+++ b/changelogs/unreleased/48889-message-for-were-merged-into.yml
@@ -0,0 +1,5 @@
+---
+title: Fix 'merged with' UI being displayed when merge request has no merge commit
+merge_request: 22022
+author:
+type: fixed
diff --git a/changelogs/unreleased/49417-improve-settings-pages-design-by-prioritizing-content-group-settings.yml b/changelogs/unreleased/49417-improve-settings-pages-design-by-prioritizing-content-group-settings.yml
new file mode 100644
index 00000000000..8ded24a1cd0
--- /dev/null
+++ b/changelogs/unreleased/49417-improve-settings-pages-design-by-prioritizing-content-group-settings.yml
@@ -0,0 +1,5 @@
+---
+title: Update group settings/edit page to new design
+merge_request: 21115
+author:
+type: other
diff --git a/changelogs/unreleased/50185-fix-broken-file-name-navigation.yml b/changelogs/unreleased/50185-fix-broken-file-name-navigation.yml
new file mode 100644
index 00000000000..d1b341af457
--- /dev/null
+++ b/changelogs/unreleased/50185-fix-broken-file-name-navigation.yml
@@ -0,0 +1,5 @@
+---
+title: Fix broken file name navigation on MRs
+merge_request: 22109
+author:
+type: fixed
diff --git a/changelogs/unreleased/51958-fix-mr-discussion-loading.yml b/changelogs/unreleased/51958-fix-mr-discussion-loading.yml
deleted file mode 100644
index f80ee51291d..00000000000
--- a/changelogs/unreleased/51958-fix-mr-discussion-loading.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix loading issue on some merge request discussion
-merge_request: 21982
-author:
-type: fixed
diff --git a/changelogs/unreleased/52361-fix-file-tree-mobile.yml b/changelogs/unreleased/52361-fix-file-tree-mobile.yml
new file mode 100644
index 00000000000..fe978eeca2d
--- /dev/null
+++ b/changelogs/unreleased/52361-fix-file-tree-mobile.yml
@@ -0,0 +1,5 @@
+---
+title: Improve MR file tree in smaller screens
+merge_request: 22273
+author:
+type: fixed
diff --git a/changelogs/unreleased/52421-show-canary-no-canary-in-the-performance-bar.yml b/changelogs/unreleased/52421-show-canary-no-canary-in-the-performance-bar.yml
new file mode 100644
index 00000000000..20e32a2e987
--- /dev/null
+++ b/changelogs/unreleased/52421-show-canary-no-canary-in-the-performance-bar.yml
@@ -0,0 +1,5 @@
+---
+title: Show canary status in the performance bar
+merge_request: 22222
+author:
+type: changed
diff --git a/changelogs/unreleased/52472-pipeline-endpoint-json.yml b/changelogs/unreleased/52472-pipeline-endpoint-json.yml
new file mode 100644
index 00000000000..feff195beb8
--- /dev/null
+++ b/changelogs/unreleased/52472-pipeline-endpoint-json.yml
@@ -0,0 +1,5 @@
+---
+title: Fix caching issue with pipelines URL
+merge_request: 22293
+author:
+type: fixed
diff --git a/changelogs/unreleased/52519-runners-link.yml b/changelogs/unreleased/52519-runners-link.yml
new file mode 100644
index 00000000000..5d904a8b340
--- /dev/null
+++ b/changelogs/unreleased/52519-runners-link.yml
@@ -0,0 +1,5 @@
+---
+title: Fixes stuck block URL linking to documentation instead of settings page
+merge_request: 22286
+author:
+type: fixed
diff --git a/changelogs/unreleased/52532-unable-to-toggle-issuable-sidebar-out-of-collapsed-state.yml b/changelogs/unreleased/52532-unable-to-toggle-issuable-sidebar-out-of-collapsed-state.yml
new file mode 100644
index 00000000000..9abad3d2cd8
--- /dev/null
+++ b/changelogs/unreleased/52532-unable-to-toggle-issuable-sidebar-out-of-collapsed-state.yml
@@ -0,0 +1,5 @@
+---
+title: Allow Issue and Merge Request sidebar to be toggled from collapsed state
+merge_request: 22353
+author:
+type: fixed
diff --git a/changelogs/unreleased/52564-personal-projects-pagination-in-profile-overview-tab-is-broken.yml b/changelogs/unreleased/52564-personal-projects-pagination-in-profile-overview-tab-is-broken.yml
new file mode 100644
index 00000000000..bddc1e16fab
--- /dev/null
+++ b/changelogs/unreleased/52564-personal-projects-pagination-in-profile-overview-tab-is-broken.yml
@@ -0,0 +1,5 @@
+---
+title: Hide pagination for personal projects on profile overview tab
+merge_request: 22321
+author:
+type: other
diff --git a/changelogs/unreleased/52570-erased-block.yml b/changelogs/unreleased/52570-erased-block.yml
new file mode 100644
index 00000000000..6ec295bf81b
--- /dev/null
+++ b/changelogs/unreleased/52570-erased-block.yml
@@ -0,0 +1,5 @@
+---
+title: Fix erased block not being rendered when job was erased
+merge_request: 22294
+author:
+type: fixed
diff --git a/changelogs/unreleased/52608-sidebar.yml b/changelogs/unreleased/52608-sidebar.yml
new file mode 100644
index 00000000000..9eca30f7b95
--- /dev/null
+++ b/changelogs/unreleased/52608-sidebar.yml
@@ -0,0 +1,5 @@
+---
+title: Hides sidebar for job page in mobile
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/52614-update-job-started-check.yml b/changelogs/unreleased/52614-update-job-started-check.yml
new file mode 100644
index 00000000000..60ea237dbf3
--- /dev/null
+++ b/changelogs/unreleased/52614-update-job-started-check.yml
@@ -0,0 +1,5 @@
+---
+title: Fixes triggered/created labeled in job header
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/52618-incorrect-stage-being-shown-in-side-bar-of-job-view-api.yml b/changelogs/unreleased/52618-incorrect-stage-being-shown-in-side-bar-of-job-view-api.yml
new file mode 100644
index 00000000000..fdbde709e77
--- /dev/null
+++ b/changelogs/unreleased/52618-incorrect-stage-being-shown-in-side-bar-of-job-view-api.yml
@@ -0,0 +1,5 @@
+---
+title: Load correct stage in the stages dropdown
+merge_request: 22317
+author:
+type: fixed
diff --git a/changelogs/unreleased/52669-fixes-quick-actions-preview.yml b/changelogs/unreleased/52669-fixes-quick-actions-preview.yml
new file mode 100644
index 00000000000..51b1425d04d
--- /dev/null
+++ b/changelogs/unreleased/52669-fixes-quick-actions-preview.yml
@@ -0,0 +1,5 @@
+---
+title: Fixes close/reopen quick actions preview for issues and merge_requests
+merge_request: 22343
+author: Jacopo Beschi @jacopo-beschi
+type: fixed
diff --git a/changelogs/unreleased/bvl-merge-base-multiple-revisions.yml b/changelogs/unreleased/bvl-merge-base-multiple-revisions.yml
new file mode 100644
index 00000000000..4075e35fce9
--- /dev/null
+++ b/changelogs/unreleased/bvl-merge-base-multiple-revisions.yml
@@ -0,0 +1,5 @@
+---
+title: Allow finding the common ancestor for multiple revisions through the API
+merge_request: 22295
+author:
+type: changed
diff --git a/changelogs/unreleased/da-fix-does-not-import-projects-over-ssh.yml b/changelogs/unreleased/da-fix-does-not-import-projects-over-ssh.yml
new file mode 100644
index 00000000000..5867b1f0981
--- /dev/null
+++ b/changelogs/unreleased/da-fix-does-not-import-projects-over-ssh.yml
@@ -0,0 +1,5 @@
+---
+title: Does not allow a SSH URI when importing new projects
+merge_request: 22309
+author:
+type: fixed
diff --git a/changelogs/unreleased/enable-frozen-string-lib-gitlab.yml b/changelogs/unreleased/enable-frozen-string-lib-gitlab.yml
new file mode 100644
index 00000000000..4a216c46d38
--- /dev/null
+++ b/changelogs/unreleased/enable-frozen-string-lib-gitlab.yml
@@ -0,0 +1,5 @@
+---
+title: Enable some frozen string in lib/gitlab
+merge_request:
+author: gfyoung
+type: performance
diff --git a/changelogs/unreleased/even-more-frozen-string-lib.yml b/changelogs/unreleased/even-more-frozen-string-lib.yml
new file mode 100644
index 00000000000..3f5fd7710aa
--- /dev/null
+++ b/changelogs/unreleased/even-more-frozen-string-lib.yml
@@ -0,0 +1,5 @@
+---
+title: Enable even more frozen string in lib/**/*.rb
+merge_request:
+author: gfyoung
+type: performance
diff --git a/changelogs/unreleased/feature-improved-branch-filter-sorting.yml b/changelogs/unreleased/feature-improved-branch-filter-sorting.yml
new file mode 100644
index 00000000000..539c297e0dd
--- /dev/null
+++ b/changelogs/unreleased/feature-improved-branch-filter-sorting.yml
@@ -0,0 +1,6 @@
+---
+title: Improving branch filter sorting by listing exact matches first and added support
+ for begins_with (^) and ends_with ($) matching.
+merge_request: 22166
+author: Jason Rutherford
+type: changed
diff --git a/changelogs/unreleased/fl-update-svgs.yml b/changelogs/unreleased/fl-update-svgs.yml
new file mode 100644
index 00000000000..e6e76617df1
--- /dev/null
+++ b/changelogs/unreleased/fl-update-svgs.yml
@@ -0,0 +1,5 @@
+---
+title: Updates svg dependency
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/gt-update-application-copy-secret-to-clipboard-data.yml b/changelogs/unreleased/gt-update-application-copy-secret-to-clipboard-data.yml
new file mode 100644
index 00000000000..7205c138777
--- /dev/null
+++ b/changelogs/unreleased/gt-update-application-copy-secret-to-clipboard-data.yml
@@ -0,0 +1,5 @@
+---
+title: Update copy to clipboard button data for application secret
+merge_request: 22268
+author: George Tsiolis
+type: fixed
diff --git a/changelogs/unreleased/replace-i-to-icons-in-vue-components.yml b/changelogs/unreleased/replace-i-to-icons-in-vue-components.yml
new file mode 100644
index 00000000000..6de57b04338
--- /dev/null
+++ b/changelogs/unreleased/replace-i-to-icons-in-vue-components.yml
@@ -0,0 +1,5 @@
+---
+title: Replace i to icons in vue components
+merge_request: 20748
+author: George Tsiolis
+type: changed
diff --git a/changelogs/unreleased/sh-remove-koding.yml b/changelogs/unreleased/sh-remove-koding.yml
new file mode 100644
index 00000000000..2c4e8c76a61
--- /dev/null
+++ b/changelogs/unreleased/sh-remove-koding.yml
@@ -0,0 +1,5 @@
+---
+title: Remove Koding integration and documentation
+merge_request: 22334
+author:
+type: removed
diff --git a/changelogs/unreleased/zj-remove-linguist.yml b/changelogs/unreleased/zj-remove-linguist.yml
new file mode 100644
index 00000000000..5719512c4cc
--- /dev/null
+++ b/changelogs/unreleased/zj-remove-linguist.yml
@@ -0,0 +1,5 @@
+---
+title: Remove Linguist gem, reducing Rails memory usage by 128MB per process
+merge_request: 21008
+author:
+type: changed
diff --git a/config/routes.rb b/config/routes.rb
index 5c093aa5626..c081ca9672a 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -81,9 +81,6 @@ Rails.application.routes.draw do
draw :instance_statistics
end
- # Koding route
- get 'koding' => 'koding#index'
-
draw :api
draw :sidekiq
draw :help
diff --git a/config/unicorn.rb.example b/config/unicorn.rb.example
index 020e9a00d87..e06cce3e97a 100644
--- a/config/unicorn.rb.example
+++ b/config/unicorn.rb.example
@@ -95,7 +95,7 @@ end
before_fork do |server, worker|
# the following is highly recommended for Rails + "preload_app true"
# as there's no need for the master process to hold a connection
- defined?(ActiveRecord::Base) and
+ defined?(ActiveRecord::Base) &&
ActiveRecord::Base.connection.disconnect!
# The following is only recommended for memory/DB-constrained
@@ -133,7 +133,7 @@ after_fork do |server, worker|
# server.listen(addr, :tries => -1, :delay => 5, :tcp_nopush => true)
# the following is *required* for Rails + "preload_app true",
- defined?(ActiveRecord::Base) and
+ defined?(ActiveRecord::Base) &&
ActiveRecord::Base.establish_connection
# reset prometheus client, this will cause any opened metrics files to be closed
diff --git a/config/unicorn.rb.example.development b/config/unicorn.rb.example.development
index 5712549a66d..f31df66015a 100644
--- a/config/unicorn.rb.example.development
+++ b/config/unicorn.rb.example.development
@@ -7,7 +7,7 @@ check_client_connection false
before_fork do |server, worker|
# the following is highly recommended for Rails + "preload_app true"
# as there's no need for the master process to hold a connection
- defined?(ActiveRecord::Base) and
+ defined?(ActiveRecord::Base) &&
ActiveRecord::Base.connection.disconnect!
if /darwin/ =~ RUBY_PLATFORM
@@ -27,6 +27,6 @@ after_fork do |server, worker|
require 'rbtrace' if ENV['ENABLE_RBTRACE']
# the following is *required* for Rails + "preload_app true",
- defined?(ActiveRecord::Base) and
+ defined?(ActiveRecord::Base) &&
ActiveRecord::Base.establish_connection
end
diff --git a/db/post_migrate/20181013005024_remove_koding_from_application_settings.rb b/db/post_migrate/20181013005024_remove_koding_from_application_settings.rb
new file mode 100644
index 00000000000..938a32e4e98
--- /dev/null
+++ b/db/post_migrate/20181013005024_remove_koding_from_application_settings.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class RemoveKodingFromApplicationSettings < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ remove_column :application_settings, :koding_enabled
+ remove_column :application_settings, :koding_url
+ end
+
+ def down
+ add_column :application_settings, :koding_enabled, :boolean # rubocop:disable Migration/SaferBooleanColumn
+ add_column :application_settings, :koding_url, :string
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 5b44bbb2756..3f3bec0ce04 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20181008200441) do
+ActiveRecord::Schema.define(version: 20181013005024) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -104,8 +104,6 @@ ActiveRecord::Schema.define(version: 20181008200441) do
t.boolean "domain_blacklist_enabled", default: false
t.text "domain_blacklist"
t.boolean "usage_ping_enabled", default: true, null: false
- t.boolean "koding_enabled"
- t.string "koding_url"
t.text "sign_in_text_html"
t.text "help_page_text_html"
t.text "shared_runners_text_html"
diff --git a/doc/README.md b/doc/README.md
index 7548240bfef..03371226041 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -33,7 +33,7 @@ provides solutions for all the stages of the DevOps lifecycle:
[plan](#plan), [create](#create), [verify](#verify), [package](#package),
[release](#release), [configure](#configure), [monitor](#monitor).
-![DevOps Lifecycle](img/devops_lifecycle.png)
+<img class="image-noshadow" src="img/devops_lifecycle.png" alt="DevOps Lifecycle">
### Plan
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index b5e2b5448f7..e1b2a0a24eb 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -25,15 +25,13 @@ gitaly['prometheus_listen_addr'] = 'localhost:9236'
```
To change a Gitaly setting in installations from source you can edit
-`/home/git/gitaly/config.toml`.
+`/home/git/gitaly/config.toml`. Changes will be applied when you run
+`service gitlab restart`.
```toml
prometheus_listen_addr = "localhost:9236"
```
-Changes to `/home/git/gitaly/config.toml` are applied when you run `service
-gitlab restart`.
-
## Client-side GRPC logs
Gitaly uses the [gRPC](https://grpc.io/) RPC framework. The Ruby gRPC
diff --git a/doc/administration/integration/koding.md b/doc/administration/integration/koding.md
deleted file mode 100644
index def0add0061..00000000000
--- a/doc/administration/integration/koding.md
+++ /dev/null
@@ -1,246 +0,0 @@
-# Koding & GitLab
-
-> **Notes:**
-> - **As of GitLab 10.0, the Koding integration is deprecated and will be removed
-> in a future version. The option to configure it is removed from GitLab's admin
-> area.**
-> - [Introduced][ce-5909] in GitLab 8.11.
-
-This document will guide you through installing and configuring Koding with
-GitLab.
-
-First of all, to be able to use Koding and GitLab together you will need public
-access to your server. This allows you to use single sign-on from GitLab to
-Koding and using vms from cloud providers like AWS. Koding has a registry for
-VMs, called Kontrol and it runs on the same server as Koding itself, VMs from
-cloud providers register themselves to Kontrol via the agent that we put into
-provisioned VMs. This agent is called Klient and it provides Koding to access
-and manage the target machine.
-
-Kontrol and Klient are based on another technology called
-[Kite](https://github.com/koding/kite), that we have written at Koding. Which is a
-microservice framework that allows you to develop microservices easily.
-
-## Requirements
-
-### Hardware
-
-Minimum requirements are;
-
- - 2 cores CPU
- - 3G RAM
- - 10G Storage
-
-If you plan to use AWS to install Koding it is recommended that you use at
-least a `c3.xlarge` instance.
-
-### Software
-
- - [Git](https://git-scm.com)
- - [Docker](https://www.docker.com)
- - [docker-compose](https://www.docker.com/products/docker-compose)
-
-Koding can run on most of the UNIX based operating systems, since it's shipped
-as containerized with Docker support, it can work on any operating system that
-supports Docker.
-
-Required services are:
-
-- **PostgreSQL** - Kontrol and Service DB provider
-- **MongoDB** - Main DB provider the application
-- **Redis** - In memory DB used by both application and services
-- **RabbitMQ** - Message Queue for both application and services
-
-which are also provided as a Docker container by Koding.
-
-
-## Getting Started with Development Versions
-
-
-### Koding
-
-You can run `docker-compose` environment for developing koding by
-executing commands in the following snippet.
-
-```bash
-git clone https://github.com/koding/koding.git
-cd koding
-docker-compose -f docker-compose-init.yml run init
-docker-compose up
-```
-
-This should start koding on `localhost:8090`.
-
-By default there is no team exists in Koding DB. You'll need to create a team
-called `gitlab` which is the default team name for GitLab integration in the
-configuration. To make things in order it's recommended to create the `gitlab`
-team first thing after setting up Koding.
-
-
-### GitLab
-
-To install GitLab to your environment for development purposes it's recommended
-to use GitLab Development Kit which you can get it from
-[here](https://gitlab.com/gitlab-org/gitlab-development-kit).
-
-After all those steps, gitlab should be running on `localhost:3000`
-
-
-## Integration
-
-Integration includes following components;
-
- - Single Sign On with OAuth from GitLab to Koding
- - System Hook integration for handling GitLab events on Koding
- (`project_created`, `user_joined` etc.)
- - Service endpoints for importing/executing stacks from GitLab to Koding
- (`Run/Try on IDE (Koding)` buttons on GitLab Projects, Issues, MRs)
-
-As it's pointed out before, you will need public access to this machine that
-you've installed Koding and GitLab on. Better to use a domain but a static IP
-is also fine.
-
-For IP based installation you can use [nip.io](https://nip.io) service which is
-free and provides DNS resolution to IP based requests like following;
-
- - 127.0.0.1.nip.io -> resolves to 127.0.0.1
- - foo.bar.baz.127.0.0.1.nip.io -> resolves to 127.0.0.1
- - and so on...
-
-As Koding needs subdomains for team names; `foo.127.0.0.1.nip.io` requests for
-a running koding instance on `127.0.0.1` server will be handled as `foo` team
-requests.
-
-
-### GitLab Side
-
-You need to enable Koding integration from Settings under Admin Area. To do
-that login with an Admin account and do followings;
-
-- open [http://127.0.0.1:3000/admin/application_settings](http://127.0.0.1:3000/admin/application_settings)
-- scroll to bottom of the page until Koding section
-- check `Enable Koding` checkbox
-- provide GitLab team page for running Koding instance as `Koding URL`*
- * For `Koding URL` you need to provide the gitlab integration enabled team on
-your Koding installation. Team called `gitlab` has integration on Koding out
-of the box, so if you didn't change anything your team on Koding should be
-`gitlab`.
-
-So, if your Koding is running on `http://1.2.3.4.nip.io:8090` your URL needs
-to be `http://gitlab.1.2.3.4.nip.io:8090`. You need to provide the same host
-with your Koding installation here.
-
-
-#### Registering Koding for OAuth integration
-
-We need `Application ID` and `Secret` to enable login to Koding via GitLab
-feature and to do that you need to register running Koding as a new application
-to your running GitLab application. Follow
-[these](http://docs.gitlab.com/ce/integration/oauth_provider.html) steps to
-enable this integration.
-
-Redirect URI should be `http://gitlab.127.0.0.1:8090/-/oauth/gitlab/callback`
-which again you need to _replace `127.0.0.1` with your instance public IP._
-
-Take a copy of `Application ID` and `Secret` that is generated by the GitLab
-application, we will need those on _Koding Part_ of this guide.
-
-
-#### Registering system hooks to Koding (optional)
-
-Koding can take actions based on the events generated by GitLab application.
-This feature is still in progress and only following events are processed by
-Koding at the moment;
-
- - user_create
- - user_destroy
-
-All system events are handled but not implemented on Koding side.
-
-To enable this feature you need to provide a `URL` and a `Secret Token` to your
-GitLab application. Open your admin area on your GitLab app from
-[http://127.0.0.1:3000/admin/hooks](http://127.0.0.1:3000/admin/hooks)
-and provide `URL` as `http://gitlab.127.0.0.1:8090/-/api/gitlab` which is the
-endpoint to handle GitLab events on Koding side. Provide a `Secret Token` and
-keep a copy of it, we will need it on _Koding Part_ of this guide.
-
-_(replace `127.0.0.1` with your instance public IP)_
-
-
-### Koding Part
-
-If you followed the steps in GitLab part we should have followings to enable
-Koding part integrations;
-
- - `Application ID` and `Secret` for OAuth integration
- - `Secret Token` for system hook integration
- - Public address of running GitLab instance
-
-
-#### Start Koding with GitLab URL
-
-Now we need to configure Koding with all this information to get things ready.
-If it's already running please stop koding first.
-
-##### From command-line
-
-Replace followings with the ones you got from GitLab part of this guide;
-
-```bash
-cd koding
-docker-compose run \
- --service-ports backend \
- /opt/koding/scripts/bootstrap-container build \
- --host=**YOUR_IP**.nip.io \
- --gitlabHost=**GITLAB_IP** \
- --gitlabPort=**GITLAB_PORT** \
- --gitlabToken=**SECRET_TOKEN** \
- --gitlabAppId=**APPLICATION_ID** \
- --gitlabAppSecret=**SECRET**
-```
-
-##### By updating configuration
-
-Alternatively you can update `gitlab` section on
-`config/credentials.default.coffee` like following;
-
-```
-gitlab =
- host: '**GITLAB_IP**'
- port: '**GITLAB_PORT**'
- applicationId: '**APPLICATION_ID**'
- applicationSecret: '**SECRET**'
- team: 'gitlab'
- redirectUri: ''
- systemHookToken: '**SECRET_TOKEN**'
- hooksEnabled: yes
-```
-
-and start by only providing the `host`;
-
-```bash
-cd koding
-docker-compose run \
- --service-ports backend \
- /opt/koding/scripts/bootstrap-container build \
- --host=**YOUR_IP**.nip.io \
-```
-
-#### Enable Single Sign On
-
-Once you restarted your Koding and logged in with your username and password
-you need to activate oauth authentication for your user. To do that
-
- - Navigate to Dashboard on Koding from;
- `http://gitlab.**YOUR_IP**.nip.io:8090/Home/my-account`
- - Scroll down to Integrations section
- - Click on toggle to turn On integration in GitLab integration section
-
-This will redirect you to your GitLab instance and will ask your permission (
-if you are not logged in to GitLab at this point you will be redirected after
-login) once you accept you will be redirected to your Koding instance.
-
-From now on you can login by using `SIGN IN WITH GITLAB` button on your Login
-screen in your Koding instance.
-
-[ce-5909]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5909
diff --git a/doc/administration/integration/plantuml.md b/doc/administration/integration/plantuml.md
index 293036f2f4b..b61c5409a56 100644
--- a/doc/administration/integration/plantuml.md
+++ b/doc/administration/integration/plantuml.md
@@ -80,10 +80,10 @@ our AsciiDoc snippets, wikis and repos using delimited blocks:
```
[plantuml, format="png", id="myDiagram", width="200px"]
- --
+ ----
Bob->Alice : hello
Alice -> Bob : Go Away
- --
+ ----
```
- **reStructuredText**
diff --git a/doc/administration/job_artifacts.md b/doc/administration/job_artifacts.md
index 757865ea2c5..2feac1fd3b0 100644
--- a/doc/administration/job_artifacts.md
+++ b/doc/administration/job_artifacts.md
@@ -98,7 +98,7 @@ _The artifacts are stored by default in
If you don't want to use the local disk where GitLab is installed to store the
artifacts, you can use an object storage like AWS S3 instead.
This configuration relies on valid AWS credentials to be configured already.
-Use an [Object storage option][os] like AWS S3 to store job artifacts.
+Use an object storage option like AWS S3 to store job artifacts.
### Object Storage Settings
@@ -315,4 +315,3 @@ memory and disk I/O.
[reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab"
[restart gitlab]: restart_gitlab.md#installations-from-source "How to restart GitLab"
[gitlab workhorse]: https://gitlab.com/gitlab-org/gitlab-workhorse "GitLab Workhorse repository"
-[os]: https://docs.gitlab.com/administration/job_artifacts.html#using-object-storage
diff --git a/doc/api/events.md b/doc/api/events.md
index cd84b32029e..ccac5b8bb60 100644
--- a/doc/api/events.md
+++ b/doc/api/events.md
@@ -71,7 +71,7 @@ Parameters:
Example request:
```
-curl --header "PRIVATE-TOKEN 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/events&target_type=issue&action=created&after=2017-01-31&before=2017-03-01
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/events&target_type=issue&action=created&after=2017-01-31&before=2017-03-01
```
Example response:
@@ -276,7 +276,7 @@ Parameters:
Example request:
```
-curl --header "PRIVATE-TOKEN 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:project_id/events&target_type=issue&action=created&after=2017-01-31&before=2017-03-01
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:project_id/events&target_type=issue&action=created&after=2017-01-31&before=2017-03-01
```
Example response:
diff --git a/doc/api/repositories.md b/doc/api/repositories.md
index a4fdeca162e..f5ac3816fe5 100644
--- a/doc/api/repositories.md
+++ b/doc/api/repositories.md
@@ -216,7 +216,7 @@ GET /projects/:id/repository/merge_base
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
-| `refs` | array | yes | The refs to find the common ancestor of, for now only 2 refs are supported |
+| `refs` | array | yes | The refs to find the common ancestor of, multiple refs can be passed |
```bash
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/repository/merge_base?refs[]=304d257dcb821665ab5110318fc58a007bd104ed&refs[]=0031876facac3f2b2702a0e53a26e89939a42209"
diff --git a/doc/api/settings.md b/doc/api/settings.md
index 4482030888d..9b38e3a4eb7 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -1,3 +1,7 @@
+---
+table_display_block: true
+---
+
# Application settings API
These API calls allow you to read and modify GitLab instance
@@ -45,8 +49,6 @@ Example response:
"sign_in_text" : null,
"container_registry_token_expire_delay": 5,
"repository_storages": ["default"],
- "koding_enabled": false,
- "koding_url": null,
"plantuml_enabled": false,
"plantuml_url": null,
"terminal_max_session_time": 0,
@@ -103,8 +105,6 @@ Example response:
"after_sign_out_path": "",
"container_registry_token_expire_delay": 5,
"repository_storages": ["default"],
- "koding_enabled": false,
- "koding_url": null,
"plantuml_enabled": false,
"plantuml_url": null,
"terminal_max_session_time": 0,
@@ -175,8 +175,6 @@ are listed in the descriptions of the relevant settings.
| `html_emails_enabled` | boolean | no | Enable HTML emails. |
| `instance_statistics_visibility_private` | boolean | no | When set to `true` Instance statistics will only be available to admins. |
| `import_sources` | array of strings | no | Sources to allow project import from, possible values: `github`, `bitbucket`, `gitlab`, `google_code`, `fogbugz`, `git`, and `gitlab_project`. |
-| `koding_enabled` | boolean | no | (If enabled, requires: `koding_url`) Enable Koding integration. Default is `false`. |
-| `koding_url` | string | required by: `koding_enabled` | The Koding instance URL for integration. |
| `max_artifacts_size` | integer | no | Maximum artifacts size in MB |
| `max_attachment_size` | integer | no | Limit attachment size in MB |
| `max_pages_size` | integer | no | Maximum size of pages repositories in MB |
diff --git a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
index ab429e0ded3..70020d461d9 100644
--- a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
+++ b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
@@ -125,7 +125,7 @@ They can be added per project by navigating to the project's **Settings** > **CI
To the field **KEY**, add the name `SSH_PRIVATE_KEY`, and to the **VALUE** field, paste the private key you've copied earlier.
We'll use this variable in the `.gitlab-ci.yml` later, to easily connect to our remote server as the deployer user without entering its password.
-We also need to add the public key to **Project** > **Settings** > **Repository** as [Deploy Keys](../../../ssh/README.md/#deploy-keys), which gives us the ability to access our repository from the server through [SSH protocol](../../../gitlab-basics/command-line-commands.md/#start-working-on-your-project).
+We also need to add the public key to **Project** > **Settings** > **Repository** as [Deploy Keys](../../../ssh/README.md#deploy-keys), which gives us the ability to access our repository from the server through [SSH protocol](../../../gitlab-basics/command-line-commands.md#start-working-on-your-project).
```bash
@@ -378,7 +378,7 @@ These are persistent data and will be shared to every new release.
Now, we would need to deploy our app by running `envoy run deploy`, but it won't be necessary since GitLab can handle that for us with CI's [environments](../../environments.md), which will be described [later](#setting-up-gitlab-ci-cd) in this tutorial.
Now it's time to commit [Envoy.blade.php](https://gitlab.com/mehranrasulian/laravel-sample/blob/master/Envoy.blade.php) and push it to the `master` branch.
-To keep things simple, we commit directly to `master`, without using [feature-branches](../../../workflow/gitlab_flow.md/#github-flow-as-a-simpler-alternative) since collaboration is beyond the scope of this tutorial.
+To keep things simple, we commit directly to `master`, without using [feature-branches](../../../workflow/gitlab_flow.md#github-flow-as-a-simpler-alternative) since collaboration is beyond the scope of this tutorial.
In a real world project, teams may use [Issue Tracker](../../../user/project/issues/index.md) and [Merge Requests](../../../user/project/merge_requests/index.md) to move their code across branches:
```bash
@@ -398,7 +398,7 @@ In the case you're not familiar with Docker, refer to [How to Automate Docker De
To be able to build, test, and deploy our app with GitLab CI/CD, we need to prepare our work environment.
To do that, we'll use a Docker image which has the minimum requirements that a Laravel app needs to run.
-[There are other ways](../php.md/#test-php-projects-using-the-docker-executor) to do that as well, but they may lead our builds run slowly, which is not what we want when there are faster options to use.
+[There are other ways](../php.md#test-php-projects-using-the-docker-executor) to do that as well, but they may lead our builds run slowly, which is not what we want when there are faster options to use.
With Docker images our builds run incredibly faster!
@@ -536,7 +536,7 @@ That's a lot to take in, isn't it? Let's run through it step by step.
[GitLab Runners](../../runners/README.md) run the script defined by `.gitlab-ci.yml`.
The `image` keyword tells the Runners which image to use.
-The `services` keyword defines additional images [that are linked to the main image](../../docker/using_docker_images.md/#what-is-a-service).
+The `services` keyword defines additional images [that are linked to the main image](../../docker/using_docker_images.md#what-is-a-service).
Here we use the container image we created before as our main image and also use MySQL 5.7 as a service.
```yaml
@@ -560,7 +560,7 @@ So we should adjust the configuration of MySQL instance by defining `MYSQL_DATAB
Find out more about MySQL variables at the [official MySQL Docker Image](https://hub.docker.com/r/_/mysql/).
Also set the variables `DB_HOST` to `mysql` and `DB_USERNAME` to `root`, which are Laravel specific variables.
-We define `DB_HOST` as `mysql` instead of `127.0.0.1`, as we use MySQL Docker image as a service which [is linked to the main Docker image](../../docker/using_docker_images.md/#how-services-are-linked-to-the-build).
+We define `DB_HOST` as `mysql` instead of `127.0.0.1`, as we use MySQL Docker image as a service which [is linked to the main Docker image](../../docker/using_docker_images.md#how-services-are-linked-to-the-build).
```yaml
...
@@ -602,7 +602,7 @@ unit_test:
#### Deploy to production
The job `deploy_production` will deploy the app to the production server.
-To deploy our app with Envoy, we had to set up the `$SSH_PRIVATE_KEY` variable as an [SSH private key](../../ssh_keys/README.md/#ssh-keys-when-using-the-docker-executor).
+To deploy our app with Envoy, we had to set up the `$SSH_PRIVATE_KEY` variable as an [SSH private key](../../ssh_keys/README.md#ssh-keys-when-using-the-docker-executor).
If the SSH keys have added successfully, we can run Envoy.
As mentioned before, GitLab supports [Continuous Delivery](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#continuous-delivery) methods as well.
diff --git a/doc/ci/examples/php.md b/doc/ci/examples/php.md
index df4805ea7ac..c1048f3d2e3 100644
--- a/doc/ci/examples/php.md
+++ b/doc/ci/examples/php.md
@@ -20,7 +20,7 @@ build environment.
Let's first specify the PHP image that will be used for the job process
(you can read more about what an image means in the Runner's lingo reading
-about [Using Docker images](../docker/using_docker_images.md#what-is-image)).
+about [Using Docker images](../docker/using_docker_images.md#what-is-an-image)).
Start by adding the image to your `.gitlab-ci.yml`:
diff --git a/doc/ci/pipelines.md b/doc/ci/pipelines.md
index 44589500eb0..371703a12c8 100644
--- a/doc/ci/pipelines.md
+++ b/doc/ci/pipelines.md
@@ -197,9 +197,9 @@ stage has a job with a manual action.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21767) in GitLab 11.4.
-When you do not want to run a job immediately, you can [delay the job to run after a certain period](yaml/README.md#delayed).
+When you do not want to run a job immediately, you can [delay the job to run after a certain period](yaml/README.md#when-delayed).
This is especially useful for timed incremental rollout that new code is rolled out gradually.
-For example, if you start rolling out new code and users do not experience trouble, GitLab automatically completes the deployment from 0% to 100%.
+For example, if you start rolling out new code and users do not experience trouble, GitLab automatically completes the deployment from 0% to 100%.
Alternatively, if you start rolling out and you noticed that a few users experience trouble with the version,
you can stop the timed incremental rollout by canceling the pipeline, and [rolling](environments.md#rolling-back-changes) it back to the stable version.
diff --git a/doc/ci/triggers/README.md b/doc/ci/triggers/README.md
index cf92d90ba30..bffb0121603 100644
--- a/doc/ci/triggers/README.md
+++ b/doc/ci/triggers/README.md
@@ -2,7 +2,7 @@
> **Notes**:
>
-> - [Introduced][ci-229] in GitLab CE 7.14.
+> - [Introduced](https://about.gitlab.com/2015/08/22/gitlab-7-14-released/) in GitLab 7.14.
> - GitLab 8.12 has a completely redesigned job permissions system. Read all
> about the [new model and its implications](../../user/project/new_ci_build_permissions_model.md#job-triggers).
@@ -154,10 +154,10 @@ This information is also exposed in the UI.
Using trigger variables can be proven useful for a variety of reasons:
-* Identifiable jobs. Since the variable is exposed in the UI you can know
+- Identifiable jobs. Since the variable is exposed in the UI you can know
why the rebuild was triggered if you pass a variable that explains the
purpose.
-* Conditional job processing. You can have conditional jobs that run whenever
+- Conditional job processing. You can have conditional jobs that run whenever
a certain variable is present.
Consider the following `.gitlab-ci.yml` where we set three
@@ -221,7 +221,6 @@ removed with one of the future versions of GitLab. You are advised to
[take ownership](#taking-ownership) of any legacy triggers.
[ee-2017]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/2017
-[ci-229]: https://gitlab.com/gitlab-org/gitlab-ci/merge_requests/229
[ee]: https://about.gitlab.com/pricing/
[variables]: ../variables/README.md
[predef]: ../variables/README.md#predefined-variables-environment-variables
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index f0738252640..24d60a0cdcc 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -415,7 +415,7 @@ Four keys are now available: `refs`, `kubernetes` and `variables` and `changes`.
Refs strategy equals to simplified only/except configuration, whereas
kubernetes strategy accepts only `active` keyword.
-### `variables`
+### `only:variables`
`variables` keyword is used to define variables expressions. In other words
you can use predefined variables / project / group or
@@ -460,7 +460,7 @@ end-to-end:
Learn more about variables expressions on [a separate page][variables-expressions].
-### `changes`
+### `only:changes`
Using `changes` keyword with `only` or `except` makes it possible to define if
a job should be created based on files modified by a git push event.
diff --git a/doc/development/README.md b/doc/development/README.md
index 43d3865da0e..14dfe8eb1f3 100644
--- a/doc/development/README.md
+++ b/doc/development/README.md
@@ -8,7 +8,7 @@ description: 'Learn how to contribute to GitLab.'
## Get started!
- Set up GitLab's development environment with [GitLab Development Kit (GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/README.md)
-- [GitLab contributing guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md)
+- [GitLab contributing guide](contributing/index.md)
- [Architecture](architecture.md) of GitLab
- [Rake tasks](rake_tasks.md) for development
@@ -50,6 +50,7 @@ description: 'Learn how to contribute to GitLab.'
- [Permissions](permissions.md)
- [Prometheus metrics](prometheus_metrics.md)
- [Guidelines for reusing abstractions](reusing_abstractions.md)
+- [DeclarativePolicy framework](policies.md)
## Performance guides
diff --git a/doc/development/code_review.md b/doc/development/code_review.md
index edf0b6f46df..87437dd7720 100644
--- a/doc/development/code_review.md
+++ b/doc/development/code_review.md
@@ -29,7 +29,7 @@ There are a few rules to get your merge request accepted:
to ask one of the [Merge request coaches][team].
1. It is recommended that you assign a maintainer that is from a different team than your own.
This ensures that all code across GitLab is consistent and can be easily understood by all contributors.
-
+
1. Keep in mind that maintainers are also going to perform a final code review.
The ideal scenario is that the reviewer has already addressed any concerns
the maintainer would have found, and the maintainer only has to perform the
@@ -97,6 +97,20 @@ first time.
branch. Do not squash until the branch is ready to merge. Reviewers should be
able to read individual updates based on their earlier feedback.
+### Assigning a merge request for a review
+
+If you want to have your merge request reviewed you can assign it to any reviewer. The list of reviewers can be found on [Engineering projects](https://about.gitlab.com/handbook/engineering/projects/) page.
+
+You can also use `ready for review` label. That means that your merge request is ready to be reviewed and any reviewer can pick it. It is recommended to use that label only if there isn't time pressure and make sure the merge request is assigned to a reviewer.
+
+When your merge request was reviewed and can be passed to a maintainer you can either pick a specific maintainer or use a label `ready for merge`.
+
+It is responsibility of the author of a merge request that the merge request is reviewed. If it stays in `ready for review` state too long it is recommended to assign it to a specific reviewer.
+
+### List of merge requests ready for review
+
+Developers who have capacity can regularly check the list of [merge requests to review](https://gitlab.com/groups/gitlab-org/-/merge_requests?scope=all&utf8=%E2%9C%93&state=opened&label_name%5B%5D=ready%20for%20review&assignee_id=0) and assign any merge request they want to review.
+
### Reviewing code
Understand why the change is necessary (fixes a bug, improves the user
diff --git a/doc/development/contributing/community_roles.md b/doc/development/contributing/community_roles.md
index c508969f7f4..b9c369286d2 100644
--- a/doc/development/contributing/community_roles.md
+++ b/doc/development/contributing/community_roles.md
@@ -9,4 +9,8 @@ GitLab community members and their privileges/responsibilities.
| Developer |Has access to GitLab internal infrastructure & issues (e.g. HR-related) | GitLab employee or a Core Team member (with an NDA) |
| Contributor | Can make contributions to all GitLab public projects | Have a GitLab.com account |
-[List of current reviewers/maintainers](https://about.gitlab.com/handbook/engineering/projects/#gitlab-ce) \ No newline at end of file
+[List of current reviewers/maintainers](https://about.gitlab.com/handbook/engineering/projects/#gitlab-ce).
+
+---
+
+[Return to Contributing documentation](index.md)
diff --git a/doc/development/contributing/design.md b/doc/development/contributing/design.md
index be7891061f9..79750878aac 100644
--- a/doc/development/contributing/design.md
+++ b/doc/development/contributing/design.md
@@ -13,7 +13,10 @@ There is a special type label called ~"product discovery". It represents a disco
~"product discovery" issues are like any other issue and should contain a milestone label, ~"Deliverable" or ~"Stretch", when scheduled in the current milestone.
-The initial issue should be about the problem we are solving. If a separate [product discovery issue](#product-discovery-issues) is needed for additional research and design work, it will be created by a PM or UX person. Assign the ~UX, ~"product discovery" and ~"Deliverable" labels, add a milestone and use a title that makes it clear that the scheduled issue is product discovery
+The initial issue should be about the problem we are solving. If a separate [product discovery issue](https://about.gitlab.com/handbook/engineering/ux/ux-department-workflow/#how-we-use-labels)
+is needed for additional research and design work, it will be created by a PM or UX person.
+Assign the ~UX, ~"product discovery" and ~"Deliverable" labels, add a milestone and
+use a title that makes it clear that the scheduled issue is product discovery
(e.g. `Product discovery for XYZ`).
In order to complete a product discovery issue in a release, you must complete the following:
@@ -23,34 +26,6 @@ In order to complete a product discovery issue in a release, you must complete t
1. Copy the design to the description of the delivery issue for which the product discovery issue was created. Do not simply refer to the product discovery issue as a separate source of truth.
1. In some cases, a product discovery issue also identifies future enhancements that will not go into the issue that originated the product discovery issue. For these items, create new issues containing the designs to ensure they are not lost. Put the issues in the backlog if they are agreed upon as good ideas. Otherwise leave them for triage.
-## Style guides
-
-1. [Ruby](https://github.com/bbatsov/ruby-style-guide).
- Important sections include [Source Code Layout][rss-source] and
- [Naming][rss-naming]. Use:
- - multi-line method chaining style **Option A**: dot `.` on the second line
- - string literal quoting style **Option A**: single quoted by default
-1. [Rails](https://github.com/bbatsov/rails-style-guide)
-1. [Newlines styleguide][newlines-styleguide]
-1. [Testing][testing]
-1. [JavaScript styleguide][js-styleguide]
-1. [SCSS styleguide][scss-styleguide]
-1. [Shell commands](../shell_commands.md) created by GitLab
- contributors to enhance security
-1. [Database Migrations](../migration_style_guide.md)
-1. [Markdown](http://www.cirosantilli.com/markdown-styleguide)
-1. [Documentation styleguide](https://docs.gitlab.com/ee/development/documentation/styleguide.html)
-1. Interface text should be written subjectively instead of objectively. It
- should be the GitLab core team addressing a person. It should be written in
- present time and never use past tense (has been/was). For example instead
- of _prohibited this user from being saved due to the following errors:_ the
- text should be _sorry, we could not create your account because:_
-1. Code should be written in [US English][us-english]
-
-This is also the style used by linting tools such as
-[RuboCop](https://github.com/bbatsov/rubocop),
-[PullReview](https://www.pullreview.com/) and [Hound CI](https://houndci.com).
-
---
[Return to Contributing documentation](index.md)
diff --git a/doc/development/contributing/index.md b/doc/development/contributing/index.md
index f4486ae3549..29af8dcb9bb 100644
--- a/doc/development/contributing/index.md
+++ b/doc/development/contributing/index.md
@@ -1,22 +1,24 @@
# Contribute to GitLab
-For a first-time step-by-step guide to the contribution process, see
-["Contributing to GitLab"](https://about.gitlab.com/contributing/).
-
Thank you for your interest in contributing to GitLab. This guide details how
-to contribute to GitLab in a way that is efficient for everyone.
+to contribute to GitLab in a way that is easy for everyone.
+
+For a first-time step-by-step guide to the contribution process, please see
+["Contributing to GitLab"](https://about.gitlab.com/contributing/).
-Looking for something to work on? Look for issues with the label [Accepting Merge Requests](#i-want-to-contribute).
+Looking for something to work on? Look for issues in the [Backlog (Accepting merge requests) milestone](#i-want-to-contribute).
-GitLab comes into two flavors, GitLab Community Edition (CE) our free and open
+GitLab comes in two flavors, GitLab Community Edition (CE) our free and open
source edition, and GitLab Enterprise Edition (EE) which is our commercial
edition. Throughout this guide you will see references to CE and EE for
abbreviation.
-If you have read this guide and want to know how the GitLab [core team]
+To get an overview of GitLab community membership including those that would be reviewing or merging your contributions, please visit [the community roles page](community_roles.md).
+
+If you want to know how the GitLab [core team]
operates please see [the GitLab contributing process](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/PROCESS.md).
-- [GitLab Inc engineers should refer to the engineering workflow document](https://about.gitlab.com/handbook/engineering/workflow/)
+[GitLab Inc engineers should refer to the engineering workflow document](https://about.gitlab.com/handbook/engineering/workflow/)
## Security vulnerability disclosure
@@ -28,33 +30,77 @@ vulnerabilities.
## Code of conduct
-As contributors and maintainers of this project, we pledge to respect all
-people who contribute through reporting issues, posting feature requests,
-updating documentation, submitting pull requests or patches, and other
-activities.
+### Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, sex characteristics, gender identity and expression,
+level of experience, education, socio-economic status, nationality, personal
+appearance, race, religion, or sexual identity and orientation.
+
+### Our Standards
-We are committed to making participation in this project a harassment-free
-experience for everyone, regardless of level of experience, gender, gender
-identity and expression, sexual orientation, disability, personal appearance,
-body size, race, ethnicity, age, or religion.
+Examples of behavior that contributes to creating a positive environment
+include:
-Examples of unacceptable behavior by participants include the use of sexual
-language or imagery, derogatory comments or personal attacks, trolling, public
-or private harassment, insults, or other unprofessional conduct.
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+ advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+### Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
-that are not aligned to this Code of Conduct. Project maintainers who do not
-follow the Code of Conduct may be removed from the project team.
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+### Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+### Enforcement
-This code of conduct applies both within project spaces and in public spaces
-when an individual is representing the project or its community.
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at conduct@gitlab.com. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
-Instances of abusive, harassing, or otherwise unacceptable behavior can be
-reported by emailing `contact@gitlab.com`.
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
-This Code of Conduct is adapted from the [Contributor Covenant][contributor-covenant], version 1.1.0,
-available at [http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/).
+### Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
+
+[homepage]: https://www.contributor-covenant.org
## Closing policy for issues and merge requests
@@ -87,8 +133,8 @@ the remaining issues on the GitHub issue tracker.
## I want to contribute!
-If you want to contribute to GitLab [issues with the label `Accepting Merge Requests` and small weight][accepting-mrs-weight]
-is a great place to start. Issues with a lower weight (1 or 2) are deemed
+If you want to contribute to GitLab, [issues in the `Backlog (Accepting merge requests)` milestone][accepting-mrs-weight]
+are a great place to start. Issues with a lower weight (1 or 2) are deemed
suitable for beginners. These issues will be of reasonable size and challenge,
for anyone to start contributing to GitLab. If you have any questions or need help visit [Getting Help](https://about.gitlab.com/getting-help/#discussion) to
learn how to communicate with GitLab. If you're looking for a Gitter or Slack channel
@@ -117,93 +163,39 @@ When your code contains more than 500 changes, any major breaking changes, or an
This [documentation](issue_workflow.md) outlines the current workflow labels.
-### Type labels
-
-This [documentation](issue_workflow.md) outlines the current type labels.
-
-### Subject labels
-
-This [documentation](issue_workflow.md) outlines the current subject labels.
-
-### Team labels
-
-This [documentation](issue_workflow.md) outlines the current team labels.
-
-### Milestone labels
-
-This [documentation](issue_workflow.md) outlines the current milestone labels.
-
-### Bug Priority labels
-
-This [documentation](issue_workflow.md) outlines the current bug priority labels.
-
-### Bug Severity labels
-
-This [documentation](issue_workflow.md) outlines the current severity labels.
-
-#### Severity impact guidance
-
-This [documentation](issue_workflow.md) outlines the current severity impact guidance.
-
-### Label for community contributors
-
-This [documentation](issue_workflow.md) outlines the current policy regarding community contributor issues.
-
-## Implement design & UI elements
-
-This [documentation](design.md) outlines the current design and UI guidelines.
-
-## Issue tracker
-
-This [documentation](issue_workflow.md) outlines the issue tracker process.
-
-### Issue triaging
-
-This [documentation](issue_workflow.md) outlines the current issue triaging process.
-
-### Feature proposals
-
-This [documentation](issue_workflow.md) outlines the feature proposal process.
-
-### Issue tracker guidelines
-
-This [documentation](issue_workflow.md) outlines the issue tracker guidelines.
-
-### Issue weight
-
-This [documentation](issue_workflow.md) outlines the issue weight guidelines.
-
-### Regression issues
-
-This [documentation](issue_workflow.md) outlines the regression issue process.
-
-### Technical and UX debt
-
-This [documentation](issue_workflow.md) about technical and UX debt has been moved.
-
-### Stewardship
-
-This [documentation](issue_workflow.md) outlines the stewardship process.
+* [Type labels](issue_workflow.md#type-labels)
+* [Subject labels](issue_workflow.md#subject-labels)
+* [Team labels](issue_workflow.md#team-labels)
+* [Release Scoping labels](issue_workflow.md#release-scoping-labels)
+* [Priority labels](issue_workflow.md#priority-labels)
+* [Severity labels](issue_workflow.md#severity-labels)
+* [Label for community contributors](issue_workflow.md#label-for-community-contributors)
+* [Issue triaging](issue_workflow.md#issue-triaging)
+* [Feature proposals](issue_workflow.md#feature-proposals)
+* [Issue tracker guidelines](issue_workflow.md#issue-tracker-guidelines)
+* [Issue weight](issue_workflow.md#issue-weight)
+* [Regression issues](issue_workflow.md#regression-issues)
+* [Technical and UX debt](issue_workflow.md#technical-and-ux-debt)
+* [Stewardship](issue_workflow.md#stewardship)
## Merge requests
This [documentation](merge_request_workflow.md) outlines the current merge request process.
-### Merge request guidelines
-
-This [documentation](merge_request_workflow.md) outlines the current merge request guidelines.
-
-### Contribution acceptance criteria
-
-This [documentation](merge_request_workflow.md) outlines the current acceptance criteria for contributions.
-
-## Definition of done
-
-This [documentation](merge_request_workflow.md) outlines the definition of done.
+* [Merge request guidelines](merge_request_workflow.md#merge-request-guidelines)
+* [Contribution acceptance criteria](merge_request_workflow.md#contribution-acceptance-criteria)
+* [Definition of done](merge_request_workflow.md#definition-of-done)
## Style guides
-This [documentation](design.md) outlines the current style guidelines.
+
+This [documentation](style_guides.md) outlines the current style guidelines.
---
[Return to Development documentation](../README.md)
+
+[core team]: https://about.gitlab.com/core-team/
+[team]: https://about.gitlab.com/team/
+[getting-help]: https://about.gitlab.com/getting-help/
+[codetriage]: http://www.codetriage.com/gitlabhq/gitlabhq
+[accepting-mrs-weight]: https://gitlab.com/gitlab-org/gitlab-ce/issues?scope=all&utf8=✓&state=opened&assignee_id=0&milestone_title=Backlog%20&#40;Accepting%20merge%20requests&#41;
diff --git a/doc/development/contributing/issue_workflow.md b/doc/development/contributing/issue_workflow.md
index 1b25a5a2fb7..cd5eee6ea36 100644
--- a/doc/development/contributing/issue_workflow.md
+++ b/doc/development/contributing/issue_workflow.md
@@ -9,6 +9,7 @@ Most issues will have labels for at least one of the following:
- Type: ~"feature proposal", ~bug, ~customer, etc.
- Subject: ~wiki, ~"container registry", ~ldap, ~api, ~frontend, etc.
- Team: ~"CI/CD", ~Plan, ~Manage, ~Quality, etc.
+- Stage: ~"devops:plan", ~"devops:create", etc.
- Release Scoping: ~Deliverable, ~Stretch, ~"Next Patch Release"
- Priority: ~P1, ~P2, ~P3, ~P4
- Severity: ~S1, ~S2, ~S3, ~S4
@@ -20,7 +21,6 @@ If you come across an issue that has none of these, and you're allowed to set
labels, you can _always_ add the team and type, and often also the subject.
[milestones-page]: https://gitlab.com/gitlab-org/gitlab-ce/milestones
-[labels-page]: https://gitlab.com/gitlab-org/gitlab-ce/labels
## Type labels
@@ -84,6 +84,39 @@ indicate if an issue needs backend work, frontend work, or both.
Team labels are always capitalized so that they show up as the first label for
any issue.
+## Stage labels
+
+Stage labels specify which [DevOps stage][devops-stages] the issue belongs to.
+
+The current stage labels are:
+
+- ~"devops:manage"
+- ~"devops:plan"
+- ~"devops:create"
+- ~"devops:verify"
+- ~"devops:package"
+- ~"devops:release"
+- ~"devops:configure"
+- ~"devops:monitor"
+- ~"devops:secure"
+
+These labels should be mutually exclusive. If an issue belongs to multiple
+stages, the most relevant should be used.
+
+They differ from the [Team labels](#team-labels) because teams may work on
+issues outside their stage.
+
+Normally there is a 1:1 relationship between Stage labels and Team labels, but
+any issue can be picked up by any team, depending on current priorities.
+So, an issue labeled ~"devops:create" may be scheduled by the ~Plan team, for
+example. In such cases, it's usual to include both team labels so each team can
+be aware of the progress.
+
+The Stage labels are used to generate the [direction pages][direction-pages] automatically.
+
+[devops-stages]: https://about.gitlab.com/direction/#devops-stages
+[direction-pages]: https://about.gitlab.com/direction/
+
## Release Scoping labels
Release Scoping labels help us clearly communicate expectations of the work for the
@@ -208,6 +241,7 @@ project.
[GitLab Triage]: https://gitlab.com/gitlab-org/gitlab-triage
[scheduled pipeline]: https://gitlab.com/gitlab-org/quality/triage-ops/pipeline_schedules/10512/edit
[quality/triage-ops]: https://gitlab.com/gitlab-org/quality/triage-ops
+[team]: https://about.gitlab.com/team/
## Feature proposals
@@ -235,6 +269,8 @@ need to ask one of the [core team] members to add the label, if you do not have
If you want to create something yourself, consider opening an issue first to
discuss whether it is interesting to include this in GitLab.
+[fpl]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=feature+proposal
+
## Issue tracker guidelines
**[Search the issue tracker][ce-tracker]** for similar entries before
@@ -331,3 +367,7 @@ A recent example of this was the issue for
---
[Return to Contributing documentation](index.md)
+
+[labels-page]: https://gitlab.com/gitlab-org/gitlab-ce/labels
+[ce-tracker]: https://gitlab.com/gitlab-org/gitlab-ce/issues
+[ee-tracker]: https://gitlab.com/gitlab-org/gitlab-ee/issues
diff --git a/doc/development/contributing/merge_request_workflow.md b/doc/development/contributing/merge_request_workflow.md
index 0d20e1a02dd..cc7d8a1e1db 100644
--- a/doc/development/contributing/merge_request_workflow.md
+++ b/doc/development/contributing/merge_request_workflow.md
@@ -2,9 +2,9 @@
We welcome merge requests with fixes and improvements to GitLab code, tests,
and/or documentation. The issues that are specifically suitable for
-community contributions are listed with the label
-[`Accepting Merge Requests` on our issue tracker for CE][accepting-mrs-ce]
-and [EE][accepting-mrs-ee], but you are free to contribute to any other issue
+community contributions are listed with the
+[`Backlog (Accepting merge requests)` milestone in the CE issue tracker][accepting-mrs-ce]
+and [EE issue tracker][accepting-mrs-ee], but you are free to contribute to any other issue
you want.
Please note that if an issue is marked for the current milestone either before
@@ -19,11 +19,16 @@ wireframes if the feature will also change the UI.
Merge requests should be opened at [GitLab.com][gitlab-mr-tracker].
If you are new to GitLab development (or web development in general), see the
-[I want to contribute!](#i-want-to-contribute) section to get you started with
+[I want to contribute!](index.md#i-want-to-contribute) section to get you started with
some potentially easy issues.
To start with GitLab development download the [GitLab Development Kit][gdk] and
-see the [Development section](../README.md) for some guidelines.
+see the [Development section](../../README.md) for some guidelines.
+
+[accepting-mrs-ce]: https://gitlab.com/gitlab-org/gitlab-ce/issues?milestone_title=Backlog%20&#40;Accepting%20merge%20requests&#41;
+[accepting-mrs-ee]: https://gitlab.com/gitlab-org/gitlab-ee/issues?milestone_title=Backlog%20&#40;Accepting%20merge%20requests&#41;
+[gitlab-mr-tracker]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests
+[gdk]: https://gitlab.com/gitlab-org/gitlab-development-kit
## Merge request guidelines
@@ -103,6 +108,10 @@ Please ensure that your merge request meets the contribution acceptance criteria
When having your code reviewed and when reviewing merge requests please take the
[code review guidelines](../code_review.md) into account.
+[git-squash]: https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits
+[closed-merge-requests]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests?assignee_id=&label_name=&milestone_id=&scope=&sort=&state=closed
+[team]: https://about.gitlab.com/team/
+
## Contribution acceptance criteria
1. The change is as small as possible
@@ -133,7 +142,7 @@ When having your code reviewed and when reviewing merge requests please take the
[polling with ETag caching][polling-etag].
1. Changes after submitting the merge request should be in separate commits
(no squashing).
-1. It conforms to the [style guides](#style-guides) and the following:
+1. It conforms to the [style guides](style_guides.md) and the following:
- If your change touches a line that does not follow the style, modify the
entire line to follow it. This prevents linting tools from generating warnings.
- Don't touch neighbouring lines. As an exception, automatic mass
@@ -144,6 +153,9 @@ When having your code reviewed and when reviewing merge requests please take the
"license-finder" test with a "Dependencies that need approval" error.
1. The merge request meets the [definition of done](#definition-of-done).
+[license-finder-doc]: ../licensing.md
+[polling-etag]: ../polling.md
+
## Definition of done
If you contribute to GitLab please know that changes involve more than just
@@ -175,6 +187,12 @@ merge request:
1. Test suite https://gitlab.com/gitlab-org/gitlab-ce/blob/master/scripts/prepare_build.sh
1. Omnibus package creator https://gitlab.com/gitlab-org/omnibus-gitlab
+[definition-of-done]: http://guide.agilealliance.org/guide/definition-of-done.html
+[testing]: ../testing_guide/index.md
+
---
[Return to Contributing documentation](index.md)
+
+[changelog]: ../changelog.md "Generate a changelog entry"
+[doc-guidelines]: ../documentation/index.md "Documentation guidelines"
diff --git a/doc/development/contributing/style_guides.md b/doc/development/contributing/style_guides.md
new file mode 100644
index 00000000000..fb0454db7d2
--- /dev/null
+++ b/doc/development/contributing/style_guides.md
@@ -0,0 +1,40 @@
+# Style guides
+
+1. [Ruby](https://github.com/bbatsov/ruby-style-guide).
+ Important sections include [Source Code Layout][rss-source] and
+ [Naming][rss-naming]. Use:
+ - multi-line method chaining style **Option A**: dot `.` on the second line
+ - string literal quoting style **Option A**: single quoted by default
+1. [Rails](https://github.com/bbatsov/rails-style-guide)
+1. [Newlines styleguide][newlines-styleguide]
+1. [Testing][testing]
+1. [JavaScript styleguide][js-styleguide]
+1. [SCSS styleguide][scss-styleguide]
+1. [Shell commands](../shell_commands.md) created by GitLab
+ contributors to enhance security
+1. [Database Migrations](../migration_style_guide.md)
+1. [Markdown](http://www.cirosantilli.com/markdown-styleguide)
+1. [Documentation styleguide](../documentation/styleguide.md)
+1. Interface text should be written subjectively instead of objectively. It
+ should be the GitLab core team addressing a person. It should be written in
+ present time and never use past tense (has been/was). For example instead
+ of _prohibited this user from being saved due to the following errors:_ the
+ text should be _sorry, we could not create your account because:_
+1. Code should be written in [US English][us-english]
+
+This is also the style used by linting tools such as
+[RuboCop](https://github.com/bbatsov/rubocop),
+[PullReview](https://www.pullreview.com/) and [Hound CI](https://houndci.com).
+
+---
+
+[Return to Contributing documentation](index.md)
+
+[rss-source]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#source-code-layout
+[rss-naming]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#naming
+[doc-guidelines]: ../documentation/index.md "Documentation guidelines"
+[js-styleguide]: ../fe_guide/style_guide_js.md "JavaScript styleguide"
+[scss-styleguide]: ../fe_guide/style_guide_scss.md "SCSS styleguide"
+[newlines-styleguide]: ../newlines_styleguide.md "Newlines styleguide"
+[testing]: ../testing_guide/index.md
+[us-english]: https://en.wikipedia.org/wiki/American_English
diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md
index 2db78e4a365..1dcdf788a3e 100644
--- a/doc/development/documentation/index.md
+++ b/doc/development/documentation/index.md
@@ -321,7 +321,7 @@ The following sample `markdownlint` configuration modifies the available default
}
```
-For [`markdownlint`](https://gitahub.com/DavidAnson/markdownlint/), this configuration must be
+For [`markdownlint`](https://github.com/DavidAnson/markdownlint/), this configuration must be
placed in a [valid location](https://github.com/igorshubovych/markdownlint-cli#configuration). For
example, `~/.markdownlintrc`.
@@ -414,7 +414,7 @@ to EE only.
NOTE: **Note:**
To preview your changes to documentation locally, follow this
-[development guide](https://gitlab.com/gitlab-com/gitlab-docs/blob/master/README.md#development).
+[development guide](https://gitlab.com/gitlab-com/gitlab-docs/blob/master/README.md#development-when-contributing-to-gitlab-documentation) or [these instructions for GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/gitlab_docs.md).
The live preview is currently enabled for the following projects:
diff --git a/doc/development/feature_flags.md b/doc/development/feature_flags.md
index 417298205f5..0f1f079bdb4 100644
--- a/doc/development/feature_flags.md
+++ b/doc/development/feature_flags.md
@@ -69,6 +69,37 @@ For more information about rolling out changes using feature flags, refer to the
[Rolling out changes using feature flags](rolling_out_changes_using_feature_flags.md)
guide.
+### Frontend
+
+For frontend code you can use the method `push_frontend_feature_flag`, which is
+available to all controllers that inherit from `ApplicationController`. Using
+this method you can expose the state of a feature flag as follows:
+
+```ruby
+before_action do
+ push_frontend_feature_flag(:vim_bindings)
+end
+
+def index
+ # ...
+end
+
+def edit
+ # ...
+end
+```
+
+You can then check for the state of the feature flag in JavaScript as follows:
+
+```javascript
+if ( gon.features.vimBindings ) {
+ // ...
+}
+```
+
+The name of the feature flag in JavaScript will always be camelCased, meaning
+that checking for `gon.features.vim_bindings` would not work.
+
### Specs
In the test environment `Feature.enabled?` is stubbed to always respond to `true`,
diff --git a/doc/development/new_fe_guide/index.md b/doc/development/new_fe_guide/index.md
index 78931defa24..bfcca9cec7b 100644
--- a/doc/development/new_fe_guide/index.md
+++ b/doc/development/new_fe_guide/index.md
@@ -19,6 +19,10 @@ Guidance on topics related to development.
Learn about all the dependencies that make up our frontend, including some of our own custom built libraries.
+## [Modules](modules/index.md)
+
+Learn about all the internal JavaScript modules that make up our frontend.
+
## [Style guides](style/index.md)
Style guides to keep our code consistent.
diff --git a/doc/development/new_fe_guide/modules/dirty_submit.md b/doc/development/new_fe_guide/modules/dirty_submit.md
new file mode 100644
index 00000000000..6c03958b463
--- /dev/null
+++ b/doc/development/new_fe_guide/modules/dirty_submit.md
@@ -0,0 +1,23 @@
+# Dirty Submit
+
+> [Introduced][ce-21115] in GitLab 11.3.
+> [dirty_submit][dirty-submit]
+
+## Summary
+
+Prevent submitting forms with no changes.
+
+Currently handles `input`, `textarea` and `select` elements.
+
+## Usage
+
+```js
+import dirtySubmitFactory from './dirty_submit/dirty_submit_form';
+
+new DirtySubmitForm(document.querySelector('form'));
+// or
+new DirtySubmitForm(document.querySelectorAll('form'));
+```
+
+[ce-21115]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21115
+[dirty-submit]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/assets/javascripts/dirty_submit/ \ No newline at end of file
diff --git a/doc/development/new_fe_guide/modules/index.md b/doc/development/new_fe_guide/modules/index.md
new file mode 100644
index 00000000000..0a7f2dbd819
--- /dev/null
+++ b/doc/development/new_fe_guide/modules/index.md
@@ -0,0 +1,5 @@
+# Modules
+
+* [DirtySubmit](dirty_submit.md)
+
+ Disable form submits until there are unsaved changes. \ No newline at end of file
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 25aa5d3369d..9e2e58657f1 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -103,7 +103,7 @@ Is the system packaged Git too old? Remove it and compile from source.
# When editing config/gitlab.yml (Step 5), change the git -> bin_path to /usr/local/bin/git
-**Note:** In order to receive mail notifications, make sure to install a mail server. By default, Debian is shipped with exim4 but this [has problems](https://github.com/gitlabhq/gitlabhq/issues/4866#issuecomment-32726573) while Ubuntu does not ship with one. The recommended mail server is postfix and you can install it with:
+**Note:** In order to receive mail notifications, make sure to install a mail server. By default, Debian is shipped with exim4 but this [has problems](https://gitlab.com/gitlab-org/gitlab-ce/issues/12754) while Ubuntu does not ship with one. The recommended mail server is postfix and you can install it with:
sudo apt-get install -y postfix
diff --git a/doc/policy/maintenance.md b/doc/policy/maintenance.md
index fc7b97b3cc2..03ba2ae8817 100644
--- a/doc/policy/maintenance.md
+++ b/doc/policy/maintenance.md
@@ -75,7 +75,8 @@ Please see the table below for some examples:
| Latest stable version | Your version | Recommended upgrade path | Note |
| -------------- | ------------ | ------------------------ | ---------------- |
| 9.4.5 | 8.13.4 | `8.13.4` -> `8.17.7` -> `9.4.5` | `8.17.7` is the last version in version `8` |
-| 10.1.4 | 8.13.4 | `8.13.4` -> `8.17.7` -> `9.5.8` -> `10.1.4` | `8.17.7` is the last version in version `8`, `9.5.8` is the last version in version `9` |
+| 10.1.4 | 8.13.4 | `8.13.4 -> 8.17.7 -> 9.5.10 -> 10.1.4` | `8.17.7` is the last version in version `8`, `9.5.10` is the last version in version `9` |
+| 11.3.4 | 8.13.4 | `8.13.4` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.3.4` | `8.17.7` is the last version in version `8`, `9.5.10` is the last version in version `9`, `10.8.7` is the last version in version `10` |
More information about the release procedures can be found in our
[release-tools documentation][rel]. You may also want to read our
diff --git a/doc/update/11.3-to-11.4.md b/doc/update/11.3-to-11.4.md
index 985239369d7..b50e21f27dd 100644
--- a/doc/update/11.3-to-11.4.md
+++ b/doc/update/11.3-to-11.4.md
@@ -80,8 +80,8 @@ More information can be found on the [yarn website](https://yarnpkg.com/en/docs/
### 5. Update Go
-NOTE: GitLab 11.0 and higher only supports Go 1.9.x and newer, and dropped support for Go
-1.5.x through 1.8.x. Be sure to upgrade your installation if necessary.
+NOTE: GitLab 11.4 and higher only supports Go 1.10.x and newer, and dropped support for Go
+1.9.x. Be sure to upgrade your installation if necessary.
You can check which version you are running with `go version`.
diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md
index 1b3fb9db4ec..097b18ad496 100644
--- a/doc/user/discussions/index.md
+++ b/doc/user/discussions/index.md
@@ -281,7 +281,7 @@ Additionally locked issues can not be reopened.
[ce-14053]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/14053
[ce-14061]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/14061
[ce-14531]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/14531
-[ce-31847]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/31847
+[ce-31847]: https://gitlab.com/gitlab-org/gitlab-ce/issues/31847
[resolve-discussion-button]: img/resolve_discussion_button.png
[resolve-comment-button]: img/resolve_comment_button.png
[discussion-view]: img/discussion_view.png
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index b14377a72b6..7d01c6f2bf6 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -257,7 +257,6 @@ Learn more about [Member Lock](https://docs.gitlab.com/ee/user/group/index.html#
- **Projects**: view all projects within that group, add members to each project,
access each project's settings, and remove any project from the same screen.
- **Webhooks**: configure [webhooks](../project/integrations/webhooks.md) to your group.
-- **Push rules**: configure [push rules](https://docs.gitlab.com/ee/push_rules/push_rules.html#push-rules) to your group. **[STARTER]**
- **Audit Events**: view [Audit Events](https://docs.gitlab.com/ee/administration/audit_events.html#audit-events)
for the group. **[STARTER ONLY]**
- **Pipelines quota**: keep track of the [pipeline quota](../admin_area/settings/continuous_integration.md) for the group
diff --git a/doc/user/project/img/issue_boards_core.png b/doc/user/project/img/issue_boards_core.png
index 9e819160861..9e819160861 100755..100644
--- a/doc/user/project/img/issue_boards_core.png
+++ b/doc/user/project/img/issue_boards_core.png
Binary files differ
diff --git a/doc/user/project/img/issue_boards_premium.png b/doc/user/project/img/issue_boards_premium.png
index bd9164b2961..bd9164b2961 100755..100644
--- a/doc/user/project/img/issue_boards_premium.png
+++ b/doc/user/project/img/issue_boards_premium.png
Binary files differ
diff --git a/doc/user/project/img/koding_build-in-progress.png b/doc/user/project/img/koding_build-in-progress.png
deleted file mode 100644
index 118b97c07e1..00000000000
--- a/doc/user/project/img/koding_build-in-progress.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_build-logs.png b/doc/user/project/img/koding_build-logs.png
deleted file mode 100644
index b30c8375b20..00000000000
--- a/doc/user/project/img/koding_build-logs.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_build-success.png b/doc/user/project/img/koding_build-success.png
deleted file mode 100644
index 0f3b954abf5..00000000000
--- a/doc/user/project/img/koding_build-success.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_commit-koding.yml.png b/doc/user/project/img/koding_commit-koding.yml.png
deleted file mode 100644
index d921c73dc73..00000000000
--- a/doc/user/project/img/koding_commit-koding.yml.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_different-stack-on-mr-try.png b/doc/user/project/img/koding_different-stack-on-mr-try.png
deleted file mode 100644
index 10c7c51d2e6..00000000000
--- a/doc/user/project/img/koding_different-stack-on-mr-try.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_edit-on-ide.png b/doc/user/project/img/koding_edit-on-ide.png
deleted file mode 100644
index 25ca7694fe0..00000000000
--- a/doc/user/project/img/koding_edit-on-ide.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_enable-koding.png b/doc/user/project/img/koding_enable-koding.png
deleted file mode 100644
index 7e6c1735df2..00000000000
--- a/doc/user/project/img/koding_enable-koding.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_landing.png b/doc/user/project/img/koding_landing.png
deleted file mode 100644
index ac880376e09..00000000000
--- a/doc/user/project/img/koding_landing.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_open-gitlab-from-koding.png b/doc/user/project/img/koding_open-gitlab-from-koding.png
deleted file mode 100644
index 4235a72b36f..00000000000
--- a/doc/user/project/img/koding_open-gitlab-from-koding.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_run-in-ide.png b/doc/user/project/img/koding_run-in-ide.png
deleted file mode 100644
index fb5825a4010..00000000000
--- a/doc/user/project/img/koding_run-in-ide.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_run-mr-in-ide.png b/doc/user/project/img/koding_run-mr-in-ide.png
deleted file mode 100644
index cb1112c4034..00000000000
--- a/doc/user/project/img/koding_run-mr-in-ide.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_set-up-ide.png b/doc/user/project/img/koding_set-up-ide.png
deleted file mode 100644
index 033d41729a2..00000000000
--- a/doc/user/project/img/koding_set-up-ide.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_stack-import.png b/doc/user/project/img/koding_stack-import.png
deleted file mode 100644
index 483bfad7d6a..00000000000
--- a/doc/user/project/img/koding_stack-import.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_start-build.png b/doc/user/project/img/koding_start-build.png
deleted file mode 100644
index c09a6d669f0..00000000000
--- a/doc/user/project/img/koding_start-build.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/koding.md b/doc/user/project/koding.md
deleted file mode 100644
index 2c886d7916a..00000000000
--- a/doc/user/project/koding.md
+++ /dev/null
@@ -1,131 +0,0 @@
-# Koding integration
-
-> **Notes:**
-> - **As of GitLab 10.0, the Koding integration is deprecated and will be removed
-> in a future version.**
-> - [Introduced][ce-5909] in GitLab 8.11.
-
-This document will guide you through using Koding integration on GitLab in
-detail. For configuring and installing please follow the
-[administrator guide](../../administration/integration/koding.md).
-
-You can use Koding integration to run and develop your projects on GitLab. This
-will allow you and the users to test your project without leaving the browser.
-Koding handles projects as stacks which are basic recipes to define your
-environment for your project. With this integration you can automatically
-create a proper stack template for your projects. Currently auto-generated
-stack templates are designed to work with AWS which requires a valid AWS
-credential to be able to use these stacks. You can find more information about
-stacks and the other providers that you can use on Koding following the
-[Koding documentation][koding-docs].
-
-## Enable Integration
-
-You can enable Koding integration by providing the running Koding instance URL
-in Application Settings under **Admin area > Settings** (`/admin/application_settings`).
-
-![Enable Koding](img/koding_enable-koding.png)
-
-Once enabled you will see `Koding` link on your sidebar which leads you to
-Koding Landing page.
-
-![Koding Landing](img/koding_landing.png)
-
-You can navigate to running Koding instance from here. For more information and
-details about configuring the integration, please follow the
-[administrator guide](../../administration/integration/koding.md).
-
-## Set up Koding on Projects
-
-Once it's enabled, you will see some integration buttons on Project pages,
-Merge Requests etc. To get started working on a specific project you first need
-to create a `.koding.yml` file under your project root. You can easily do that
-by using `Set Up Koding` button which will be visible on every project's
-landing page;
-
-![Set Up Koding](img/koding_set-up-ide.png)
-
-Once you click this will open a New File page on GitLab with auto-generated
-`.koding.yml` content based on your server and repository configuration.
-
-![Commit .koding.yml](img/koding_commit-koding.yml.png)
-
-
-## Run a project on Koding
-
-If there is `.koding.yml` exists in your project root, you will see
-`Run in IDE (Koding)` button in your project landing page. You can initiate the
-process from here.
-
-![Run on Koding](img/koding_run-in-ide.png)
-
-This will open Koding defined in the settings in a new window and will start
-importing the project's stack file.
-
-![Import Stack](img/koding_stack-import.png)
-
-You should see the details of your repository imported into your Koding
-instance. Once it's completed it will lead you to the Stack Editor and from
-there you can start using your new stack integrated with your project on your
-GitLab instance. For details about what's next you can follow
-[this guide](https://www.koding.com/docs/creating-an-aws-stack) from step 8.
-
-Once stack initialized you will see the `README.md` content from your project
-in `Stack Build` wizard, this wizard will let you build the stack and import
-your project into it. **Once it's completed it will automatically open the
-related vm instead of importing from scratch**.
-
-![Stack Building](img/koding_start-build.png)
-
-This will take time depending on the required environment.
-
-![Stack Building in Progress](img/koding_build-in-progress.png)
-
-It usually takes ~4 min. to make it ready with a `t2.nano` instance on given
-AWS region. (`t2.nano` is default vm type on auto-generated stack template
-which can be manually changed).
-
-![Stack Building Success](img/koding_build-success.png)
-
-You can check out the `Build Logs` from this success modal as well.
-
-![Stack Build Logs](img/koding_build-logs.png)
-
-You can now `Start Coding`!
-
-![Edit On IDE](img/koding_edit-on-ide.png)
-
-## Try a Merge Request on IDE
-
-It's also possible to try a change on IDE before merging it. This flow only
-enabled if the target project has `.koding.yml` in it's target branch. You
-should see the alternative version of `Run in IDE (Koding)` button in merge
-request pages as well;
-
-![Run in IDE on MR](img/koding_run-mr-in-ide.png)
-
-This will again take you to Koding with proper arguments passed, which will
-allow Koding to modify the stack template provided by target branch. You can
-see the difference;
-
-![Different Branch for MR](img/koding_different-stack-on-mr-try.png)
-
-The flow for the branch stack is also same with the regular project flow.
-
-## Open GitLab from Koding
-
-Since stacks generated with import flow defined in previous steps, they have
-information about the repository they are belonging to. By using this
-information you can access to related GitLab page from stacks on your sidebar
-on Koding.
-
-![Open GitLab from Koding](img/koding_open-gitlab-from-koding.png)
-
-## Other links
-
-- [YouTube video on GitLab + Koding workflow][youtube]
-- [Koding documentation][koding-docs]
-
-[ce-5909]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5909
-[youtube]: https://youtu.be/3wei5yv_Ye8
-[koding-docs]: https://www.koding.com/docs
diff --git a/doc/user/project/merge_requests/cherry_pick_changes.md b/doc/user/project/merge_requests/cherry_pick_changes.md
index 22ef11e4049..06b3779668b 100644
--- a/doc/user/project/merge_requests/cherry_pick_changes.md
+++ b/doc/user/project/merge_requests/cherry_pick_changes.md
@@ -12,9 +12,11 @@ to cherry-pick the changes introduced by that merge request.
![Cherry-pick Merge Request](img/cherry_pick_changes_mr.png)
-After you click that button, a modal will appear where you can choose to
-cherry-pick the changes directly into the selected branch or you can opt to
-create a new merge request with the cherry-pick changes
+After you click that button, a modal will appear showing a [branch filter search box](../repository/branches/index.md#branch-filter-search-box)
+where you can choose to either:
+
+- Cherry-pick the changes directly into the selected branch.
+- Create a new merge request with the cherry-picked changes.
## Cherry-picking a Commit
diff --git a/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png b/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png
index ac766c99935..3b3bf88df31 100644
--- a/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png
+++ b/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png
Binary files differ
diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md
index 43ca498d006..f9ebf277125 100644
--- a/doc/user/project/merge_requests/index.md
+++ b/doc/user/project/merge_requests/index.md
@@ -205,9 +205,9 @@ have been marked as a **Work In Progress**.
## Merge request diff file navigation
-The diff view has a persistent dropdown for file navigation. As you scroll through
-diffs with a large number of files and/or many changes in those files, you can
-easily jump to any changed file through the dropdown navigation.
+The diff view has a file tree for file navigation. As you scroll through
+diffs with a large number of files, you can easily jump to any changed file
+using the file tree.
![Merge request diff file navigation](img/merge_request_diff_file_navigation.png)
diff --git a/doc/user/project/repository/branches/img/branch_filter_search_box.png b/doc/user/project/repository/branches/img/branch_filter_search_box.png
new file mode 100644
index 00000000000..c4364ef39f4
--- /dev/null
+++ b/doc/user/project/repository/branches/img/branch_filter_search_box.png
Binary files differ
diff --git a/doc/user/project/repository/branches/index.md b/doc/user/project/repository/branches/index.md
index 19417d91fec..e1d8345f415 100644
--- a/doc/user/project/repository/branches/index.md
+++ b/doc/user/project/repository/branches/index.md
@@ -6,6 +6,7 @@ Read through GiLab's branching documentation:
- [Default branch](#default-branch)
- [Protected branches](../../protected_branches.md#protected-branches)
- [Delete merged branches](#delete-merged-branches)
+- [Branch filter search box](#branch-filter-search-box)
See also:
@@ -40,5 +41,22 @@ this operation.
It's particularly useful to clean up old branches that were not deleted
automatically when a merge request was merged.
+
+## Branch filter search box
+
+> [Introduced][https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22166] in GitLab 11.5.
+
+![Branch filter search box](img/branch_filter_search_box.png)
+
+This feature allows you to search and select branches quickly. Search results appear in the following order:
+
+- Branches with names that matched search terms exactly.
+- Other branches with names that include search terms, sorted alphabetically.
+
+Sometimes when you have hundreds of branches you may want a more flexible matching pattern. In such cases you can use the following:
+
+- `^feature` will only match branch names that begin with 'feature'.
+- `feature$` will only match branch names that end with 'feature'.
+
[ce-6449]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6449 "Add button to delete all merged branches"
[protected]: ../../protected_branches.md
diff --git a/doc/user/project/repository/index.md b/doc/user/project/repository/index.md
index 4d016277824..ce79bfc0a03 100644
--- a/doc/user/project/repository/index.md
+++ b/doc/user/project/repository/index.md
@@ -85,12 +85,13 @@ You can live preview changes submitted to a new branch with
With [GitLab Starter](https://about.gitlab.com/pricing/), you can also request
[approval](https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html) from your managers.
-To create, delete, and [branches](branches/index.md) via GitLab's UI:
+To create, delete, and view [branches](branches/index.md) via GitLab's UI:
- [Default branches](branches/index.md#default-branch)
- [Create a branch](web_editor.md#create-a-new-branch)
- [Protected branches](../protected_branches.md#protected-branches)
- [Delete merged branches](branches/index.md#delete-merged-branches)
+- [Branch filter search box](branches/index.md#branch-filter-search-box)
Alternatively, you can use the
[command line](../../../gitlab-basics/start-using-git.md#create-a-branch).
@@ -169,7 +170,7 @@ vendored code, and most markup languages are excluded.
## Compare
-Select branches to compare and view the changes inline:
+Select branches to compare using the [branch filter search box](branches/index.md#branch-filter-search-box), then click the **Compare** button to view the changes inline:
![compare branches](img/compare_branches.png)
diff --git a/doc/user/reserved_names.md b/doc/user/reserved_names.md
index 52610378ad5..45c306f5988 100644
--- a/doc/user/reserved_names.md
+++ b/doc/user/reserved_names.md
@@ -68,7 +68,6 @@ Currently the following names are reserved as top level groups:
- import
- invites
- jwt
-- koding
- notification_settings
- oauth
- profile
diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb
index 5125f302fbb..dc844c0bd27 100644
--- a/lib/api/repositories.rb
+++ b/lib/api/repositories.rb
@@ -130,18 +130,13 @@ module API
success Entities::Commit
end
params do
- # For now we just support 2 refs passed, but `merge-base` supports
- # multiple defining this as an Array instead of 2 separate params will
- # make sure we don't need to deprecate this API in favor of one
- # supporting multiple commits when this functionality gets added to
- # Gitaly
requires :refs, type: Array[String]
end
get ':id/repository/merge_base' do
refs = params[:refs]
- unless refs.size == 2
- render_api_error!('Provide exactly 2 refs', 400)
+ if refs.size < 2
+ render_api_error!('Provide at least 2 refs', 400)
end
merge_base = Gitlab::Git::MergeBase.new(user_project.repository, refs)
diff --git a/lib/api/settings.rb b/lib/api/settings.rb
index edbd134822c..f53ba0ab761 100644
--- a/lib/api/settings.rb
+++ b/lib/api/settings.rb
@@ -66,10 +66,6 @@ module API
optional :html_emails_enabled, type: Boolean, desc: 'By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format.'
optional :import_sources, type: Array[String], values: %w[github bitbucket gitlab google_code fogbugz git gitlab_project manifest],
desc: 'Enabled sources for code import during project creation. OmniAuth must be configured for GitHub, Bitbucket, and GitLab.com'
- optional :koding_enabled, type: Boolean, desc: 'Enable Koding'
- given koding_enabled: ->(val) { val } do
- requires :koding_url, type: String, desc: 'The Koding team URL'
- end
optional :max_artifacts_size, type: Integer, desc: "Set the maximum file size for each job's artifacts"
optional :max_attachment_size, type: Integer, desc: 'Maximum attachment size in MB'
optional :max_pages_size, type: Integer, desc: 'Maximum size of pages in MB'
diff --git a/lib/generators/rails/post_deployment_migration/post_deployment_migration_generator.rb b/lib/generators/rails/post_deployment_migration/post_deployment_migration_generator.rb
index 91175b49c79..15cdd25e711 100644
--- a/lib/generators/rails/post_deployment_migration/post_deployment_migration_generator.rb
+++ b/lib/generators/rails/post_deployment_migration/post_deployment_migration_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails/generators'
module Rails
diff --git a/lib/gitaly/server.rb b/lib/gitaly/server.rb
index f95e423ef22..7b238623418 100644
--- a/lib/gitaly/server.rb
+++ b/lib/gitaly/server.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitaly
class Server
def self.all
diff --git a/lib/gitlab/auth/activity.rb b/lib/gitlab/auth/activity.rb
index 761f0819c60..558628b5422 100644
--- a/lib/gitlab/auth/activity.rb
+++ b/lib/gitlab/auth/activity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
##
diff --git a/lib/gitlab/auth/database/authentication.rb b/lib/gitlab/auth/database/authentication.rb
index 1234ace0334..c0dc2b0875f 100644
--- a/lib/gitlab/auth/database/authentication.rb
+++ b/lib/gitlab/auth/database/authentication.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# These calls help to authenticate to OAuth provider by providing username and password
#
diff --git a/lib/gitlab/auth/ip_rate_limiter.rb b/lib/gitlab/auth/ip_rate_limiter.rb
index e6173d45af3..81e616fa20a 100644
--- a/lib/gitlab/auth/ip_rate_limiter.rb
+++ b/lib/gitlab/auth/ip_rate_limiter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
class IpRateLimiter
diff --git a/lib/gitlab/auth/ldap/access.rb b/lib/gitlab/auth/ldap/access.rb
index f323d2e0f7a..c875bba4bcb 100644
--- a/lib/gitlab/auth/ldap/access.rb
+++ b/lib/gitlab/auth/ldap/access.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# LDAP authorization model
#
# * Check if we are allowed access (not blocked)
diff --git a/lib/gitlab/auth/ldap/adapter.rb b/lib/gitlab/auth/ldap/adapter.rb
index 82ff1e77e5c..42c657afe6a 100644
--- a/lib/gitlab/auth/ldap/adapter.rb
+++ b/lib/gitlab/auth/ldap/adapter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
module LDAP
diff --git a/lib/gitlab/auth/ldap/auth_hash.rb b/lib/gitlab/auth/ldap/auth_hash.rb
index ac5c14d374d..83fdc8a8c76 100644
--- a/lib/gitlab/auth/ldap/auth_hash.rb
+++ b/lib/gitlab/auth/ldap/auth_hash.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Class to parse and transform the info provided by omniauth
#
module Gitlab
diff --git a/lib/gitlab/auth/ldap/authentication.rb b/lib/gitlab/auth/ldap/authentication.rb
index 7c134fb6438..174e81dd603 100644
--- a/lib/gitlab/auth/ldap/authentication.rb
+++ b/lib/gitlab/auth/ldap/authentication.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# These calls help to authenticate to LDAP by providing username and password
#
# Since multiple LDAP servers are supported, it will loop through all of them
diff --git a/lib/gitlab/auth/ldap/config.rb b/lib/gitlab/auth/ldap/config.rb
index d4415eaa6dc..7ceb96f502b 100644
--- a/lib/gitlab/auth/ldap/config.rb
+++ b/lib/gitlab/auth/ldap/config.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Load a specific server configuration
module Gitlab
module Auth
diff --git a/lib/gitlab/auth/ldap/dn.rb b/lib/gitlab/auth/ldap/dn.rb
index 1fa5338f5a6..5df914aa367 100644
--- a/lib/gitlab/auth/ldap/dn.rb
+++ b/lib/gitlab/auth/ldap/dn.rb
@@ -1,4 +1,5 @@
# -*- ruby encoding: utf-8 -*-
+# frozen_string_literal: true
# Based on the `ruby-net-ldap` gem's `Net::LDAP::DN`
#
diff --git a/lib/gitlab/auth/ldap/ldap_connection_error.rb b/lib/gitlab/auth/ldap/ldap_connection_error.rb
index ef0a695742b..d0e5f24d203 100644
--- a/lib/gitlab/auth/ldap/ldap_connection_error.rb
+++ b/lib/gitlab/auth/ldap/ldap_connection_error.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
module LDAP
diff --git a/lib/gitlab/auth/ldap/person.rb b/lib/gitlab/auth/ldap/person.rb
index 8dfae3ee541..a0244a3cea1 100644
--- a/lib/gitlab/auth/ldap/person.rb
+++ b/lib/gitlab/auth/ldap/person.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
module LDAP
diff --git a/lib/gitlab/auth/ldap/user.rb b/lib/gitlab/auth/ldap/user.rb
index 3c21ddf3241..9c71671f409 100644
--- a/lib/gitlab/auth/ldap/user.rb
+++ b/lib/gitlab/auth/ldap/user.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# LDAP extension for User model
#
# * Find or create user from omniauth.auth data
diff --git a/lib/gitlab/auth/o_auth/auth_hash.rb b/lib/gitlab/auth/o_auth/auth_hash.rb
index ed8fba94305..4a5f9d2839d 100644
--- a/lib/gitlab/auth/o_auth/auth_hash.rb
+++ b/lib/gitlab/auth/o_auth/auth_hash.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Class to parse and transform the info provided by omniauth
#
module Gitlab
diff --git a/lib/gitlab/auth/o_auth/authentication.rb b/lib/gitlab/auth/o_auth/authentication.rb
index d4e7f35c857..5f008678bd1 100644
--- a/lib/gitlab/auth/o_auth/authentication.rb
+++ b/lib/gitlab/auth/o_auth/authentication.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# These calls help to authenticate to OAuth provider by providing username and password
#
diff --git a/lib/gitlab/auth/o_auth/identity_linker.rb b/lib/gitlab/auth/o_auth/identity_linker.rb
index de92d7a214d..e69c2bb54dc 100644
--- a/lib/gitlab/auth/o_auth/identity_linker.rb
+++ b/lib/gitlab/auth/o_auth/identity_linker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
module OAuth
diff --git a/lib/gitlab/auth/o_auth/provider.rb b/lib/gitlab/auth/o_auth/provider.rb
index 26da9d09ccc..9fdf3324db3 100644
--- a/lib/gitlab/auth/o_auth/provider.rb
+++ b/lib/gitlab/auth/o_auth/provider.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
module OAuth
diff --git a/lib/gitlab/auth/o_auth/session.rb b/lib/gitlab/auth/o_auth/session.rb
index 8f2b4d58552..4925b107042 100644
--- a/lib/gitlab/auth/o_auth/session.rb
+++ b/lib/gitlab/auth/o_auth/session.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# :nocov:
module Gitlab
module Auth
diff --git a/lib/gitlab/auth/o_auth/user.rb b/lib/gitlab/auth/o_auth/user.rb
index 2b4f6ed75e5..a4e8a41b246 100644
--- a/lib/gitlab/auth/o_auth/user.rb
+++ b/lib/gitlab/auth/o_auth/user.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# OAuth extension for User model
#
# * Find GitLab user based on omniauth uid and provider
diff --git a/lib/gitlab/auth/omniauth_identity_linker_base.rb b/lib/gitlab/auth/omniauth_identity_linker_base.rb
index 8ae29a02a13..253445570f2 100644
--- a/lib/gitlab/auth/omniauth_identity_linker_base.rb
+++ b/lib/gitlab/auth/omniauth_identity_linker_base.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
class OmniauthIdentityLinkerBase
diff --git a/lib/gitlab/auth/request_authenticator.rb b/lib/gitlab/auth/request_authenticator.rb
index 66de52506ce..cb9f2582936 100644
--- a/lib/gitlab/auth/request_authenticator.rb
+++ b/lib/gitlab/auth/request_authenticator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Use for authentication only, in particular for Rack::Attack.
# Does not perform authorization of scopes, etc.
module Gitlab
diff --git a/lib/gitlab/auth/result.rb b/lib/gitlab/auth/result.rb
index 00cdc94a9ef..78fa25c5516 100644
--- a/lib/gitlab/auth/result.rb
+++ b/lib/gitlab/auth/result.rb
@@ -1,4 +1,7 @@
-module Gitlab # rubocop:disable Naming/FileName
+# rubocop:disable Naming/FileName
+# frozen_string_literal: true
+
+module Gitlab
module Auth
Result = Struct.new(:actor, :project, :type, :authentication_abilities) do
def ci?(for_project)
diff --git a/lib/gitlab/auth/saml/auth_hash.rb b/lib/gitlab/auth/saml/auth_hash.rb
index 3bc5e2864df..316354fd50c 100644
--- a/lib/gitlab/auth/saml/auth_hash.rb
+++ b/lib/gitlab/auth/saml/auth_hash.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
module Saml
diff --git a/lib/gitlab/auth/saml/config.rb b/lib/gitlab/auth/saml/config.rb
index 625dab7c6f4..8cb999f50d4 100644
--- a/lib/gitlab/auth/saml/config.rb
+++ b/lib/gitlab/auth/saml/config.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
module Saml
diff --git a/lib/gitlab/auth/saml/identity_linker.rb b/lib/gitlab/auth/saml/identity_linker.rb
index 7e4b191d512..ae0d6dded4e 100644
--- a/lib/gitlab/auth/saml/identity_linker.rb
+++ b/lib/gitlab/auth/saml/identity_linker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
module Saml
diff --git a/lib/gitlab/auth/saml/user.rb b/lib/gitlab/auth/saml/user.rb
index 6c3b75f3eb0..ec95bc46791 100644
--- a/lib/gitlab/auth/saml/user.rb
+++ b/lib/gitlab/auth/saml/user.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# SAML extension for User model
#
# * Find GitLab user based on SAML uid and provider
diff --git a/lib/gitlab/auth/too_many_ips.rb b/lib/gitlab/auth/too_many_ips.rb
index ed862791551..ee4d80e6b89 100644
--- a/lib/gitlab/auth/too_many_ips.rb
+++ b/lib/gitlab/auth/too_many_ips.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
class TooManyIps < StandardError
diff --git a/lib/gitlab/auth/unique_ips_limiter.rb b/lib/gitlab/auth/unique_ips_limiter.rb
index baa1f802d8a..31dd61ae6cf 100644
--- a/lib/gitlab/auth/unique_ips_limiter.rb
+++ b/lib/gitlab/auth/unique_ips_limiter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
class UniqueIpsLimiter
diff --git a/lib/gitlab/auth/user_access_denied_reason.rb b/lib/gitlab/auth/user_access_denied_reason.rb
index 1893cb001b2..fd09fe76c02 100644
--- a/lib/gitlab/auth/user_access_denied_reason.rb
+++ b/lib/gitlab/auth/user_access_denied_reason.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
class UserAccessDeniedReason
diff --git a/lib/gitlab/auth/user_auth_finders.rb b/lib/gitlab/auth/user_auth_finders.rb
index 064cba43278..5df6db6f366 100644
--- a/lib/gitlab/auth/user_auth_finders.rb
+++ b/lib/gitlab/auth/user_auth_finders.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
AuthenticationError = Class.new(StandardError)
diff --git a/lib/gitlab/badge/base.rb b/lib/gitlab/badge/base.rb
index 909fa24fa90..fb55b9e2f1f 100644
--- a/lib/gitlab/badge/base.rb
+++ b/lib/gitlab/badge/base.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Badge
class Base
diff --git a/lib/gitlab/badge/coverage/metadata.rb b/lib/gitlab/badge/coverage/metadata.rb
index e898f5d790e..9181ba2d4b0 100644
--- a/lib/gitlab/badge/coverage/metadata.rb
+++ b/lib/gitlab/badge/coverage/metadata.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Badge
module Coverage
diff --git a/lib/gitlab/badge/coverage/report.rb b/lib/gitlab/badge/coverage/report.rb
index 16fd6f01495..a7fcb6b0fca 100644
--- a/lib/gitlab/badge/coverage/report.rb
+++ b/lib/gitlab/badge/coverage/report.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Badge
module Coverage
diff --git a/lib/gitlab/badge/coverage/template.rb b/lib/gitlab/badge/coverage/template.rb
index afbf9dd17e3..817dc28f84a 100644
--- a/lib/gitlab/badge/coverage/template.rb
+++ b/lib/gitlab/badge/coverage/template.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Badge
module Coverage
diff --git a/lib/gitlab/badge/metadata.rb b/lib/gitlab/badge/metadata.rb
index 8ad6f3cb986..b9ae68134b0 100644
--- a/lib/gitlab/badge/metadata.rb
+++ b/lib/gitlab/badge/metadata.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Badge
##
diff --git a/lib/gitlab/badge/pipeline/metadata.rb b/lib/gitlab/badge/pipeline/metadata.rb
index db1e9f8cfb8..d4d789558c9 100644
--- a/lib/gitlab/badge/pipeline/metadata.rb
+++ b/lib/gitlab/badge/pipeline/metadata.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Badge
module Pipeline
diff --git a/lib/gitlab/badge/pipeline/status.rb b/lib/gitlab/badge/pipeline/status.rb
index d1d9b7949f5..37e61f07e5b 100644
--- a/lib/gitlab/badge/pipeline/status.rb
+++ b/lib/gitlab/badge/pipeline/status.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Badge
module Pipeline
diff --git a/lib/gitlab/badge/pipeline/template.rb b/lib/gitlab/badge/pipeline/template.rb
index e09db32262d..64c3dfcd10b 100644
--- a/lib/gitlab/badge/pipeline/template.rb
+++ b/lib/gitlab/badge/pipeline/template.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Badge
module Pipeline
diff --git a/lib/gitlab/badge/template.rb b/lib/gitlab/badge/template.rb
index bfeb0052642..ed2ec50b197 100644
--- a/lib/gitlab/badge/template.rb
+++ b/lib/gitlab/badge/template.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Badge
##
diff --git a/lib/gitlab/bare_repository_import/importer.rb b/lib/gitlab/bare_repository_import/importer.rb
index 04aa6aab771..3cd327f5109 100644
--- a/lib/gitlab/bare_repository_import/importer.rb
+++ b/lib/gitlab/bare_repository_import/importer.rb
@@ -1,10 +1,15 @@
+# frozen_string_literal: true
+
module Gitlab
module BareRepositoryImport
class Importer
NoAdminError = Class.new(StandardError)
def self.execute(import_path)
- import_path << '/' unless import_path.ends_with?('/')
+ unless import_path.ends_with?('/')
+ import_path = "#{import_path}/"
+ end
+
repos_to_import = Dir.glob(import_path + '**/*.git')
unless user = User.admins.order_id_asc.first
diff --git a/lib/gitlab/bare_repository_import/repository.rb b/lib/gitlab/bare_repository_import/repository.rb
index c0c666dfb7b..b903c581aac 100644
--- a/lib/gitlab/bare_repository_import/repository.rb
+++ b/lib/gitlab/bare_repository_import/repository.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module BareRepositoryImport
class Repository
@@ -6,9 +8,12 @@ module Gitlab
attr_reader :group_path, :project_name, :repo_path
def initialize(root_path, repo_path)
+ unless root_path.ends_with?('/')
+ root_path = "#{root_path}/"
+ end
+
@root_path = root_path
@repo_path = repo_path
- @root_path << '/' unless root_path.ends_with?('/')
full_path =
if hashed? && !wiki?
diff --git a/lib/gitlab/bitbucket_import/importer.rb b/lib/gitlab/bitbucket_import/importer.rb
index a7dfccea2f6..45e550b3450 100644
--- a/lib/gitlab/bitbucket_import/importer.rb
+++ b/lib/gitlab/bitbucket_import/importer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module BitbucketImport
class Importer
diff --git a/lib/gitlab/bitbucket_import/project_creator.rb b/lib/gitlab/bitbucket_import/project_creator.rb
index d94f70fd1fb..11070a68e02 100644
--- a/lib/gitlab/bitbucket_import/project_creator.rb
+++ b/lib/gitlab/bitbucket_import/project_creator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module BitbucketImport
class ProjectCreator
diff --git a/lib/gitlab/bitbucket_server_import/project_creator.rb b/lib/gitlab/bitbucket_server_import/project_creator.rb
index 35e8cd7e0ab..48ca4951957 100644
--- a/lib/gitlab/bitbucket_server_import/project_creator.rb
+++ b/lib/gitlab/bitbucket_server_import/project_creator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module BitbucketServerImport
class ProjectCreator
diff --git a/lib/gitlab/blob_helper.rb b/lib/gitlab/blob_helper.rb
new file mode 100644
index 00000000000..9b3b383b0c8
--- /dev/null
+++ b/lib/gitlab/blob_helper.rb
@@ -0,0 +1,145 @@
+# This has been extracted from https://github.com/github/linguist/blob/master/lib/linguist/blob_helper.rb
+module Gitlab
+ module BlobHelper
+ def extname
+ File.extname(name.to_s)
+ end
+
+ def known_extension?
+ LanguageData.extensions.include?(extname)
+ end
+
+ def viewable?
+ !large? && text?
+ end
+
+ MEGABYTE = 1024 * 1024
+
+ def large?
+ size.to_i > MEGABYTE
+ end
+
+ def binary?
+ # Large blobs aren't even loaded into memory
+ if data.nil?
+ true
+
+ # Treat blank files as text
+ elsif data == ""
+ false
+
+ # Charlock doesn't know what to think
+ elsif encoding.nil?
+ true
+
+ # If Charlock says its binary
+ else
+ detect_encoding[:type] == :binary
+ end
+ end
+
+ def text?
+ !binary?
+ end
+
+ def image?
+ ['.png', '.jpg', '.jpeg', '.gif'].include?(extname.downcase)
+ end
+
+ # Internal: Lookup mime type for extension.
+ #
+ # Returns a MIME::Type
+ # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ def _mime_type
+ if defined? @_mime_type
+ @_mime_type
+ else
+ guesses = ::MIME::Types.type_for(extname.to_s)
+
+ # Prefer text mime types over binary
+ @_mime_type = guesses.detect { |type| type.ascii? } || guesses.first
+ end
+ end
+ # rubocop:enable Gitlab/ModuleWithInstanceVariables
+
+ # Public: Get the actual blob mime type
+ #
+ # Examples
+ #
+ # # => 'text/plain'
+ # # => 'text/html'
+ #
+ # Returns a mime type String.
+ def mime_type
+ _mime_type ? _mime_type.to_s : 'text/plain'
+ end
+
+ def binary_mime_type?
+ _mime_type ? _mime_type.binary? : false
+ end
+
+ def lines
+ @lines ||=
+ if viewable? && data
+ # `data` is usually encoded as ASCII-8BIT even when the content has
+ # been detected as a different encoding. However, we are not allowed
+ # to change the encoding of `data` because we've made the implicit
+ # guarantee that each entry in `lines` is encoded the same way as
+ # `data`.
+ #
+ # Instead, we re-encode each possible newline sequence as the
+ # detected encoding, then force them back to the encoding of `data`
+ # (usually a binary encoding like ASCII-8BIT). This means that the
+ # byte sequence will match how newlines are likely encoded in the
+ # file, but we don't have to change the encoding of `data` as far as
+ # Ruby is concerned. This allows us to correctly parse out each line
+ # without changing the encoding of `data`, and
+ # also--importantly--without having to duplicate many (potentially
+ # large) strings.
+ begin
+ data.split(encoded_newlines_re, -1)
+ rescue Encoding::ConverterNotFoundError
+ # The data is not splittable in the detected encoding. Assume it's
+ # one big line.
+ [data]
+ end
+ else
+ []
+ end
+ end
+
+ def content_type
+ # rubocop:disable Style/MultilineTernaryOperator
+ # rubocop:disable Style/NestedTernaryOperator
+ @content_type ||= binary_mime_type? || binary? ? mime_type :
+ (encoding ? "text/plain; charset=#{encoding.downcase}" : "text/plain")
+ # rubocop:enable Style/NestedTernaryOperator
+ # rubocop:enable Style/MultilineTernaryOperator
+ end
+
+ def encoded_newlines_re
+ @encoded_newlines_re ||=
+ Regexp.union(["\r\n", "\r", "\n"].map { |nl| nl.encode(ruby_encoding, "ASCII-8BIT").force_encoding(data.encoding) })
+ end
+
+ def ruby_encoding
+ if hash = detect_encoding
+ hash[:ruby_encoding]
+ end
+ end
+
+ def encoding
+ if hash = detect_encoding
+ hash[:encoding]
+ end
+ end
+
+ def detect_encoding
+ @detect_encoding ||= CharlockHolmes::EncodingDetector.new.detect(data) if data # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ end
+
+ def empty?
+ data.nil? || data == ""
+ end
+ end
+end
diff --git a/lib/gitlab/cache/ci/project_pipeline_status.rb b/lib/gitlab/cache/ci/project_pipeline_status.rb
index add048d671e..b369b9e7600 100644
--- a/lib/gitlab/cache/ci/project_pipeline_status.rb
+++ b/lib/gitlab/cache/ci/project_pipeline_status.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# This class is not backed by a table in the main database.
# It loads the latest Pipeline for the HEAD of a repository, and caches that
# in Redis.
diff --git a/lib/gitlab/cache/request_cache.rb b/lib/gitlab/cache/request_cache.rb
index b96e161a5b6..4c658dc0b8d 100644
--- a/lib/gitlab/cache/request_cache.rb
+++ b/lib/gitlab/cache/request_cache.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Cache
# See https://docs.gitlab.com/ee/development/utilities.html#requestcache
diff --git a/lib/gitlab/checks/change_access.rb b/lib/gitlab/checks/change_access.rb
index 7a4224e5bbe..49e7f7e1fd7 100644
--- a/lib/gitlab/checks/change_access.rb
+++ b/lib/gitlab/checks/change_access.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Checks
class ChangeAccess
diff --git a/lib/gitlab/checks/commit_check.rb b/lib/gitlab/checks/commit_check.rb
index 7e0c34aada3..6dd74e8fb74 100644
--- a/lib/gitlab/checks/commit_check.rb
+++ b/lib/gitlab/checks/commit_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Checks
class CommitCheck
diff --git a/lib/gitlab/checks/force_push.rb b/lib/gitlab/checks/force_push.rb
index 87af4a90572..263972923ed 100644
--- a/lib/gitlab/checks/force_push.rb
+++ b/lib/gitlab/checks/force_push.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Checks
class ForcePush
diff --git a/lib/gitlab/checks/lfs_integrity.rb b/lib/gitlab/checks/lfs_integrity.rb
index 3f7adecc621..fa3dc1808df 100644
--- a/lib/gitlab/checks/lfs_integrity.rb
+++ b/lib/gitlab/checks/lfs_integrity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Checks
class LfsIntegrity
diff --git a/lib/gitlab/checks/matching_merge_request.rb b/lib/gitlab/checks/matching_merge_request.rb
index 86f4aaeb4d3..71361b12d07 100644
--- a/lib/gitlab/checks/matching_merge_request.rb
+++ b/lib/gitlab/checks/matching_merge_request.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Checks
class MatchingMergeRequest
diff --git a/lib/gitlab/checks/post_push_message.rb b/lib/gitlab/checks/post_push_message.rb
index 473c0385b34..492dbb5a596 100644
--- a/lib/gitlab/checks/post_push_message.rb
+++ b/lib/gitlab/checks/post_push_message.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Checks
class PostPushMessage
diff --git a/lib/gitlab/checks/project_created.rb b/lib/gitlab/checks/project_created.rb
index cec270d6a58..0058a402a62 100644
--- a/lib/gitlab/checks/project_created.rb
+++ b/lib/gitlab/checks/project_created.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Checks
class ProjectCreated < PostPushMessage
diff --git a/lib/gitlab/checks/project_moved.rb b/lib/gitlab/checks/project_moved.rb
index 3a197078d08..cb3b7acaaad 100644
--- a/lib/gitlab/checks/project_moved.rb
+++ b/lib/gitlab/checks/project_moved.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Checks
class ProjectMoved < PostPushMessage
diff --git a/lib/gitlab/ci/templates/Android.gitlab-ci.yml b/lib/gitlab/ci/templates/Android.gitlab-ci.yml
index 5f9d54ff574..bf7831b937c 100644
--- a/lib/gitlab/ci/templates/Android.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Android.gitlab-ci.yml
@@ -2,33 +2,33 @@
image: openjdk:8-jdk
variables:
- ANDROID_COMPILE_SDK: "25"
- ANDROID_BUILD_TOOLS: "24.0.0"
- ANDROID_SDK_TOOLS: "24.4.1"
+ ANDROID_COMPILE_SDK: "28"
+ ANDROID_BUILD_TOOLS: "28.0.3"
+ ANDROID_SDK_TOOLS: "26.1.1"
before_script:
- - apt-get --quiet update --yes
- - apt-get --quiet install --yes wget tar unzip lib32stdc++6 lib32z1
- - wget --quiet --output-document=android-sdk.tgz https://dl.google.com/android/android-sdk_r${ANDROID_SDK_TOOLS}-linux.tgz
- - tar --extract --gzip --file=android-sdk.tgz
- - echo y | android-sdk-linux/tools/android --silent update sdk --no-ui --all --filter android-${ANDROID_COMPILE_SDK}
- - echo y | android-sdk-linux/tools/android --silent update sdk --no-ui --all --filter platform-tools
- - echo y | android-sdk-linux/tools/android --silent update sdk --no-ui --all --filter build-tools-${ANDROID_BUILD_TOOLS}
- - echo y | android-sdk-linux/tools/android --silent update sdk --no-ui --all --filter extra-android-m2repository
- - echo y | android-sdk-linux/tools/android --silent update sdk --no-ui --all --filter extra-google-google_play_services
- - echo y | android-sdk-linux/tools/android --silent update sdk --no-ui --all --filter extra-google-m2repository
- - export ANDROID_HOME=$PWD/android-sdk-linux
- - export PATH=$PATH:$PWD/android-sdk-linux/platform-tools/
- - chmod +x ./gradlew
+- apt-get --quiet update --yes
+- apt-get --quiet install --yes wget tar unzip lib32stdc++6 lib32z1
+- wget --quiet --output-document=android-sdk.zip https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip
+- unzip android-sdk.zip -d android-sdk-linux
+- echo y | android-sdk-linux/tools/bin/sdkmanager "platforms;android-${ANDROID_COMPILE_SDK}" > /dev/null
+- echo y | android-sdk-linux/tools/bin/sdkmanager platform-tools > /dev/null
+- echo y | android-sdk-linux/tools/bin/sdkmanager "build-tools;${ANDROID_BUILD_TOOLS}" > /dev/null
+- echo y | android-sdk-linux/tools/bin/sdkmanager "extras;google;google_play_services" > /dev/null
+- echo y | android-sdk-linux/tools/bin/sdkmanager "extras;google;m2repository" > /dev/null
+- export ANDROID_HOME=$PWD/android-sdk-linux
+- export PATH=$PATH:$PWD/android-sdk-linux/platform-tools/
+- yes | android-sdk-linux/tools/bin/sdkmanager --licenses &
+- chmod +x ./gradlew
stages:
- - build
- - test
+- build
+- test
build:
stage: build
script:
- - ./gradlew assembleDebug
+ - ./gradlew assembleDebug
artifacts:
paths:
- app/build/outputs/
@@ -36,7 +36,7 @@ build:
unitTests:
stage: test
script:
- - ./gradlew test
+ - ./gradlew test
functionalTests:
stage: test
diff --git a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
index 72547c1b407..6fa59e41d20 100644
--- a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
@@ -126,8 +126,8 @@ license_management:
artifacts:
paths: [gl-license-management-report.json]
only:
- - branches
- only:
+ refs:
+ - branches
variables:
- $GITLAB_FEATURES =~ /\blicense_management\b/
except:
diff --git a/lib/gitlab/conflict/file.rb b/lib/gitlab/conflict/file.rb
index 2a0cb640a14..30911b49b18 100644
--- a/lib/gitlab/conflict/file.rb
+++ b/lib/gitlab/conflict/file.rb
@@ -158,7 +158,6 @@ module Gitlab
json_hash.tap do |json_hash|
if opts[:full_content]
json_hash[:content] = content
- json_hash[:blob_ace_mode] = our_blob && our_blob.language.try(:ace_mode)
else
json_hash[:sections] = sections if type.text?
json_hash[:type] = type
diff --git a/lib/gitlab/file_detector.rb b/lib/gitlab/file_detector.rb
index 8f55e94975c..da62ed2fb16 100644
--- a/lib/gitlab/file_detector.rb
+++ b/lib/gitlab/file_detector.rb
@@ -18,7 +18,6 @@ module Gitlab
# Configuration files
gitignore: '.gitignore',
- koding: '.koding.yml',
gitlab_ci: '.gitlab-ci.yml',
route_map: '.gitlab/route-map.yml',
diff --git a/lib/gitlab/git/blob.rb b/lib/gitlab/git/blob.rb
index 71857bd2d87..13b0bb930f4 100644
--- a/lib/gitlab/git/blob.rb
+++ b/lib/gitlab/git/blob.rb
@@ -3,13 +3,13 @@
module Gitlab
module Git
class Blob
- include Linguist::BlobHelper
+ include Gitlab::BlobHelper
include Gitlab::EncodingHelper
# This number is the maximum amount of data that we want to display to
- # the user. We load as much as we can for encoding detection
- # (Linguist) and LFS pointer parsing. All other cases where we need full
- # blob data should use load_all_data!.
+ # the user. We load as much as we can for encoding detection and LFS
+ # pointer parsing. All other cases where we need full blob data should
+ # use load_all_data!.
MAX_DATA_DISPLAY_SIZE = 10.megabytes
# These limits are used as a heuristic to ignore files which can't be LFS
diff --git a/lib/gitlab/git/blob_snippet.rb b/lib/gitlab/git/blob_snippet.rb
deleted file mode 100644
index 68116e775c6..00000000000
--- a/lib/gitlab/git/blob_snippet.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# Gitaly note: JV: no RPC's here.
-
-module Gitlab
- module Git
- class BlobSnippet
- include Linguist::BlobHelper
-
- attr_accessor :ref
- attr_accessor :lines
- attr_accessor :filename
- attr_accessor :startline
-
- def initialize(ref, lines, startline, filename)
- @ref, @lines, @startline, @filename = ref, lines, startline, filename
- end
-
- def data
- lines&.join("\n")
- end
-
- def name
- filename
- end
-
- def size
- data.length
- end
-
- def mode
- nil
- end
- end
- end
-end
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 4218e812146..9df04372cc2 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -382,9 +382,9 @@ module Gitlab
end
# Returns the SHA of the most recent common ancestor of +from+ and +to+
- def merge_base(from, to)
+ def merge_base(*commits)
wrapped_gitaly_errors do
- gitaly_repository_client.find_merge_base(from, to)
+ gitaly_repository_client.find_merge_base(*commits)
end
end
diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb
index deaa14c8434..c1726659a90 100644
--- a/lib/gitlab/gon_helper.rb
+++ b/lib/gitlab/gon_helper.rb
@@ -30,5 +30,20 @@ module Gitlab
gon.current_user_avatar_url = current_user.avatar_url
end
end
+
+ # Exposes the state of a feature flag to the frontend code.
+ #
+ # name - The name of the feature flag, e.g. `my_feature`.
+ # args - Any additional arguments to pass to `Feature.enabled?`. This allows
+ # you to check if a flag is enabled for a particular user.
+ def push_frontend_feature_flag(name, *args)
+ var_name = name.to_s.camelize(:lower)
+ enabled = Feature.enabled?(name, *args)
+
+ # Here the `true` argument signals gon that the value should be merged
+ # into any existing ones, instead of overwriting them. This allows you to
+ # use this method to push multiple feature flags.
+ gon.push({ features: { var_name => enabled } }, true)
+ end
end
end
diff --git a/lib/gitlab/language_data.rb b/lib/gitlab/language_data.rb
new file mode 100644
index 00000000000..bfdd7175198
--- /dev/null
+++ b/lib/gitlab/language_data.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module LanguageData
+ EXTENSION_MUTEX = Mutex.new
+
+ class << self
+ include Gitlab::Utils::StrongMemoize
+
+ def extensions
+ EXTENSION_MUTEX.synchronize do
+ strong_memoize(:extensions) do
+ Set.new.tap do |set|
+ YAML.load_file(Rails.root.join('vendor', 'languages.yml')).each do |_name, details|
+ details['extensions']&.each do |ext|
+ next unless ext.start_with?('.')
+
+ set << ext.downcase
+ end
+ end
+ end
+ end
+ end
+ end
+
+ def clear_extensions!
+ EXTENSION_MUTEX.synchronize do
+ clear_memoization(:extensions)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/path_regex.rb b/lib/gitlab/path_regex.rb
index 359dd2bcbc7..a78314afdb2 100644
--- a/lib/gitlab/path_regex.rb
+++ b/lib/gitlab/path_regex.rb
@@ -39,7 +39,6 @@ module Gitlab
import
invites
jwt
- koding
login
notification_settings
oauth
diff --git a/lib/google_api/auth.rb b/lib/google_api/auth.rb
index 1aeaa387a49..e724e58e9ca 100644
--- a/lib/google_api/auth.rb
+++ b/lib/google_api/auth.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module GoogleApi
class Auth
attr_reader :access_token, :redirect_uri, :state
diff --git a/lib/google_api/cloud_platform/client.rb b/lib/google_api/cloud_platform/client.rb
index 77b6610286f..e74ff6a9129 100644
--- a/lib/google_api/cloud_platform/client.rb
+++ b/lib/google_api/cloud_platform/client.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'google/apis/compute_v1'
require 'google/apis/container_v1'
require 'google/apis/cloudbilling_v1'
diff --git a/lib/haml_lint/inline_javascript.rb b/lib/haml_lint/inline_javascript.rb
index adbed20f152..5ecd6169ecf 100644
--- a/lib/haml_lint/inline_javascript.rb
+++ b/lib/haml_lint/inline_javascript.rb
@@ -1,4 +1,7 @@
-unless Rails.env.production? # rubocop:disable Naming/FileName
+# rubocop:disable Naming/FileName
+# frozen_string_literal: true
+
+unless Rails.env.production?
require 'haml_lint/haml_visitor'
require 'haml_lint/linter'
require 'haml_lint/linter_registry'
diff --git a/lib/json_web_token/rsa_token.rb b/lib/json_web_token/rsa_token.rb
index d6d6af7089c..160e1e506f1 100644
--- a/lib/json_web_token/rsa_token.rb
+++ b/lib/json_web_token/rsa_token.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module JSONWebToken
class RSAToken < Token
attr_reader :key_file
diff --git a/lib/json_web_token/token.rb b/lib/json_web_token/token.rb
index 5b67715b0b2..ce5d6f248d0 100644
--- a/lib/json_web_token/token.rb
+++ b/lib/json_web_token/token.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module JSONWebToken
class Token
attr_accessor :issuer, :subject, :audience, :id
diff --git a/lib/mattermost/client.rb b/lib/mattermost/client.rb
index d80cd7d2a4e..293d0c563c5 100644
--- a/lib/mattermost/client.rb
+++ b/lib/mattermost/client.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Mattermost
ClientError = Class.new(Mattermost::Error)
diff --git a/lib/mattermost/command.rb b/lib/mattermost/command.rb
index 704813dfdf0..a02745486d6 100644
--- a/lib/mattermost/command.rb
+++ b/lib/mattermost/command.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Mattermost
class Command < Client
def create(params)
diff --git a/lib/mattermost/error.rb b/lib/mattermost/error.rb
index dee6deb7974..054bd5457bd 100644
--- a/lib/mattermost/error.rb
+++ b/lib/mattermost/error.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Mattermost
Error = Class.new(StandardError)
end
diff --git a/lib/mattermost/session.rb b/lib/mattermost/session.rb
index 2aa7a2f64d8..e2083848a8d 100644
--- a/lib/mattermost/session.rb
+++ b/lib/mattermost/session.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Mattermost
class NoSessionError < Mattermost::Error
def message
diff --git a/lib/mattermost/team.rb b/lib/mattermost/team.rb
index 95c2f6f9d6b..58120178f50 100644
--- a/lib/mattermost/team.rb
+++ b/lib/mattermost/team.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Mattermost
class Team < Client
# Returns all teams that the current user is a member of
diff --git a/lib/microsoft_teams/activity.rb b/lib/microsoft_teams/activity.rb
index d2c420efdaf..207e90d2638 100644
--- a/lib/microsoft_teams/activity.rb
+++ b/lib/microsoft_teams/activity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module MicrosoftTeams
class Activity
def initialize(title:, subtitle:, text:, image:)
diff --git a/lib/microsoft_teams/notifier.rb b/lib/microsoft_teams/notifier.rb
index 226ee1373db..c7dec09ba6b 100644
--- a/lib/microsoft_teams/notifier.rb
+++ b/lib/microsoft_teams/notifier.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module MicrosoftTeams
class Notifier
def initialize(webhook)
diff --git a/lib/object_storage/direct_upload.rb b/lib/object_storage/direct_upload.rb
index 97f56e10ccf..fd26663fef0 100644
--- a/lib/object_storage/direct_upload.rb
+++ b/lib/object_storage/direct_upload.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ObjectStorage
#
# The DirectUpload c;ass generates a set of presigned URLs
diff --git a/lib/omni_auth/strategies/bitbucket.rb b/lib/omni_auth/strategies/bitbucket.rb
index ce1bdfe6ee4..6c914b4222a 100644
--- a/lib/omni_auth/strategies/bitbucket.rb
+++ b/lib/omni_auth/strategies/bitbucket.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'omniauth-oauth2'
module OmniAuth
diff --git a/lib/omni_auth/strategies/jwt.rb b/lib/omni_auth/strategies/jwt.rb
index ebdb5c7faf0..a792903fde7 100644
--- a/lib/omni_auth/strategies/jwt.rb
+++ b/lib/omni_auth/strategies/jwt.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'omniauth'
require 'jwt'
diff --git a/lib/peek/rblineprof/custom_controller_helpers.rb b/lib/peek/rblineprof/custom_controller_helpers.rb
index 9beb442bfa3..581cc6a37b4 100644
--- a/lib/peek/rblineprof/custom_controller_helpers.rb
+++ b/lib/peek/rblineprof/custom_controller_helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Peek
module Rblineprof
module CustomControllerHelpers
@@ -41,7 +43,7 @@ module Peek
]
end.sort_by{ |a,b,c,d,e,f| -f }
- output = "<div class='modal-dialog modal-xl'><div class='modal-content'>"
+ output = ["<div class='modal-dialog modal-xl'><div class='modal-content'>"]
output << "<div class='modal-header'>"
output << "<h4>Line profiling: #{human_description(params[:lineprofiler])}</h4>"
output << "<button class='close' type='button' data-dismiss='modal' aria-label='close'><span aria-hidden='true'>&times;</span></button>"
@@ -93,7 +95,7 @@ module Peek
output << "</div></div></div>"
- response.body += "<div class='modal' id='modal-peek-line-profile' tabindex=-1>#{output}</div>".html_safe
+ response.body += "<div class='modal' id='modal-peek-line-profile' tabindex=-1>#{output.join}</div>".html_safe
end
ret
diff --git a/lib/peek/views/gitaly.rb b/lib/peek/views/gitaly.rb
index ab35f7a2258..860963ef94f 100644
--- a/lib/peek/views/gitaly.rb
+++ b/lib/peek/views/gitaly.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Peek
module Views
class Gitaly < View
diff --git a/lib/peek/views/host.rb b/lib/peek/views/host.rb
index 43c8a35c7ea..b77355ea11b 100644
--- a/lib/peek/views/host.rb
+++ b/lib/peek/views/host.rb
@@ -1,8 +1,13 @@
+# frozen_string_literal: true
+
module Peek
module Views
class Host < View
def results
- { hostname: Gitlab::Environment.hostname }
+ {
+ hostname: Gitlab::Environment.hostname,
+ canary: Gitlab::Utils.to_boolean(ENV['CANARY'])
+ }
end
end
end
diff --git a/lib/rouge/formatters/html_gitlab.rb b/lib/rouge/formatters/html_gitlab.rb
index e877ab10248..e2a7d3ef5ba 100644
--- a/lib/rouge/formatters/html_gitlab.rb
+++ b/lib/rouge/formatters/html_gitlab.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rouge
module Formatters
class HTMLGitlab < Rouge::Formatters::HTML
diff --git a/lib/rouge/plugins/common_mark.rb b/lib/rouge/plugins/common_mark.rb
index 8f9de061124..d240df5a0e0 100644
--- a/lib/rouge/plugins/common_mark.rb
+++ b/lib/rouge/plugins/common_mark.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# A rouge plugin for CommonMark markdown engine.
# Used to highlight code generated by CommonMark.
diff --git a/lib/rspec_flaky/config.rb b/lib/rspec_flaky/config.rb
index 06e96f969f1..55c1d4747b4 100644
--- a/lib/rspec_flaky/config.rb
+++ b/lib/rspec_flaky/config.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module RspecFlaky
class Config
def self.generate_report?
diff --git a/lib/rspec_flaky/example.rb b/lib/rspec_flaky/example.rb
index b6e790cbbab..3c1b05257a0 100644
--- a/lib/rspec_flaky/example.rb
+++ b/lib/rspec_flaky/example.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module RspecFlaky
# This is a wrapper class for RSpec::Core::Example
class Example
diff --git a/lib/rspec_flaky/flaky_example.rb b/lib/rspec_flaky/flaky_example.rb
index 6be24014d89..da5dbf06bc9 100644
--- a/lib/rspec_flaky/flaky_example.rb
+++ b/lib/rspec_flaky/flaky_example.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module RspecFlaky
# This represents a flaky RSpec example and is mainly meant to be saved in a JSON file
class FlakyExample < OpenStruct
diff --git a/lib/rspec_flaky/flaky_examples_collection.rb b/lib/rspec_flaky/flaky_examples_collection.rb
index dea23c325be..290a51766e9 100644
--- a/lib/rspec_flaky/flaky_examples_collection.rb
+++ b/lib/rspec_flaky/flaky_examples_collection.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'active_support/hash_with_indifferent_access'
require_relative 'flaky_example'
diff --git a/lib/rspec_flaky/listener.rb b/lib/rspec_flaky/listener.rb
index 9cd0c38cb55..19cc0baa2d3 100644
--- a/lib/rspec_flaky/listener.rb
+++ b/lib/rspec_flaky/listener.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'json'
require_dependency 'rspec_flaky/config'
diff --git a/lib/rspec_flaky/report.rb b/lib/rspec_flaky/report.rb
index 1c362fdd20d..9a0fb88c424 100644
--- a/lib/rspec_flaky/report.rb
+++ b/lib/rspec_flaky/report.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'json'
require 'time'
diff --git a/lib/system_check/app/active_users_check.rb b/lib/system_check/app/active_users_check.rb
index 1d72c8d6903..8446c2fc2c8 100644
--- a/lib/system_check/app/active_users_check.rb
+++ b/lib/system_check/app/active_users_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class ActiveUsersCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/database_config_exists_check.rb b/lib/system_check/app/database_config_exists_check.rb
index d1fae192350..1769145ed63 100644
--- a/lib/system_check/app/database_config_exists_check.rb
+++ b/lib/system_check/app/database_config_exists_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class DatabaseConfigExistsCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/git_config_check.rb b/lib/system_check/app/git_config_check.rb
index d08a81639e3..4e8d607096c 100644
--- a/lib/system_check/app/git_config_check.rb
+++ b/lib/system_check/app/git_config_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class GitConfigCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/git_user_default_ssh_config_check.rb b/lib/system_check/app/git_user_default_ssh_config_check.rb
index ad41760dff2..6cd53779bfd 100644
--- a/lib/system_check/app/git_user_default_ssh_config_check.rb
+++ b/lib/system_check/app/git_user_default_ssh_config_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class GitUserDefaultSSHConfigCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/git_version_check.rb b/lib/system_check/app/git_version_check.rb
index 44ec888c197..994af3ab53e 100644
--- a/lib/system_check/app/git_version_check.rb
+++ b/lib/system_check/app/git_version_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class GitVersionCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/gitlab_config_exists_check.rb b/lib/system_check/app/gitlab_config_exists_check.rb
index 247aa0994e4..1cc5ead0d89 100644
--- a/lib/system_check/app/gitlab_config_exists_check.rb
+++ b/lib/system_check/app/gitlab_config_exists_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class GitlabConfigExistsCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/gitlab_config_up_to_date_check.rb b/lib/system_check/app/gitlab_config_up_to_date_check.rb
index c609e48e133..58c7e3039c8 100644
--- a/lib/system_check/app/gitlab_config_up_to_date_check.rb
+++ b/lib/system_check/app/gitlab_config_up_to_date_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class GitlabConfigUpToDateCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/init_script_exists_check.rb b/lib/system_check/app/init_script_exists_check.rb
index d246e058e86..d36dbe7d67d 100644
--- a/lib/system_check/app/init_script_exists_check.rb
+++ b/lib/system_check/app/init_script_exists_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class InitScriptExistsCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/init_script_up_to_date_check.rb b/lib/system_check/app/init_script_up_to_date_check.rb
index 53a47eb0f42..569c41df6e4 100644
--- a/lib/system_check/app/init_script_up_to_date_check.rb
+++ b/lib/system_check/app/init_script_up_to_date_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class InitScriptUpToDateCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/log_writable_check.rb b/lib/system_check/app/log_writable_check.rb
index 3e0c436d6ee..e26ad143eb8 100644
--- a/lib/system_check/app/log_writable_check.rb
+++ b/lib/system_check/app/log_writable_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class LogWritableCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/migrations_are_up_check.rb b/lib/system_check/app/migrations_are_up_check.rb
index 5eedbacce77..b12e9ac6bba 100644
--- a/lib/system_check/app/migrations_are_up_check.rb
+++ b/lib/system_check/app/migrations_are_up_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class MigrationsAreUpCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/orphaned_group_members_check.rb b/lib/system_check/app/orphaned_group_members_check.rb
index 2b46d36fe51..3e6ffb8190b 100644
--- a/lib/system_check/app/orphaned_group_members_check.rb
+++ b/lib/system_check/app/orphaned_group_members_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class OrphanedGroupMembersCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/projects_have_namespace_check.rb b/lib/system_check/app/projects_have_namespace_check.rb
index a6ec9f7665c..2bf2529acf1 100644
--- a/lib/system_check/app/projects_have_namespace_check.rb
+++ b/lib/system_check/app/projects_have_namespace_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class ProjectsHaveNamespaceCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/redis_version_check.rb b/lib/system_check/app/redis_version_check.rb
index a0610e73576..890f8b44d13 100644
--- a/lib/system_check/app/redis_version_check.rb
+++ b/lib/system_check/app/redis_version_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class RedisVersionCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/ruby_version_check.rb b/lib/system_check/app/ruby_version_check.rb
index 57bbabece1f..d73c39f2c3f 100644
--- a/lib/system_check/app/ruby_version_check.rb
+++ b/lib/system_check/app/ruby_version_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class RubyVersionCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/tmp_writable_check.rb b/lib/system_check/app/tmp_writable_check.rb
index 99a75e57abf..6687df091d3 100644
--- a/lib/system_check/app/tmp_writable_check.rb
+++ b/lib/system_check/app/tmp_writable_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class TmpWritableCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/uploads_directory_exists_check.rb b/lib/system_check/app/uploads_directory_exists_check.rb
index 7026d0ba075..940eff9d4cf 100644
--- a/lib/system_check/app/uploads_directory_exists_check.rb
+++ b/lib/system_check/app/uploads_directory_exists_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class UploadsDirectoryExistsCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/uploads_path_permission_check.rb b/lib/system_check/app/uploads_path_permission_check.rb
index 7df6c060254..4a49f3bc2bb 100644
--- a/lib/system_check/app/uploads_path_permission_check.rb
+++ b/lib/system_check/app/uploads_path_permission_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class UploadsPathPermissionCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/uploads_path_tmp_permission_check.rb b/lib/system_check/app/uploads_path_tmp_permission_check.rb
index b276a81eac1..ae374f4707c 100644
--- a/lib/system_check/app/uploads_path_tmp_permission_check.rb
+++ b/lib/system_check/app/uploads_path_tmp_permission_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class UploadsPathTmpPermissionCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/base_check.rb b/lib/system_check/base_check.rb
index 0f5742dd67f..e06245294c4 100644
--- a/lib/system_check/base_check.rb
+++ b/lib/system_check/base_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
# Base class for Checks. You must inherit from here
# and implement the methods below when necessary
diff --git a/lib/system_check/helpers.rb b/lib/system_check/helpers.rb
index 6227e461d24..07d479848fe 100644
--- a/lib/system_check/helpers.rb
+++ b/lib/system_check/helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module Helpers
include ::Gitlab::TaskHelpers
diff --git a/lib/system_check/incoming_email/foreman_configured_check.rb b/lib/system_check/incoming_email/foreman_configured_check.rb
index 1db7bf2b782..944913087da 100644
--- a/lib/system_check/incoming_email/foreman_configured_check.rb
+++ b/lib/system_check/incoming_email/foreman_configured_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module IncomingEmail
class ForemanConfiguredCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/incoming_email/imap_authentication_check.rb b/lib/system_check/incoming_email/imap_authentication_check.rb
index 3550c5796b0..613c2296375 100644
--- a/lib/system_check/incoming_email/imap_authentication_check.rb
+++ b/lib/system_check/incoming_email/imap_authentication_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module IncomingEmail
class ImapAuthenticationCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/incoming_email/initd_configured_check.rb b/lib/system_check/incoming_email/initd_configured_check.rb
index ea23b8ef49c..acb4b5a9e74 100644
--- a/lib/system_check/incoming_email/initd_configured_check.rb
+++ b/lib/system_check/incoming_email/initd_configured_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module IncomingEmail
class InitdConfiguredCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/incoming_email/mail_room_running_check.rb b/lib/system_check/incoming_email/mail_room_running_check.rb
index c1807501829..b7aead4624e 100644
--- a/lib/system_check/incoming_email/mail_room_running_check.rb
+++ b/lib/system_check/incoming_email/mail_room_running_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module IncomingEmail
class MailRoomRunningCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/orphans/namespace_check.rb b/lib/system_check/orphans/namespace_check.rb
index 09b57c7b408..53b2d8fd5b3 100644
--- a/lib/system_check/orphans/namespace_check.rb
+++ b/lib/system_check/orphans/namespace_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module Orphans
class NamespaceCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/orphans/repository_check.rb b/lib/system_check/orphans/repository_check.rb
index 2695c658874..ef8fe945f61 100644
--- a/lib/system_check/orphans/repository_check.rb
+++ b/lib/system_check/orphans/repository_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module Orphans
class RepositoryCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/simple_executor.rb b/lib/system_check/simple_executor.rb
index 99c9e984107..11818ae54f8 100644
--- a/lib/system_check/simple_executor.rb
+++ b/lib/system_check/simple_executor.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
# Simple Executor is current default executor for GitLab
# It is a simple port from display logic in the old check.rake
diff --git a/locale/ar_SA/gitlab.po b/locale/ar_SA/gitlab.po
index d196fac6c60..903d72d9ea8 100644
--- a/locale/ar_SA/gitlab.po
+++ b/locale/ar_SA/gitlab.po
@@ -4410,12 +4410,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -5391,9 +5385,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -6942,9 +6933,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr ""
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/bg/gitlab.po b/locale/bg/gitlab.po
index 0d5026c0f4a..e3a5e191023 100644
--- a/locale/bg/gitlab.po
+++ b/locale/bg/gitlab.po
@@ -4266,12 +4266,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -5231,9 +5225,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -6774,9 +6765,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr "ÐаÑтройка на „Koding“"
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/ca_ES/gitlab.po b/locale/ca_ES/gitlab.po
index 1a052348522..91d5fb17000 100644
--- a/locale/ca_ES/gitlab.po
+++ b/locale/ca_ES/gitlab.po
@@ -4266,12 +4266,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -5231,9 +5225,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -6774,9 +6765,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr ""
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/cs_CZ/gitlab.po b/locale/cs_CZ/gitlab.po
index 3a2267c4bf7..867b9b27ad2 100644
--- a/locale/cs_CZ/gitlab.po
+++ b/locale/cs_CZ/gitlab.po
@@ -4338,12 +4338,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -5311,9 +5305,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -6858,9 +6849,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr ""
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/da_DK/gitlab.po b/locale/da_DK/gitlab.po
index 1a6e564ed36..f8412f28cbe 100644
--- a/locale/da_DK/gitlab.po
+++ b/locale/da_DK/gitlab.po
@@ -4266,12 +4266,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -5231,9 +5225,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -6774,9 +6765,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr ""
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/de/gitlab.po b/locale/de/gitlab.po
index c27a0dea04d..5f9fbc1cc39 100644
--- a/locale/de/gitlab.po
+++ b/locale/de/gitlab.po
@@ -4266,12 +4266,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -5231,9 +5225,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -6774,9 +6765,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr "Koding einrichten"
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/en/gitlab.po b/locale/en/gitlab.po
index b50685514e1..5e14e94e6fc 100644
--- a/locale/en/gitlab.po
+++ b/locale/en/gitlab.po
@@ -882,9 +882,6 @@ msgstr ""
msgid "Set up CI"
msgstr ""
-msgid "Set up Koding"
-msgstr ""
-
msgid "Set up auto deploy"
msgstr ""
diff --git a/locale/eo/gitlab.po b/locale/eo/gitlab.po
index d0a67a1d089..15d537ff3b4 100644
--- a/locale/eo/gitlab.po
+++ b/locale/eo/gitlab.po
@@ -4266,12 +4266,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -5231,9 +5225,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -6774,9 +6765,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr "Agordi „Koding“"
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/es/gitlab.po b/locale/es/gitlab.po
index 6ce5b6a3aff..0d8ee05b364 100644
--- a/locale/es/gitlab.po
+++ b/locale/es/gitlab.po
@@ -4266,12 +4266,6 @@ msgstr ""
msgid "June"
msgstr "Junio"
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -5231,9 +5225,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -6774,9 +6765,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr "Configurar Koding"
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/et_EE/gitlab.po b/locale/et_EE/gitlab.po
index 8e4edc84c83..1f699a8e06d 100644
--- a/locale/et_EE/gitlab.po
+++ b/locale/et_EE/gitlab.po
@@ -4266,12 +4266,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -5231,9 +5225,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -6774,9 +6765,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr ""
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/fil_PH/gitlab.po b/locale/fil_PH/gitlab.po
index 73eeb56bea2..c9b371f8df3 100644
--- a/locale/fil_PH/gitlab.po
+++ b/locale/fil_PH/gitlab.po
@@ -4266,12 +4266,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -5231,9 +5225,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -6774,9 +6765,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr ""
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/fr/gitlab.po b/locale/fr/gitlab.po
index 93b30d0ef31..1925235d48a 100644
--- a/locale/fr/gitlab.po
+++ b/locale/fr/gitlab.po
@@ -4266,12 +4266,6 @@ msgstr "juin"
msgid "June"
msgstr "juin"
-msgid "Koding"
-msgstr "Koding"
-
-msgid "Koding Dashboard"
-msgstr "Tableau de bord Koding"
-
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -5231,9 +5225,6 @@ msgstr "Un ou plusieurs de vos projets Bitbucket ne peuvent être importés dire
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr "Un ou plusieurs de vos projets Google Code ne peuvent être importés directement dans GitLab parce qu’ils utilisent Subversion ou Mercurial comme gestionnaire de versions au lieu de Git."
-msgid "Online IDE integration settings."
-msgstr "Paramètres d’intégration de l’EDI en ligne."
-
msgid "Only admins"
msgstr "Seulement les administrateurs"
@@ -6774,9 +6765,6 @@ msgstr "Définissez les exigences pour la connexion d’un utilisateur. Activez
msgid "Set up CI/CD"
msgstr "Configuration CI/CD"
-msgid "Set up Koding"
-msgstr "Configurer Koding"
-
msgid "Set up a %{type} Runner manually"
msgstr "Configurer manuellement un exécuteur %{type}"
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 8e0324eb194..b8c4eddbec1 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -423,7 +423,7 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
-msgid "Advanced"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
msgid "Advanced settings"
@@ -444,6 +444,9 @@ msgstr ""
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr ""
@@ -453,12 +456,21 @@ msgstr ""
msgid "Allow requests to the local network from hooks and services."
msgstr ""
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
@@ -1145,6 +1157,9 @@ msgstr ""
msgid "Chat"
msgstr ""
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr ""
+
msgid "Checking %{text} availability…"
msgstr ""
@@ -2474,9 +2489,6 @@ msgstr ""
msgid "Enable group Runners"
msgstr ""
-msgid "Enable or disable certain group features and choose access levels."
-msgstr ""
-
msgid "Enable or disable version check and usage ping."
msgstr ""
@@ -2984,6 +2996,9 @@ msgstr ""
msgid "Group avatar"
msgstr ""
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr ""
@@ -2993,6 +3008,9 @@ msgstr ""
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
+msgid "Group name"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -3008,9 +3026,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Share with group lock"
-msgstr ""
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr ""
@@ -3424,12 +3439,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -3496,6 +3505,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] ""
@@ -3905,6 +3917,9 @@ msgstr ""
msgid "Name:"
msgstr ""
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr ""
@@ -4197,9 +4212,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -4236,6 +4248,9 @@ msgstr ""
msgid "Operations"
msgstr ""
+msgid "Operations Dashboard"
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -4287,6 +4302,9 @@ msgstr ""
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr ""
@@ -4314,6 +4332,9 @@ msgstr ""
msgid "Permissions"
msgstr ""
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
msgid "Personal Access Token"
msgstr ""
@@ -5048,12 +5069,21 @@ msgstr ""
msgid "Remove avatar"
msgstr ""
+msgid "Remove group"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr ""
@@ -5120,6 +5150,9 @@ msgstr ""
msgid "Requests Profiles"
msgstr ""
+msgid "Require all users in this group to setup Two-factor authentication"
+msgstr ""
+
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
@@ -5425,9 +5458,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr ""
-
msgid "Set up a %{type} Runner manually"
msgstr ""
@@ -6176,6 +6206,9 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr ""
@@ -6194,6 +6227,9 @@ msgstr ""
msgid "Time before an issue starts implementation"
msgstr ""
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr ""
@@ -6477,6 +6513,9 @@ msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-factor authentication"
+msgstr ""
+
msgid "Type"
msgstr ""
@@ -6543,7 +6582,7 @@ msgstr ""
msgid "Update now"
msgstr ""
-msgid "Update your group name, description, avatar, and other general settings."
+msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
@@ -6699,6 +6738,9 @@ msgstr ""
msgid "Visibility and access controls"
msgstr ""
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -6741,6 +6783,9 @@ msgstr ""
msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
+msgid "Who can see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr ""
diff --git a/locale/gl_ES/gitlab.po b/locale/gl_ES/gitlab.po
index c77dc236458..44c47901b56 100644
--- a/locale/gl_ES/gitlab.po
+++ b/locale/gl_ES/gitlab.po
@@ -4266,12 +4266,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -5231,9 +5225,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -6774,9 +6765,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr ""
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/he_IL/gitlab.po b/locale/he_IL/gitlab.po
index ab014982a72..7cff1c5d712 100644
--- a/locale/he_IL/gitlab.po
+++ b/locale/he_IL/gitlab.po
@@ -4338,12 +4338,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -5311,9 +5305,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -6858,9 +6849,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr ""
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/id_ID/gitlab.po b/locale/id_ID/gitlab.po
index d5c48520155..2f3c35e4253 100644
--- a/locale/id_ID/gitlab.po
+++ b/locale/id_ID/gitlab.po
@@ -4230,12 +4230,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -5191,9 +5185,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -6732,9 +6723,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr ""
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/it/gitlab.po b/locale/it/gitlab.po
index 87bcd939fb1..984a200c958 100644
--- a/locale/it/gitlab.po
+++ b/locale/it/gitlab.po
@@ -4266,12 +4266,6 @@ msgstr "Giu"
msgid "June"
msgstr "Giugno"
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -5231,9 +5225,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -6774,9 +6765,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr "Configura Koding"
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/ja/gitlab.po b/locale/ja/gitlab.po
index ee5ea023fb5..ac940230ac2 100644
--- a/locale/ja/gitlab.po
+++ b/locale/ja/gitlab.po
@@ -4230,12 +4230,6 @@ msgstr "6月"
msgid "June"
msgstr "6月"
-msgid "Koding"
-msgstr "Koding"
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -5191,9 +5185,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr "オンライン IDE çµ±åˆè¨­å®šã€‚"
-
msgid "Only admins"
msgstr ""
@@ -6732,9 +6723,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr "CI/CD を設定"
-msgid "Set up Koding"
-msgstr "Koding を設定"
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/ko/gitlab.po b/locale/ko/gitlab.po
index 3c3bcf9688a..a50f5bfacef 100644
--- a/locale/ko/gitlab.po
+++ b/locale/ko/gitlab.po
@@ -4230,12 +4230,6 @@ msgstr "6ì›”"
msgid "June"
msgstr "6ì›”"
-msgid "Koding"
-msgstr "Koding"
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -5191,9 +5185,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr "온ë¼ì¸ IDE 통합 설정."
-
msgid "Only admins"
msgstr ""
@@ -6732,9 +6723,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr "Koding 설정"
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/mn_MN/gitlab.po b/locale/mn_MN/gitlab.po
index 0ed5a747cfd..c256a2d2b1f 100644
--- a/locale/mn_MN/gitlab.po
+++ b/locale/mn_MN/gitlab.po
@@ -4266,12 +4266,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -5231,9 +5225,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -6774,9 +6765,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr ""
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/nb_NO/gitlab.po b/locale/nb_NO/gitlab.po
index b04b3bb68ef..9be8a4e8d0b 100644
--- a/locale/nb_NO/gitlab.po
+++ b/locale/nb_NO/gitlab.po
@@ -4266,12 +4266,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -5231,9 +5225,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -6774,9 +6765,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr ""
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/nl_NL/gitlab.po b/locale/nl_NL/gitlab.po
index f354ca50f32..2ad2eaafc33 100644
--- a/locale/nl_NL/gitlab.po
+++ b/locale/nl_NL/gitlab.po
@@ -4266,12 +4266,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -5231,9 +5225,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -6774,9 +6765,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr ""
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/pl_PL/gitlab.po b/locale/pl_PL/gitlab.po
index 1d6dc4c4399..a4bd1fe747b 100644
--- a/locale/pl_PL/gitlab.po
+++ b/locale/pl_PL/gitlab.po
@@ -4338,12 +4338,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -5311,9 +5305,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -6858,9 +6849,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr ""
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po
index c76c639e8db..79e365319c9 100644
--- a/locale/pt_BR/gitlab.po
+++ b/locale/pt_BR/gitlab.po
@@ -4266,12 +4266,6 @@ msgstr "Jun"
msgid "June"
msgstr "Junho"
-msgid "Koding"
-msgstr "Koding"
-
-msgid "Koding Dashboard"
-msgstr "Painel de controle do Koding"
-
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -5231,9 +5225,6 @@ msgstr "Um ou mais dos seus projetos do Bitbucket não podem ser importados dire
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr "Um ou mais dos seus projetos do Google Code não podem ser importados diretamente no GitLab porque eles usam Subversion ou Mercurial para o controle de versão, ao invés de Git."
-msgid "Online IDE integration settings."
-msgstr "Configurações de integração on-line do IDE."
-
msgid "Only admins"
msgstr ""
@@ -6774,9 +6765,6 @@ msgstr "Definir requisitos para um usuário entrar. Ative a autenticação obrig
msgid "Set up CI/CD"
msgstr "Configurar CI/CD"
-msgid "Set up Koding"
-msgstr "Configurar Koding"
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/ro_RO/gitlab.po b/locale/ro_RO/gitlab.po
index bae64f360fc..49613a3f462 100644
--- a/locale/ro_RO/gitlab.po
+++ b/locale/ro_RO/gitlab.po
@@ -4302,12 +4302,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -5271,9 +5265,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -6816,9 +6807,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr ""
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/ru/gitlab.po b/locale/ru/gitlab.po
index bc2c26da457..b8a4805498b 100644
--- a/locale/ru/gitlab.po
+++ b/locale/ru/gitlab.po
@@ -4338,12 +4338,6 @@ msgstr "Июн."
msgid "June"
msgstr "Июнь"
-msgid "Koding"
-msgstr "Koding"
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -5311,9 +5305,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -6858,9 +6849,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr "ÐаÑтройка CI/CD"
-msgid "Set up Koding"
-msgstr "ÐаÑтройка Koding"
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/sq_AL/gitlab.po b/locale/sq_AL/gitlab.po
index 42eeed11534..633b2a6bda7 100644
--- a/locale/sq_AL/gitlab.po
+++ b/locale/sq_AL/gitlab.po
@@ -4266,12 +4266,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -5231,9 +5225,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -6774,9 +6765,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr ""
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/tr_TR/gitlab.po b/locale/tr_TR/gitlab.po
index d1087ffd29e..723f4876053 100644
--- a/locale/tr_TR/gitlab.po
+++ b/locale/tr_TR/gitlab.po
@@ -4266,12 +4266,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -5231,9 +5225,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -6774,9 +6765,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr ""
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/uk/gitlab.po b/locale/uk/gitlab.po
index 33019a3e5a8..99ba26152ee 100644
--- a/locale/uk/gitlab.po
+++ b/locale/uk/gitlab.po
@@ -4338,12 +4338,6 @@ msgstr "чер."
msgid "June"
msgstr "червень"
-msgid "Koding"
-msgstr "Koding"
-
-msgid "Koding Dashboard"
-msgstr "Панель ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Koding"
-
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -5311,9 +5305,6 @@ msgstr "Один або декілька ваших проектів Bitbucket Ð
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr "Один або декілька ваших проектів Google Code не можна імпортувати безпоÑередньо в GitLab, оÑкільки вони викориÑтовують Subversion або Mercurial Ð´Ð»Ñ ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»ÑŽ верÑій заміÑÑ‚ÑŒ Git."
-msgid "Online IDE integration settings."
-msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ— із онлайн IDE."
-
msgid "Only admins"
msgstr "Тільки Ðдміни"
@@ -6858,9 +6849,6 @@ msgstr "Ð’Ñтановіть вимоги Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ кориÑтувач
msgid "Set up CI/CD"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ CI/CD"
-msgid "Set up Koding"
-msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Koding"
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/zh_CN/gitlab.po b/locale/zh_CN/gitlab.po
index 861e459bcac..2d3aeca7cc7 100644
--- a/locale/zh_CN/gitlab.po
+++ b/locale/zh_CN/gitlab.po
@@ -4230,12 +4230,6 @@ msgstr "å…­"
msgid "June"
msgstr "六月"
-msgid "Koding"
-msgstr "Koding"
-
-msgid "Koding Dashboard"
-msgstr "Koding仪表æ¿"
-
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -5191,9 +5185,6 @@ msgstr "您的一个或多个Bitbucket项目无法直接导入GitLab,因为它
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr "您的一个或多个Google Code项目无法直接导入GitLab,因为它们使用Subversion或Mercurial进行版本控制,而ä¸æ˜¯Git。"
-msgid "Online IDE integration settings."
-msgstr "在线IDE集æˆè®¾ç½®ã€‚"
-
msgid "Only admins"
msgstr "仅管ç†å‘˜"
@@ -6732,9 +6723,6 @@ msgstr "设定用户登录的æ¡ä»¶ã€‚å¯ç”¨å¼ºåˆ¶åŒé‡è®¤è¯ã€‚"
msgid "Set up CI/CD"
msgstr "é…ç½® CI/CD"
-msgid "Set up Koding"
-msgstr "设置 Koding"
-
msgid "Set up a %{type} Runner manually"
msgstr "手动设置%{type}Runner "
diff --git a/locale/zh_HK/gitlab.po b/locale/zh_HK/gitlab.po
index 3ecd9fc4cd2..d8fe2d5b13e 100644
--- a/locale/zh_HK/gitlab.po
+++ b/locale/zh_HK/gitlab.po
@@ -4230,12 +4230,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -5191,9 +5185,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -6732,9 +6723,6 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr "設置 Koding"
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/locale/zh_TW/gitlab.po b/locale/zh_TW/gitlab.po
index bb907d9a583..1bccf6de738 100644
--- a/locale/zh_TW/gitlab.po
+++ b/locale/zh_TW/gitlab.po
@@ -4230,12 +4230,6 @@ msgstr "六月"
msgid "June"
msgstr "六月"
-msgid "Koding"
-msgstr "Koding"
-
-msgid "Koding Dashboard"
-msgstr "Koding 控制é¢æ¿"
-
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -5191,9 +5185,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr "線上 IDE æ•´åˆè¨­å®šã€‚"
-
msgid "Only admins"
msgstr ""
@@ -6732,9 +6723,6 @@ msgstr "設定使用者登入的需求。啟用強制性的兩步驟驗證。"
msgid "Set up CI/CD"
msgstr "設定 CI/CD"
-msgid "Set up Koding"
-msgstr "設定 Koding"
-
msgid "Set up a %{type} Runner manually"
msgstr ""
diff --git a/package.json b/package.json
index ac9a73cd2c9..dafb03bf75a 100644
--- a/package.json
+++ b/package.json
@@ -24,7 +24,7 @@
"@babel/plugin-syntax-dynamic-import": "^7.0.0",
"@babel/plugin-syntax-import-meta": "^7.0.0",
"@babel/preset-env": "^7.1.0",
- "@gitlab-org/gitlab-svgs": "^1.29.0",
+ "@gitlab-org/gitlab-svgs": "^1.32.0",
"@gitlab-org/gitlab-ui": "^1.8.0",
"autosize": "^4.0.0",
"axios": "^0.17.1",
diff --git a/qa/qa.rb b/qa/qa.rb
index a0511186e70..d6a150fa0b4 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -49,6 +49,7 @@ module QA
autoload :ProjectImportedFromGithub, 'qa/factory/resource/project_imported_from_github'
autoload :MergeRequestFromFork, 'qa/factory/resource/merge_request_from_fork'
autoload :DeployKey, 'qa/factory/resource/deploy_key'
+ autoload :DeployToken, 'qa/factory/resource/deploy_token'
autoload :Branch, 'qa/factory/resource/branch'
autoload :SecretVariable, 'qa/factory/resource/secret_variable'
autoload :Runner, 'qa/factory/resource/runner'
@@ -97,6 +98,7 @@ module QA
module Integration
autoload :Github, 'qa/scenario/test/integration/github'
autoload :LDAP, 'qa/scenario/test/integration/ldap'
+ autoload :InstanceSAML, 'qa/scenario/test/integration/instance_saml'
autoload :Kubernetes, 'qa/scenario/test/integration/kubernetes'
autoload :Mattermost, 'qa/scenario/test/integration/mattermost'
autoload :ObjectStorage, 'qa/scenario/test/integration/object_storage'
@@ -176,10 +178,12 @@ module QA
autoload :Repository, 'qa/page/project/settings/repository'
autoload :CICD, 'qa/page/project/settings/ci_cd'
autoload :DeployKeys, 'qa/page/project/settings/deploy_keys'
+ autoload :DeployTokens, 'qa/page/project/settings/deploy_tokens'
autoload :ProtectedBranches, 'qa/page/project/settings/protected_branches'
autoload :SecretVariables, 'qa/page/project/settings/secret_variables'
autoload :Runners, 'qa/page/project/settings/runners'
autoload :MergeRequest, 'qa/page/project/settings/merge_request'
+ autoload :Members, 'qa/page/project/settings/members'
end
module Issue
@@ -267,6 +271,7 @@ module QA
autoload :GroupsFilter, 'qa/page/component/groups_filter'
autoload :Select2, 'qa/page/component/select2'
autoload :DropdownFilter, 'qa/page/component/dropdown_filter'
+ autoload :UsersSelect, 'qa/page/component/users_select'
module Issuable
autoload :Common, 'qa/page/component/issuable/common'
@@ -300,6 +305,18 @@ module QA
autoload :Config, 'qa/specs/config'
autoload :Runner, 'qa/specs/runner'
end
+
+ ##
+ # Classes that describe the structure of vendor/third party application pages
+ #
+ module Vendor
+ module SAMLIdp
+ module Page
+ autoload :Base, 'qa/vendor/saml_idp/page/base'
+ autoload :Login, 'qa/vendor/saml_idp/page/login'
+ end
+ end
+ end
end
QA::Runtime::Release.extend_autoloads!
diff --git a/qa/qa/factory/resource/deploy_token.rb b/qa/qa/factory/resource/deploy_token.rb
new file mode 100644
index 00000000000..159f79ac50b
--- /dev/null
+++ b/qa/qa/factory/resource/deploy_token.rb
@@ -0,0 +1,48 @@
+module QA
+ module Factory
+ module Resource
+ class DeployToken < Factory::Base
+ attr_accessor :name, :expires_at
+
+ product :username do |resource|
+ Page::Project::Settings::Repository.act do
+ expand_deploy_tokens do |token|
+ token.token_username
+ end
+ end
+ end
+
+ product :password do |password|
+ Page::Project::Settings::Repository.act do
+ expand_deploy_tokens do |token|
+ token.token_password
+ end
+ end
+ end
+
+ dependency Factory::Resource::Project, as: :project do |project|
+ project.name = 'project-to-deploy'
+ project.description = 'project for adding deploy token test'
+ end
+
+ def fabricate!
+ project.visit!
+
+ Page::Project::Menu.act do
+ click_repository_settings
+ end
+
+ Page::Project::Settings::Repository.perform do |setting|
+ setting.expand_deploy_tokens do |page|
+ page.fill_token_name(name)
+ page.fill_token_expires_at(expires_at)
+ page.fill_scopes(read_repository: true, read_registry: false)
+
+ page.add_token
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/README.md b/qa/qa/page/README.md
index dfad460a9a5..4d58f1a43b7 100644
--- a/qa/qa/page/README.md
+++ b/qa/qa/page/README.md
@@ -70,15 +70,15 @@ module Page
module Main
class Login < Page::Base
view 'app/views/devise/passwords/edit.html.haml' do
- element :password_field, 'password_field :password'
- element :password_confirmation, 'password_field :password_confirmation'
- element :change_password_button, 'submit "Change your password"'
+ element :password_field
+ element :password_confirmation
+ element :change_password_button
end
view 'app/views/devise/sessions/_new_base.html.haml' do
- element :login_field, 'text_field :login'
- element :password_field, 'password_field :password'
- element :sign_in_button, 'submit "Sign in"'
+ element :login_field
+ element :password_field
+ element :sign_in_button
end
# ...
@@ -87,23 +87,31 @@ end
```
The `view` DSL method declares the filename of the view where an
-`element` is implmented.
+`element` is implemented.
-The `element` DSL method in turn declares an element and defines a value
-to match to the actual view code. It is possible to use `element` with value,
-with a String value or with a Regexp.
+The `element` DSL method in turn declares an element for which a corresponding
+`qa-element-name-dasherized` CSS class need to be added to the view file.
+
+You can also define a value (String or Regexp) to match to the actual view
+code but **this is deprecated** in favor of the above method for two reasons:
+
+- Consistency: there is only one way to define an element
+- Separation of concerns: QA uses dedicated CSS classes instead of reusing code
+ or classes used by other components (e.g. `js-*` classes etc.)
```ruby
view 'app/views/my/view.html.haml' do
+ # Implicitly require `.qa-logout-button` CSS class to be present in the view
+ element :logout_button
+
+ ## This is deprecated and forbidden by the `QA/ElementWithPattern` RuboCop cop.
# Require `f.submit "Sign in"` to be present in `my/view.html.haml
- element :my_button, 'f.submit "Sign in"'
+ element :my_button, 'f.submit "Sign in"' # rubocop:disable QA/ElementWithPattern
+ ## This is deprecated and forbidden by the `QA/ElementWithPattern` RuboCop cop.
# Match every line in `my/view.html.haml` against
# `/link_to .* "My Profile"/` regexp.
- element :profile_link, /link_to .* "My Profile"/
-
- # Implicitly require `.qa-logout-button` CSS class to be present in the view
- element :logout_button
+ element :profile_link, /link_to .* "My Profile"/ # rubocop:disable QA/ElementWithPattern
end
```
diff --git a/qa/qa/page/component/clone_panel.rb b/qa/qa/page/component/clone_panel.rb
index 8e8ff4e3bb0..94e761b0e0c 100644
--- a/qa/qa/page/component/clone_panel.rb
+++ b/qa/qa/page/component/clone_panel.rb
@@ -7,8 +7,8 @@ module QA
def self.included(base)
base.view 'app/views/shared/_clone_panel.html.haml' do
element :clone_dropdown
- element :clone_options_dropdown, '.clone-options-dropdown'
- element :project_repository_location, 'text_field_tag :project_clone'
+ element :clone_options_dropdown, '.clone-options-dropdown' # rubocop:disable QA/ElementWithPattern
+ element :project_repository_location, 'text_field_tag :project_clone' # rubocop:disable QA/ElementWithPattern
end
end
diff --git a/qa/qa/page/component/users_select.rb b/qa/qa/page/component/users_select.rb
new file mode 100644
index 00000000000..f88d6450a33
--- /dev/null
+++ b/qa/qa/page/component/users_select.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Component
+ module UsersSelect
+ def select_user(element, username)
+ find("#{element_selector_css(element)} input").set(username)
+ find('.ajax-users-dropdown .user-username', text: "@#{username}").click
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/dashboard/groups.rb b/qa/qa/page/dashboard/groups.rb
index c6ef932e33f..7a07515de62 100644
--- a/qa/qa/page/dashboard/groups.rb
+++ b/qa/qa/page/dashboard/groups.rb
@@ -7,12 +7,12 @@ module QA
include Page::Component::GroupsFilter
view 'app/views/shared/groups/_search_form.html.haml' do
- element :groups_filter, 'search_field_tag :filter'
- element :groups_filter_placeholder, 'Search by name'
+ element :groups_filter, 'search_field_tag :filter' # rubocop:disable QA/ElementWithPattern
+ element :groups_filter_placeholder, 'Search by name' # rubocop:disable QA/ElementWithPattern
end
view 'app/views/dashboard/_groups_head.html.haml' do
- element :new_group_button, 'link_to _("New group")'
+ element :new_group_button, 'link_to _("New group")' # rubocop:disable QA/ElementWithPattern
end
def has_group?(name)
diff --git a/qa/qa/page/dashboard/projects.rb b/qa/qa/page/dashboard/projects.rb
index 5b2827c089c..0f434577b3b 100644
--- a/qa/qa/page/dashboard/projects.rb
+++ b/qa/qa/page/dashboard/projects.rb
@@ -5,7 +5,7 @@ module QA
view 'app/views/dashboard/projects/index.html.haml'
view 'app/views/shared/projects/_search_form.html.haml' do
- element :form_filter_by_name, /form_tag.+id: 'project-filter-form'/
+ element :form_filter_by_name, /form_tag.+id: 'project-filter-form'/ # rubocop:disable QA/ElementWithPattern
end
def go_to_project(name)
diff --git a/qa/qa/page/file/form.rb b/qa/qa/page/file/form.rb
index 3752f5066c9..a1534231691 100644
--- a/qa/qa/page/file/form.rb
+++ b/qa/qa/page/file/form.rb
@@ -6,12 +6,12 @@ module QA
include Page::Component::DropdownFilter
view 'app/views/projects/blob/_editor.html.haml' do
- element :file_name, "text_field_tag 'file_name'"
- element :editor, '#editor'
+ element :file_name, "text_field_tag 'file_name'" # rubocop:disable QA/ElementWithPattern
+ element :editor, '#editor' # rubocop:disable QA/ElementWithPattern
end
view 'app/views/projects/_commit_button.html.haml' do
- element :commit_changes, "button_tag 'Commit changes'"
+ element :commit_changes, "button_tag 'Commit changes'" # rubocop:disable QA/ElementWithPattern
end
view 'app/views/projects/blob/_template_selectors.html.haml' do
diff --git a/qa/qa/page/file/shared/commit_message.rb b/qa/qa/page/file/shared/commit_message.rb
index 5af1a55e2ef..aa1bb081cd3 100644
--- a/qa/qa/page/file/shared/commit_message.rb
+++ b/qa/qa/page/file/shared/commit_message.rb
@@ -5,7 +5,7 @@ module QA
module CommitMessage
def self.included(base)
base.view 'app/views/shared/_commit_message_container.html.haml' do
- element :commit_message, "text_area_tag 'commit_message'"
+ element :commit_message, "text_area_tag 'commit_message'" # rubocop:disable QA/ElementWithPattern
end
end
diff --git a/qa/qa/page/file/show.rb b/qa/qa/page/file/show.rb
index 99f5924b67f..abd8ebb089f 100644
--- a/qa/qa/page/file/show.rb
+++ b/qa/qa/page/file/show.rb
@@ -5,12 +5,12 @@ module QA
include Shared::CommitMessage
view 'app/helpers/blob_helper.rb' do
- element :edit_button, "_('Edit')"
- element :delete_button, /label:\s+"Delete"/
+ element :edit_button, "_('Edit')" # rubocop:disable QA/ElementWithPattern
+ element :delete_button, /label:\s+"Delete"/ # rubocop:disable QA/ElementWithPattern
end
view 'app/views/projects/blob/_remove.html.haml' do
- element :delete_file_button, "button_tag 'Delete file'"
+ element :delete_file_button, "button_tag 'Delete file'" # rubocop:disable QA/ElementWithPattern
end
def click_edit
diff --git a/qa/qa/page/group/new.rb b/qa/qa/page/group/new.rb
index 48b71a7c883..39584daf334 100644
--- a/qa/qa/page/group/new.rb
+++ b/qa/qa/page/group/new.rb
@@ -3,14 +3,14 @@ module QA
module Group
class New < Page::Base
view 'app/views/shared/_group_form.html.haml' do
- element :group_path_field, 'text_field :path'
- element :group_name_field, 'text_field :name'
- element :group_description_field, 'text_area :description'
+ element :group_path_field, 'text_field :path' # rubocop:disable QA/ElementWithPattern
+ element :group_name_field, 'text_field :name' # rubocop:disable QA/ElementWithPattern
+ element :group_description_field, 'text_area :description' # rubocop:disable QA/ElementWithPattern
end
view 'app/views/groups/new.html.haml' do
- element :create_group_button, "submit 'Create group'"
- element :visibility_radios, 'visibility_level:'
+ element :create_group_button, "submit 'Create group'" # rubocop:disable QA/ElementWithPattern
+ element :visibility_radios, 'visibility_level:' # rubocop:disable QA/ElementWithPattern
end
def set_path(path)
diff --git a/qa/qa/page/group/show.rb b/qa/qa/page/group/show.rb
index 58a9e861971..0f0ab81a4ef 100644
--- a/qa/qa/page/group/show.rb
+++ b/qa/qa/page/group/show.rb
@@ -15,7 +15,7 @@ module QA
end
view 'app/assets/javascripts/groups/constants.js' do
- element :no_result_text, 'No groups or projects matched your search'
+ element :no_result_text, 'No groups or projects matched your search' # rubocop:disable QA/ElementWithPattern
end
def go_to_subgroup(name)
diff --git a/qa/qa/page/issuable/sidebar.rb b/qa/qa/page/issuable/sidebar.rb
index f207264e24f..d3751b712c9 100644
--- a/qa/qa/page/issuable/sidebar.rb
+++ b/qa/qa/page/issuable/sidebar.rb
@@ -3,8 +3,8 @@ module QA
module Issuable
class Sidebar < Page::Base
view 'app/views/shared/issuable/_sidebar.html.haml' do
- element :labels_block, ".issuable-show-labels"
- element :milestones_block, '.block.milestone'
+ element :labels_block, ".issuable-show-labels" # rubocop:disable QA/ElementWithPattern
+ element :milestones_block, '.block.milestone' # rubocop:disable QA/ElementWithPattern
end
def has_label?(label)
diff --git a/qa/qa/page/layout/banner.rb b/qa/qa/page/layout/banner.rb
index e7654bdafc9..2223f2adec8 100644
--- a/qa/qa/page/layout/banner.rb
+++ b/qa/qa/page/layout/banner.rb
@@ -3,7 +3,7 @@ module QA
module Layout
class Banner < Page::Base
view 'app/views/layouts/header/_read_only_banner.html.haml' do
- element :flash_notice, ".flash-notice"
+ element :flash_notice, ".flash-notice" # rubocop:disable QA/ElementWithPattern
end
def has_notice?(message)
diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb
index eab7a85ff04..94b9486b0d5 100644
--- a/qa/qa/page/main/login.rb
+++ b/qa/qa/page/main/login.rb
@@ -31,6 +31,10 @@ module QA
element :register_tab
end
+ view 'app/views/devise/shared/_omniauth_box.html.haml' do
+ element :saml_login_button
+ end
+
def initialize
# The login page is usually the entry point for all the scenarios so
# we need to wait for the instance to start. That said, in some cases
@@ -130,6 +134,11 @@ module QA
click_element :sign_in_button
end
+ def sign_in_with_saml
+ set_initial_password_if_present
+ click_element :saml_login_button
+ end
+
def sign_in_using_gitlab_credentials(user)
switch_to_sign_in_tab if has_sign_in_tab?
switch_to_standard_tab if has_standard_tab?
diff --git a/qa/qa/page/main/menu.rb b/qa/qa/page/main/menu.rb
index a2ee696e1b3..fb45ebef1b6 100644
--- a/qa/qa/page/main/menu.rb
+++ b/qa/qa/page/main/menu.rb
@@ -5,14 +5,14 @@ module QA
module Main
class Menu < Page::Base
view 'app/views/layouts/header/_current_user_dropdown.html.haml' do
- element :user_sign_out_link, 'link_to _("Sign out")'
- element :settings_link, 'link_to s_("CurrentUser|Settings")'
+ element :user_sign_out_link, 'link_to _("Sign out")' # rubocop:disable QA/ElementWithPattern
+ element :settings_link, 'link_to s_("CurrentUser|Settings")' # rubocop:disable QA/ElementWithPattern
end
view 'app/views/layouts/header/_default.html.haml' do
element :navbar
element :user_avatar
- element :user_menu, '.dropdown-menu'
+ element :user_menu, '.dropdown-menu' # rubocop:disable QA/ElementWithPattern
end
view 'app/views/layouts/nav/_dashboard.html.haml' do
diff --git a/qa/qa/page/main/oauth.rb b/qa/qa/page/main/oauth.rb
index 618f114e058..bc44d274314 100644
--- a/qa/qa/page/main/oauth.rb
+++ b/qa/qa/page/main/oauth.rb
@@ -3,7 +3,7 @@ module QA
module Main
class OAuth < Page::Base
view 'app/views/doorkeeper/authorizations/new.html.haml' do
- element :authorization_button, 'submit_tag _("Authorize")'
+ element :authorization_button, 'submit_tag _("Authorize")' # rubocop:disable QA/ElementWithPattern
end
def needs_authorization?
diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb
index d9254d89541..b40e90ef4ad 100644
--- a/qa/qa/page/merge_request/show.rb
+++ b/qa/qa/page/merge_request/show.rb
@@ -4,19 +4,19 @@ module QA
class Show < Page::Base
view 'app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue' do
element :merge_button
- element :fast_forward_message, 'Fast-forward merge without a merge commit'
+ element :fast_forward_message, 'Fast-forward merge without a merge commit' # rubocop:disable QA/ElementWithPattern
element :merge_moment_dropdown
element :merge_when_pipeline_succeeds_option
element :merge_immediately_option
end
view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue' do
- element :merged_status, 'The changes were merged into'
+ element :merged_status, 'The changes were merged into' # rubocop:disable QA/ElementWithPattern
end
view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue' do
element :mr_rebase_button
- element :no_fast_forward_message, 'Fast-forward merge is not possible'
+ element :no_fast_forward_message, 'Fast-forward merge is not possible' # rubocop:disable QA/ElementWithPattern
end
view 'app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue' do
diff --git a/qa/qa/page/profile/menu.rb b/qa/qa/page/profile/menu.rb
index f8a7d64e016..2d503499e13 100644
--- a/qa/qa/page/profile/menu.rb
+++ b/qa/qa/page/profile/menu.rb
@@ -5,10 +5,10 @@ module QA
module Profile
class Menu < Page::Base
view 'app/views/layouts/nav/sidebar/_profile.html.haml' do
- element :access_token_link, 'link_to profile_personal_access_tokens_path'
- element :access_token_title, 'Access Tokens'
- element :top_level_items, '.sidebar-top-level-items'
- element :ssh_keys, 'SSH Keys'
+ element :access_token_link, 'link_to profile_personal_access_tokens_path' # rubocop:disable QA/ElementWithPattern
+ element :access_token_title, 'Access Tokens' # rubocop:disable QA/ElementWithPattern
+ element :top_level_items, '.sidebar-top-level-items' # rubocop:disable QA/ElementWithPattern
+ element :ssh_keys, 'SSH Keys' # rubocop:disable QA/ElementWithPattern
end
def click_access_tokens
diff --git a/qa/qa/page/profile/personal_access_tokens.rb b/qa/qa/page/profile/personal_access_tokens.rb
index f5ae47dadd0..2f0202951bb 100644
--- a/qa/qa/page/profile/personal_access_tokens.rb
+++ b/qa/qa/page/profile/personal_access_tokens.rb
@@ -3,13 +3,13 @@ module QA
module Profile
class PersonalAccessTokens < Page::Base
view 'app/views/shared/_personal_access_tokens_form.html.haml' do
- element :personal_access_token_name_field, 'text_field :name'
- element :create_token_button, 'submit "Create #{type} token"' # rubocop:disable Lint/InterpolationCheck
- element :scopes_api_radios, "label :scopes"
+ element :personal_access_token_name_field, 'text_field :name' # rubocop:disable QA/ElementWithPattern
+ element :create_token_button, 'submit "Create #{type} token"' # rubocop:disable QA/ElementWithPattern, Lint/InterpolationCheck
+ element :scopes_api_radios, "label :scopes" # rubocop:disable QA/ElementWithPattern
end
view 'app/views/profiles/personal_access_tokens/index.html.haml' do
- element :create_token_field, "text_field_tag 'created-personal-access-token'"
+ element :create_token_field, "text_field_tag 'created-personal-access-token'" # rubocop:disable QA/ElementWithPattern
end
def fill_token_name(name)
diff --git a/qa/qa/page/project/activity.rb b/qa/qa/page/project/activity.rb
index a0500b4d31a..56fbaa90790 100644
--- a/qa/qa/page/project/activity.rb
+++ b/qa/qa/page/project/activity.rb
@@ -3,7 +3,7 @@ module QA
module Project
class Activity < Page::Base
view 'app/views/shared/_event_filter.html.haml' do
- element :push_events, "event_filter_link EventFilter::PUSH, _('Push events')"
+ element :push_events, "event_filter_link EventFilter::PUSH, _('Push events')" # rubocop:disable QA/ElementWithPattern
end
def go_to_push_events
diff --git a/qa/qa/page/project/fork/new.rb b/qa/qa/page/project/fork/new.rb
index ed92df956bf..140c004b458 100644
--- a/qa/qa/page/project/fork/new.rb
+++ b/qa/qa/page/project/fork/new.rb
@@ -4,7 +4,7 @@ module QA
module Fork
class New < Page::Base
view 'app/views/projects/forks/_fork_button.html.haml' do
- element :namespace, 'link_to project_forks_path'
+ element :namespace, 'link_to project_forks_path' # rubocop:disable QA/ElementWithPattern
end
def choose_namespace(namespace = Runtime::Namespace.path)
diff --git a/qa/qa/page/project/import/github.rb b/qa/qa/page/project/import/github.rb
index 1a410a0f8a5..a3cde73d3f2 100644
--- a/qa/qa/page/project/import/github.rb
+++ b/qa/qa/page/project/import/github.rb
@@ -6,16 +6,16 @@ module QA
include Page::Component::Select2
view 'app/views/import/github/new.html.haml' do
- element :personal_access_token_field, 'text_field_tag :personal_access_token'
- element :list_repos_button, "submit_tag _('List your GitHub repositories')"
+ element :personal_access_token_field, 'text_field_tag :personal_access_token' # rubocop:disable QA/ElementWithPattern
+ element :list_repos_button, "submit_tag _('List your GitHub repositories')" # rubocop:disable QA/ElementWithPattern
end
view 'app/views/import/_githubish_status.html.haml' do
- element :project_import_row, 'data: { qa: { repo_path: repo.full_name } }'
+ element :project_import_row, 'data: { qa: { repo_path: repo.full_name } }' # rubocop:disable QA/ElementWithPattern
element :project_namespace_select
- element :project_namespace_field, 'select_tag :namespace_id'
- element :project_path_field, 'text_field_tag :path, sanitize_project_name(repo.name)'
- element :import_button, "_('Import')"
+ element :project_namespace_field, 'select_tag :namespace_id' # rubocop:disable QA/ElementWithPattern
+ element :project_path_field, 'text_field_tag :path, sanitize_project_name(repo.name)' # rubocop:disable QA/ElementWithPattern
+ element :import_button, "_('Import')" # rubocop:disable QA/ElementWithPattern
end
def add_personal_access_token(personal_access_token)
diff --git a/qa/qa/page/project/issue/index.rb b/qa/qa/page/project/issue/index.rb
index b5903f536a4..1035bf74a43 100644
--- a/qa/qa/page/project/issue/index.rb
+++ b/qa/qa/page/project/issue/index.rb
@@ -4,7 +4,7 @@ module QA
module Issue
class Index < Page::Base
view 'app/views/projects/issues/_issue.html.haml' do
- element :issue_link, 'link_to issue.title'
+ element :issue_link, 'link_to issue.title' # rubocop:disable QA/ElementWithPattern
end
def go_to_issue(title)
diff --git a/qa/qa/page/project/issue/new.rb b/qa/qa/page/project/issue/new.rb
index 7fc581da1ed..03b605ab24b 100644
--- a/qa/qa/page/project/issue/new.rb
+++ b/qa/qa/page/project/issue/new.rb
@@ -4,15 +4,15 @@ module QA
module Issue
class New < Page::Base
view 'app/views/shared/issuable/_form.html.haml' do
- element :submit_issue_button, 'form.submit "Submit'
+ element :submit_issue_button, 'form.submit "Submit' # rubocop:disable QA/ElementWithPattern
end
view 'app/views/shared/issuable/form/_title.html.haml' do
- element :issue_title_textbox, 'form.text_field :title'
+ element :issue_title_textbox, 'form.text_field :title' # rubocop:disable QA/ElementWithPattern
end
view 'app/views/shared/form_elements/_description.html.haml' do
- element :issue_description_textarea, "render 'projects/zen', f: form, attr: :description"
+ element :issue_description_textarea, "render 'projects/zen', f: form, attr: :description" # rubocop:disable QA/ElementWithPattern
end
def add_title(title)
diff --git a/qa/qa/page/project/issue/show.rb b/qa/qa/page/project/issue/show.rb
index 9a738f56202..1062f0b2dbb 100644
--- a/qa/qa/page/project/issue/show.rb
+++ b/qa/qa/page/project/issue/show.rb
@@ -8,17 +8,17 @@ module QA
include Page::Component::Issuable::Common
view 'app/views/projects/issues/show.html.haml' do
- element :issue_details, '.issue-details'
- element :title, '.title'
+ element :issue_details, '.issue-details' # rubocop:disable QA/ElementWithPattern
+ element :title, '.title' # rubocop:disable QA/ElementWithPattern
end
view 'app/views/shared/notes/_form.html.haml' do
- element :new_note_form, 'new-note'
- element :new_note_form, 'attr: :note'
+ element :new_note_form, 'new-note' # rubocop:disable QA/ElementWithPattern
+ element :new_note_form, 'attr: :note' # rubocop:disable QA/ElementWithPattern
end
view 'app/views/shared/notes/_comment_button.html.haml' do
- element :comment_button, '%strong Comment'
+ element :comment_button, '%strong Comment' # rubocop:disable QA/ElementWithPattern
end
def issue_title
diff --git a/qa/qa/page/project/job/show.rb b/qa/qa/page/project/job/show.rb
index 228ffd9d381..5baf6439cfc 100644
--- a/qa/qa/page/project/job/show.rb
+++ b/qa/qa/page/project/job/show.rb
@@ -5,12 +5,12 @@ module QA::Page
PASSED_STATUS = 'passed'.freeze
view 'app/views/shared/builds/_build_output.html.haml' do
- element :build_output, '.js-build-output'
- element :loading_animation, '.js-build-refresh'
+ element :build_output, '.js-build-output' # rubocop:disable QA/ElementWithPattern
+ element :loading_animation, '.js-build-refresh' # rubocop:disable QA/ElementWithPattern
end
view 'app/assets/javascripts/vue_shared/components/ci_badge_link.vue' do
- element :status_badge, 'ci-status'
+ element :status_badge, 'ci-status' # rubocop:disable QA/ElementWithPattern
end
def completed?
diff --git a/qa/qa/page/project/menu.rb b/qa/qa/page/project/menu.rb
index d9f01c50f19..b32d5ea772b 100644
--- a/qa/qa/page/project/menu.rb
+++ b/qa/qa/page/project/menu.rb
@@ -6,25 +6,26 @@ module QA
class Menu < Page::Base
view 'app/views/layouts/nav/sidebar/_project.html.haml' do
element :settings_item
- element :settings_link, 'link_to edit_project_path'
- element :repository_link, "title: _('Repository')"
+ element :settings_link, 'link_to edit_project_path' # rubocop:disable QA/ElementWithPattern
+ element :repository_link, "title: _('Repository')" # rubocop:disable QA/ElementWithPattern
element :link_pipelines
- element :pipelines_settings_link, "title: _('CI / CD')"
- element :operations_kubernetes_link, "title: _('Kubernetes')"
+ element :link_members_settings
+ element :pipelines_settings_link, "title: _('CI / CD')" # rubocop:disable QA/ElementWithPattern
+ element :operations_kubernetes_link, "title: _('Kubernetes')" # rubocop:disable QA/ElementWithPattern
element :operations_environments_link
- element :issues_link, /link_to.*shortcuts-issues/
- element :issues_link_text, "Issues"
- element :merge_requests_link, /link_to.*shortcuts-merge_requests/
- element :merge_requests_link_text, "Merge Requests"
- element :top_level_items, '.sidebar-top-level-items'
- element :operations_section, "class: 'shortcuts-operations'"
- element :activity_link, "title: _('Activity')"
- element :wiki_link_text, "Wiki"
+ element :issues_link, /link_to.*shortcuts-issues/ # rubocop:disable QA/ElementWithPattern
+ element :issues_link_text, "Issues" # rubocop:disable QA/ElementWithPattern
+ element :merge_requests_link, /link_to.*shortcuts-merge_requests/ # rubocop:disable QA/ElementWithPattern
+ element :merge_requests_link_text, "Merge Requests" # rubocop:disable QA/ElementWithPattern
+ element :top_level_items, '.sidebar-top-level-items' # rubocop:disable QA/ElementWithPattern
+ element :operations_section, "class: 'shortcuts-operations'" # rubocop:disable QA/ElementWithPattern
+ element :activity_link, "title: _('Activity')" # rubocop:disable QA/ElementWithPattern
+ element :wiki_link_text, "Wiki" # rubocop:disable QA/ElementWithPattern
element :milestones_link
end
view 'app/assets/javascripts/fly_out_nav.js' do
- element :fly_out, "classList.add('fly-out-list')"
+ element :fly_out, "classList.add('fly-out-list')" # rubocop:disable QA/ElementWithPattern
end
def click_repository_settings
@@ -51,6 +52,14 @@ module QA
end
end
+ def click_members_settings
+ hover_settings do
+ within_submenu do
+ click_element :link_members_settings
+ end
+ end
+ end
+
def click_operations_kubernetes
hover_operations do
within_submenu do
diff --git a/qa/qa/page/project/new.rb b/qa/qa/page/project/new.rb
index 0766c98da6f..6acc413b586 100644
--- a/qa/qa/page/project/new.rb
+++ b/qa/qa/page/project/new.rb
@@ -5,21 +5,21 @@ module QA
include Page::Component::Select2
view 'app/views/projects/new.html.haml' do
- element :import_project_tab, "Import project"
+ element :import_project_tab, "Import project" # rubocop:disable QA/ElementWithPattern
end
view 'app/views/projects/_new_project_fields.html.haml' do
element :project_namespace_select
- element :project_namespace_field, 'namespaces_options'
- element :project_name, 'text_field :name'
- element :project_path, 'text_field :path'
- element :project_description, 'text_area :description'
- element :project_create_button, "submit 'Create project'"
- element :visibility_radios, 'visibility_level:'
+ element :project_namespace_field, 'namespaces_options' # rubocop:disable QA/ElementWithPattern
+ element :project_name, 'text_field :name' # rubocop:disable QA/ElementWithPattern
+ element :project_path, 'text_field :path' # rubocop:disable QA/ElementWithPattern
+ element :project_description, 'text_area :description' # rubocop:disable QA/ElementWithPattern
+ element :project_create_button, "submit 'Create project'" # rubocop:disable QA/ElementWithPattern
+ element :visibility_radios, 'visibility_level:' # rubocop:disable QA/ElementWithPattern
end
view 'app/views/projects/_import_project_pane.html.haml' do
- element :import_github, "icon('github', text: 'GitHub')"
+ element :import_github, "icon('github', text: 'GitHub')" # rubocop:disable QA/ElementWithPattern
end
def choose_test_namespace
diff --git a/qa/qa/page/project/operations/kubernetes/add.rb b/qa/qa/page/project/operations/kubernetes/add.rb
index 11ebe10fb18..18c16ca6db7 100644
--- a/qa/qa/page/project/operations/kubernetes/add.rb
+++ b/qa/qa/page/project/operations/kubernetes/add.rb
@@ -5,7 +5,7 @@ module QA
module Kubernetes
class Add < Page::Base
view 'app/views/projects/clusters/new.html.haml' do
- element :add_existing_cluster_button, "Add existing cluster"
+ element :add_existing_cluster_button, "Add existing cluster" # rubocop:disable QA/ElementWithPattern
end
def add_existing_cluster
diff --git a/qa/qa/page/project/operations/kubernetes/add_existing.rb b/qa/qa/page/project/operations/kubernetes/add_existing.rb
index 38f8527b9b4..f8e026b4405 100644
--- a/qa/qa/page/project/operations/kubernetes/add_existing.rb
+++ b/qa/qa/page/project/operations/kubernetes/add_existing.rb
@@ -5,11 +5,11 @@ module QA
module Kubernetes
class AddExisting < Page::Base
view 'app/views/projects/clusters/user/_form.html.haml' do
- element :cluster_name, 'text_field :name'
- element :api_url, 'text_field :api_url'
- element :ca_certificate, 'text_area :ca_cert'
- element :token, 'text_field :token'
- element :add_cluster_button, "submit s_('ClusterIntegration|Add Kubernetes cluster')"
+ element :cluster_name, 'text_field :name' # rubocop:disable QA/ElementWithPattern
+ element :api_url, 'text_field :api_url' # rubocop:disable QA/ElementWithPattern
+ element :ca_certificate, 'text_area :ca_cert' # rubocop:disable QA/ElementWithPattern
+ element :token, 'text_field :token' # rubocop:disable QA/ElementWithPattern
+ element :add_cluster_button, "submit s_('ClusterIntegration|Add Kubernetes cluster')" # rubocop:disable QA/ElementWithPattern
element :rbac_checkbox
end
diff --git a/qa/qa/page/project/operations/kubernetes/index.rb b/qa/qa/page/project/operations/kubernetes/index.rb
index 7261b5645da..312b459ac89 100644
--- a/qa/qa/page/project/operations/kubernetes/index.rb
+++ b/qa/qa/page/project/operations/kubernetes/index.rb
@@ -5,7 +5,7 @@ module QA
module Kubernetes
class Index < Page::Base
view 'app/views/projects/clusters/_empty_state.html.haml' do
- element :add_kubernetes_cluster_button, "link_to s_('ClusterIntegration|Add Kubernetes cluster')"
+ element :add_kubernetes_cluster_button, "link_to s_('ClusterIntegration|Add Kubernetes cluster')" # rubocop:disable QA/ElementWithPattern
end
def add_kubernetes_cluster
diff --git a/qa/qa/page/project/operations/kubernetes/show.rb b/qa/qa/page/project/operations/kubernetes/show.rb
index e831edeb89e..9e8f9ba79d7 100644
--- a/qa/qa/page/project/operations/kubernetes/show.rb
+++ b/qa/qa/page/project/operations/kubernetes/show.rb
@@ -5,13 +5,13 @@ module QA
module Kubernetes
class Show < Page::Base
view 'app/assets/javascripts/clusters/components/application_row.vue' do
- element :application_row, 'js-cluster-application-row-${this.id}'
- element :install_button, "s__('ClusterIntegration|Install')"
- element :installed_button, "s__('ClusterIntegration|Installed')"
+ element :application_row, 'js-cluster-application-row-${this.id}' # rubocop:disable QA/ElementWithPattern
+ element :install_button, "s__('ClusterIntegration|Install')" # rubocop:disable QA/ElementWithPattern
+ element :installed_button, "s__('ClusterIntegration|Installed')" # rubocop:disable QA/ElementWithPattern
end
view 'app/assets/javascripts/clusters/components/applications.vue' do
- element :ingress_ip_address, 'id="ingress-ip-address"'
+ element :ingress_ip_address, 'id="ingress-ip-address"' # rubocop:disable QA/ElementWithPattern
end
def install!(application_name)
diff --git a/qa/qa/page/project/pipeline/index.rb b/qa/qa/page/project/pipeline/index.rb
index ce430a2a6ee..19d83ecc4f4 100644
--- a/qa/qa/page/project/pipeline/index.rb
+++ b/qa/qa/page/project/pipeline/index.rb
@@ -2,7 +2,7 @@ module QA::Page
module Project::Pipeline
class Index < QA::Page::Base
view 'app/assets/javascripts/pipelines/components/pipeline_url.vue' do
- element :pipeline_link, 'class="js-pipeline-url-link"'
+ element :pipeline_link, 'class="js-pipeline-url-link"' # rubocop:disable QA/ElementWithPattern
end
def go_to_latest_pipeline
diff --git a/qa/qa/page/project/pipeline/show.rb b/qa/qa/page/project/pipeline/show.rb
index babc0079f3f..06df1238738 100644
--- a/qa/qa/page/project/pipeline/show.rb
+++ b/qa/qa/page/project/pipeline/show.rb
@@ -2,20 +2,20 @@ module QA::Page
module Project::Pipeline
class Show < QA::Page::Base
view 'app/assets/javascripts/vue_shared/components/header_ci_component.vue' do
- element :pipeline_header, /header class.*ci-header-container.*/
+ element :pipeline_header, /header class.*ci-header-container.*/ # rubocop:disable QA/ElementWithPattern
end
view 'app/assets/javascripts/pipelines/components/graph/graph_component.vue' do
- element :pipeline_graph, /class.*pipeline-graph.*/
+ element :pipeline_graph, /class.*pipeline-graph.*/ # rubocop:disable QA/ElementWithPattern
end
view 'app/assets/javascripts/pipelines/components/graph/job_component.vue' do
- element :job_component, /class.*ci-job-component.*/
- element :job_link, /class.*js-pipeline-graph-job-link.*/
+ element :job_component, /class.*ci-job-component.*/ # rubocop:disable QA/ElementWithPattern
+ element :job_link, /class.*js-pipeline-graph-job-link.*/ # rubocop:disable QA/ElementWithPattern
end
view 'app/assets/javascripts/vue_shared/components/ci_icon.vue' do
- element :status_icon, 'ci-status-icon-${status}'
+ element :status_icon, 'ci-status-icon-${status}' # rubocop:disable QA/ElementWithPattern
end
def running?
diff --git a/qa/qa/page/project/settings/advanced.rb b/qa/qa/page/project/settings/advanced.rb
index d7b2b66b587..578f097e2dc 100644
--- a/qa/qa/page/project/settings/advanced.rb
+++ b/qa/qa/page/project/settings/advanced.rb
@@ -4,9 +4,9 @@ module QA
module Settings
class Advanced < Page::Base
view 'app/views/projects/edit.html.haml' do
- element :project_path_field, 'text_field :path'
- element :project_name_field, 'text_field :name'
- element :rename_project_button, "submit 'Rename project'"
+ element :project_path_field, 'text_field :path' # rubocop:disable QA/ElementWithPattern
+ element :project_name_field, 'text_field :name' # rubocop:disable QA/ElementWithPattern
+ element :rename_project_button, "submit 'Rename project'" # rubocop:disable QA/ElementWithPattern
end
def rename_to(path)
diff --git a/qa/qa/page/project/settings/ci_cd.rb b/qa/qa/page/project/settings/ci_cd.rb
index 752d3d93407..cc5fc370a5a 100644
--- a/qa/qa/page/project/settings/ci_cd.rb
+++ b/qa/qa/page/project/settings/ci_cd.rb
@@ -12,11 +12,11 @@ module QA # rubocop:disable Naming/FileName
end
view 'app/views/projects/settings/ci_cd/_autodevops_form.html.haml' do
- element :enable_auto_devops_field, 'check_box :enabled'
- element :domain_field, 'text_field :domain'
- element :enable_auto_devops_button, "%strong= s_('CICD|Default to Auto DevOps pipeline')"
- element :domain_input, "%strong= _('Domain')"
- element :save_changes_button, "submit _('Save changes')"
+ element :enable_auto_devops_field, 'check_box :enabled' # rubocop:disable QA/ElementWithPattern
+ element :domain_field, 'text_field :domain' # rubocop:disable QA/ElementWithPattern
+ element :enable_auto_devops_button, "%strong= s_('CICD|Default to Auto DevOps pipeline')" # rubocop:disable QA/ElementWithPattern
+ element :domain_input, "%strong= _('Domain')" # rubocop:disable QA/ElementWithPattern
+ element :save_changes_button, "submit _('Save changes')" # rubocop:disable QA/ElementWithPattern
end
def expand_runners_settings(&block)
diff --git a/qa/qa/page/project/settings/common.rb b/qa/qa/page/project/settings/common.rb
index 874fb381554..f3b217677f2 100644
--- a/qa/qa/page/project/settings/common.rb
+++ b/qa/qa/page/project/settings/common.rb
@@ -8,7 +8,7 @@ module QA
def self.included(base)
base.class_eval do
view 'app/views/projects/edit.html.haml' do
- element :advanced_settings_expand, "= expanded ? 'Collapse' : 'Expand'"
+ element :advanced_settings_expand, "= expanded ? 'Collapse' : 'Expand'" # rubocop:disable QA/ElementWithPattern
end
end
end
diff --git a/qa/qa/page/project/settings/deploy_keys.rb b/qa/qa/page/project/settings/deploy_keys.rb
index 90a0e7092bd..3c8c0cbdf7c 100644
--- a/qa/qa/page/project/settings/deploy_keys.rb
+++ b/qa/qa/page/project/settings/deploy_keys.rb
@@ -4,18 +4,18 @@ module QA
module Settings
class DeployKeys < Page::Base
view 'app/views/projects/deploy_keys/_form.html.haml' do
- element :deploy_key_title, 'text_field :title'
- element :deploy_key_key, 'text_area :key'
+ element :deploy_key_title, 'text_field :title' # rubocop:disable QA/ElementWithPattern
+ element :deploy_key_key, 'text_area :key' # rubocop:disable QA/ElementWithPattern
end
view 'app/assets/javascripts/deploy_keys/components/app.vue' do
- element :deploy_keys_section, /class=".*deploy\-keys.*"/
- element :project_deploy_keys, 'class="qa-project-deploy-keys"'
+ element :deploy_keys_section, /class=".*deploy\-keys.*"/ # rubocop:disable QA/ElementWithPattern
+ element :project_deploy_keys, 'class="qa-project-deploy-keys"' # rubocop:disable QA/ElementWithPattern
end
view 'app/assets/javascripts/deploy_keys/components/key.vue' do
- element :key_title, /class=".*qa-key-title.*"/
- element :key_fingerprint, /class=".*qa-key-fingerprint.*"/
+ element :key_title, /class=".*qa-key-title.*"/ # rubocop:disable QA/ElementWithPattern
+ element :key_fingerprint, /class=".*qa-key-fingerprint.*"/ # rubocop:disable QA/ElementWithPattern
end
def fill_key_title(title)
diff --git a/qa/qa/page/project/settings/deploy_tokens.rb b/qa/qa/page/project/settings/deploy_tokens.rb
new file mode 100644
index 00000000000..2d42372cbc5
--- /dev/null
+++ b/qa/qa/page/project/settings/deploy_tokens.rb
@@ -0,0 +1,64 @@
+module QA
+ module Page
+ module Project
+ module Settings
+ class DeployTokens < Page::Base
+ view 'app/views/projects/deploy_tokens/_form.html.haml' do
+ element :deploy_token_name
+ element :deploy_token_expires_at
+ element :deploy_token_read_repository
+ element :deploy_token_read_registry
+ element :create_deploy_token
+ end
+
+ view 'app/views/projects/deploy_tokens/_new_deploy_token.html.haml' do
+ element :created_deploy_token_section
+ element :deploy_token_user
+ element :deploy_token
+ end
+
+ def fill_token_name(name)
+ fill_element :deploy_token_name, name
+ end
+
+ def fill_token_expires_at(expires_at)
+ fill_element :deploy_token_expires_at, expires_at.to_s + "\n"
+ end
+
+ def fill_scopes(read_repository:, read_registry:)
+ check_element :deploy_token_read_repository if read_repository
+ check_element :deploy_token_read_registry if read_registry
+ end
+
+ def add_token
+ click_element :create_deploy_token
+ end
+
+ def token_username
+ within_new_project_deploy_token do
+ find_element(:deploy_token_user).value
+ end
+ end
+
+ def token_password
+ within_new_project_deploy_token do
+ find_element(:deploy_token).value
+ end
+ end
+
+ private
+
+ def within_new_project_deploy_token
+ wait(reload: false) do
+ has_css?(element_selector_css(:created_deploy_token_section))
+ end
+
+ within_element(:created_deploy_token_section) do
+ yield
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/settings/members.rb b/qa/qa/page/project/settings/members.rb
new file mode 100644
index 00000000000..7fed93ca83f
--- /dev/null
+++ b/qa/qa/page/project/settings/members.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module Settings
+ class Members < Page::Base
+ include Page::Component::UsersSelect
+
+ view 'app/views/projects/project_members/_new_project_member.html.haml' do
+ element :member_select_input
+ element :add_member_button
+ end
+
+ view 'app/views/projects/project_members/_team.html.haml' do
+ element :members_list
+ end
+
+ def add_member(username)
+ select_user :member_select_input, username
+ click_element :add_member_button
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/settings/repository.rb b/qa/qa/page/project/settings/repository.rb
index 1ed5f455a85..53ebe28970b 100644
--- a/qa/qa/page/project/settings/repository.rb
+++ b/qa/qa/page/project/settings/repository.rb
@@ -24,6 +24,12 @@ module QA
ProtectedBranches.perform(&block)
end
end
+
+ def expand_deploy_tokens(&block)
+ expand_section(:deploy_tokens_settings) do
+ DeployTokens.perform(&block)
+ end
+ end
end
end
end
diff --git a/qa/qa/page/project/settings/runners.rb b/qa/qa/page/project/settings/runners.rb
index b41668c94cd..ac930f5385a 100644
--- a/qa/qa/page/project/settings/runners.rb
+++ b/qa/qa/page/project/settings/runners.rb
@@ -4,8 +4,8 @@ module QA
module Settings
class Runners < Page::Base
view 'app/views/ci/runner/_how_to_setup_runner.html.haml' do
- element :registration_token, '%code#registration_token'
- element :coordinator_address, '%code#coordinator_address'
+ element :registration_token, '%code#registration_token' # rubocop:disable QA/ElementWithPattern
+ element :coordinator_address, '%code#coordinator_address' # rubocop:disable QA/ElementWithPattern
end
##
@@ -13,7 +13,7 @@ module QA
#
view 'app/helpers/runners_helper.rb' do
# rubocop:disable Lint/InterpolationCheck
- element :runner_status, 'runner-status-#{status}'
+ element :runner_status, 'runner-status-#{status}' # rubocop:disable QA/ElementWithPattern
# rubocop:enable Lint/InterpolationCheck
end
diff --git a/qa/qa/page/project/settings/secret_variables.rb b/qa/qa/page/project/settings/secret_variables.rb
index 937ae6797c8..6a87ef472e4 100644
--- a/qa/qa/page/project/settings/secret_variables.rb
+++ b/qa/qa/page/project/settings/secret_variables.rb
@@ -6,14 +6,14 @@ module QA
include Common
view 'app/views/ci/variables/_variable_row.html.haml' do
- element :variable_row, '.ci-variable-row-body'
- element :variable_key, '.qa-ci-variable-input-key'
- element :variable_value, '.qa-ci-variable-input-value'
+ element :variable_row, '.ci-variable-row-body' # rubocop:disable QA/ElementWithPattern
+ element :variable_key, '.qa-ci-variable-input-key' # rubocop:disable QA/ElementWithPattern
+ element :variable_value, '.qa-ci-variable-input-value' # rubocop:disable QA/ElementWithPattern
end
view 'app/views/ci/variables/_index.html.haml' do
- element :save_variables, '.js-secret-variables-save-button'
- element :reveal_values, '.js-secret-value-reveal-button'
+ element :save_variables, '.js-secret-variables-save-button' # rubocop:disable QA/ElementWithPattern
+ element :reveal_values, '.js-secret-value-reveal-button' # rubocop:disable QA/ElementWithPattern
end
def fill_variable(key, value)
diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb
index 2e7be1deb27..fcc4bb79c10 100644
--- a/qa/qa/page/project/show.rb
+++ b/qa/qa/page/project/show.rb
@@ -16,7 +16,7 @@ module QA
view 'app/views/layouts/header/_new_dropdown.haml' do
element :new_menu_toggle
- element :new_issue_link, "link_to _('New issue'), new_project_issue_path(@project)"
+ element :new_issue_link, "link_to _('New issue'), new_project_issue_path(@project)" # rubocop:disable QA/ElementWithPattern
end
view 'app/views/shared/_ref_switcher.html.haml' do
@@ -25,12 +25,12 @@ module QA
end
view 'app/views/projects/buttons/_fork.html.haml' do
- element :fork_label, "%span= s_('ProjectOverview|Fork')"
- element :fork_link, "link_to new_project_fork_path(@project)"
+ element :fork_label, "%span= s_('ProjectOverview|Fork')" # rubocop:disable QA/ElementWithPattern
+ element :fork_link, "link_to new_project_fork_path(@project)" # rubocop:disable QA/ElementWithPattern
end
view 'app/views/projects/_files.html.haml' do
- element :tree_holder, '.tree-holder'
+ element :tree_holder, '.tree-holder' # rubocop:disable QA/ElementWithPattern
end
view 'app/views/projects/buttons/_dropdown.html.haml' do
diff --git a/qa/qa/page/project/wiki/edit.rb b/qa/qa/page/project/wiki/edit.rb
index 6fa45569cc0..8d0eafa1818 100644
--- a/qa/qa/page/project/wiki/edit.rb
+++ b/qa/qa/page/project/wiki/edit.rb
@@ -4,9 +4,9 @@ module QA
module Wiki
class Edit < Page::Base
view 'app/views/projects/wikis/_main_links.html.haml' do
- element :new_page_link, 'New page'
- element :page_history_link, 'Page history'
- element :edit_page_link, 'Edit'
+ element :new_page_link, 'New page' # rubocop:disable QA/ElementWithPattern
+ element :page_history_link, 'Page history' # rubocop:disable QA/ElementWithPattern
+ element :edit_page_link, 'Edit' # rubocop:disable QA/ElementWithPattern
end
def go_to_new_page
diff --git a/qa/qa/page/project/wiki/new.rb b/qa/qa/page/project/wiki/new.rb
index 415b3835538..2498af8600c 100644
--- a/qa/qa/page/project/wiki/new.rb
+++ b/qa/qa/page/project/wiki/new.rb
@@ -4,15 +4,15 @@ module QA
module Wiki
class New < Page::Base
view 'app/views/projects/wikis/_form.html.haml' do
- element :wiki_title_textbox, 'text_field :title'
- element :wiki_content_textarea, "render 'projects/zen', f: f, attr: :content"
- element :wiki_message_textbox, 'text_field :message'
- element :save_changes_button, 'submit _("Save changes")'
- element :create_page_button, 'submit s_("Wiki|Create page")'
+ element :wiki_title_textbox, 'text_field :title' # rubocop:disable QA/ElementWithPattern
+ element :wiki_content_textarea, "render 'projects/zen', f: f, attr: :content" # rubocop:disable QA/ElementWithPattern
+ element :wiki_message_textbox, 'text_field :message' # rubocop:disable QA/ElementWithPattern
+ element :save_changes_button, 'submit _("Save changes")' # rubocop:disable QA/ElementWithPattern
+ element :create_page_button, 'submit s_("Wiki|Create page")' # rubocop:disable QA/ElementWithPattern
end
view 'app/views/shared/empty_states/_wikis.html.haml' do
- element :create_link, 'Create your first page'
+ element :create_link, 'Create your first page' # rubocop:disable QA/ElementWithPattern
end
def go_to_create_first_page
diff --git a/qa/qa/page/project/wiki/show.rb b/qa/qa/page/project/wiki/show.rb
index c47a715687f..a7c4455d080 100644
--- a/qa/qa/page/project/wiki/show.rb
+++ b/qa/qa/page/project/wiki/show.rb
@@ -8,7 +8,7 @@ module QA
include Page::Component::ClonePanel
view 'app/views/projects/wikis/pages.html.haml' do
- element :clone_repository_link, 'Clone repository'
+ element :clone_repository_link, 'Clone repository' # rubocop:disable QA/ElementWithPattern
end
def go_to_clone_repository
diff --git a/qa/qa/runtime/browser.rb b/qa/qa/runtime/browser.rb
index 4c64270ce92..9aaf57e8d83 100644
--- a/qa/qa/runtime/browser.rb
+++ b/qa/qa/runtime/browser.rb
@@ -51,6 +51,10 @@ module QA
}
)
+ if QA::Runtime::Env.accept_insecure_certs?
+ capabilities['acceptInsecureCerts'] = true
+ end
+
options = Selenium::WebDriver::Chrome::Options.new
options.add_argument("window-size=1240,1680")
diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index 5bebb5ccec0..4a2109799fa 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -8,6 +8,10 @@ module QA
enabled?(ENV['CHROME_HEADLESS'])
end
+ def accept_insecure_certs?
+ enabled?(ENV['ACCEPT_INSECURE_CERTS'])
+ end
+
def running_in_ci?
ENV['CI'] || ENV['CI_SERVER']
end
diff --git a/qa/qa/scenario/test/integration/instance_saml.rb b/qa/qa/scenario/test/integration/instance_saml.rb
new file mode 100644
index 00000000000..0697d0c2a0e
--- /dev/null
+++ b/qa/qa/scenario/test/integration/instance_saml.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module QA
+ module Scenario
+ module Test
+ module Integration
+ class InstanceSAML < Test::Instance::All
+ tags :instance_saml
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb
new file mode 100644
index 00000000000..8d5055aab45
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module QA
+ context :manage, :orchestrated, :instance_saml do
+ describe 'Instance wide SAML SSO' do
+ it 'User logs in to gitlab with SAML SSO' do
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+
+ Page::Main::Login.act { sign_in_with_saml }
+
+ Vendor::SAMLIdp::Page::Login.act { login }
+
+ expect(page).to have_content('Welcome to GitLab')
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb
new file mode 100644
index 00000000000..b276c7ee579
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module QA
+ context :manage do
+ describe 'Add project member' do
+ it 'user adds project member' do
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+
+ user = Factory::Resource::User.fabricate!
+
+ Page::Main::Menu.perform { |main| main.sign_out }
+ Page::Main::Login.act { sign_in_using_credentials }
+
+ Factory::Resource::Project.fabricate! do |resource|
+ resource.name = 'add-member-project'
+ end
+
+ Page::Project::Menu.act { click_members_settings }
+ Page::Project::Settings::Members.perform do |page|
+ page.add_member(user.username)
+ end
+
+ expect(page).to have_content("#{user.name} @#{user.username} Given access")
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb
new file mode 100644
index 00000000000..e521597e07f
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module QA
+ context :release do
+ describe 'Deploy token creation' do
+ it 'user adds a deploy token' do
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.act { sign_in_using_credentials }
+
+ deploy_token_name = 'deploy token name'
+ deploy_token_expires_at = Date.today + 7 # 1 Week from now
+
+ deploy_token = Factory::Resource::DeployToken.fabricate! do |resource|
+ resource.name = deploy_token_name
+ resource.expires_at = deploy_token_expires_at
+ end
+
+ expect(deploy_token.username.length).to be > 0
+ expect(deploy_token.password.length).to be > 0
+ end
+ end
+ end
+end
diff --git a/qa/qa/vendor/saml_idp/page/base.rb b/qa/qa/vendor/saml_idp/page/base.rb
new file mode 100644
index 00000000000..286cb0a8cd8
--- /dev/null
+++ b/qa/qa/vendor/saml_idp/page/base.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module QA
+ module Vendor
+ module SAMLIdp
+ module Page
+ class Base
+ include Capybara::DSL
+ include Scenario::Actable
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/vendor/saml_idp/page/login.rb b/qa/qa/vendor/saml_idp/page/login.rb
new file mode 100644
index 00000000000..9c1f9904a7a
--- /dev/null
+++ b/qa/qa/vendor/saml_idp/page/login.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'capybara/dsl'
+
+module QA
+ module Vendor
+ module SAMLIdp
+ module Page
+ class Login < Page::Base
+ def login
+ fill_in 'username', with: 'user1'
+ fill_in 'password', with: 'user1pass'
+ click_on 'Login'
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/spec/page/base_spec.rb b/qa/spec/page/base_spec.rb
index 52daa9697ee..076a8087db5 100644
--- a/qa/spec/page/base_spec.rb
+++ b/qa/spec/page/base_spec.rb
@@ -9,12 +9,12 @@ describe QA::Page::Base do
subject do
Class.new(described_class) do
view 'path/to/some/view.html.haml' do
- element :something, 'string pattern'
- element :something_else, /regexp pattern/
+ element :something, 'string pattern' # rubocop:disable QA/ElementWithPattern
+ element :something_else, /regexp pattern/ # rubocop:disable QA/ElementWithPattern
end
view 'path/to/some/_partial.html.haml' do
- element :another_element, 'string pattern'
+ element :another_element, 'string pattern' # rubocop:disable QA/ElementWithPattern
end
end
end
diff --git a/qa/spec/page/view_spec.rb b/qa/spec/page/view_spec.rb
index 34d2ff11447..d7b3ccd316d 100644
--- a/qa/spec/page/view_spec.rb
+++ b/qa/spec/page/view_spec.rb
@@ -8,8 +8,8 @@ describe QA::Page::View do
describe '.evaluate' do
it 'evaluates a block and returns a DSL object' do
results = described_class.evaluate do
- element :something, 'my pattern'
- element :something_else, /another pattern/
+ element :something
+ element :something_else
end
expect(results.elements.size).to eq 2
diff --git a/qa/spec/scenario/test/integration/instance_saml_spec.rb b/qa/spec/scenario/test/integration/instance_saml_spec.rb
new file mode 100644
index 00000000000..cb8a6a630cc
--- /dev/null
+++ b/qa/spec/scenario/test/integration/instance_saml_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+describe QA::Scenario::Test::Integration::InstanceSAML do
+ context '#perform' do
+ it_behaves_like 'a QA scenario class' do
+ let(:tags) { [:instance_saml] }
+ end
+ end
+end
diff --git a/rubocop/cop/qa/element_with_pattern.rb b/rubocop/cop/qa/element_with_pattern.rb
new file mode 100644
index 00000000000..9d80946f1ba
--- /dev/null
+++ b/rubocop/cop/qa/element_with_pattern.rb
@@ -0,0 +1,39 @@
+require_relative '../../qa_helpers'
+
+module RuboCop
+ module Cop
+ module QA
+ # This cop checks for the usage of factories in migration specs
+ #
+ # @example
+ #
+ # # bad
+ # let(:user) { create(:user) }
+ #
+ # # good
+ # let(:users) { table(:users) }
+ # let(:user) { users.create!(name: 'User 1', username: 'user1') }
+ class ElementWithPattern < RuboCop::Cop::Cop
+ include QAHelpers
+
+ MESSAGE = "Don't use a pattern for element, create a corresponding `%s` instead.".freeze
+
+ def on_send(node)
+ return unless in_qa_file?(node)
+ return unless method_name(node).to_s == 'element'
+
+ element_name, pattern = node.arguments
+ return unless pattern
+
+ add_offense(node, location: pattern.source_range, message: MESSAGE % "qa-#{element_name.value.to_s.tr('_', '-')}")
+ end
+
+ private
+
+ def method_name(node)
+ node.children[1]
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/qa_helpers.rb b/rubocop/qa_helpers.rb
new file mode 100644
index 00000000000..f4adf7f4e9f
--- /dev/null
+++ b/rubocop/qa_helpers.rb
@@ -0,0 +1,11 @@
+module RuboCop
+ # Module containing helper methods for writing QA cops.
+ module QAHelpers
+ # Returns true if the given node originated from the qa/ directory.
+ def in_qa_file?(node)
+ path = node.location.expression.source_buffer.name
+
+ path.start_with?(File.join(Dir.pwd, 'qa'))
+ end
+ end
+end
diff --git a/rubocop/rubocop.rb b/rubocop/rubocop.rb
index 76d6037706e..6c9b8753c1a 100644
--- a/rubocop/rubocop.rb
+++ b/rubocop/rubocop.rb
@@ -29,6 +29,7 @@ require_relative 'cop/migration/update_large_table'
require_relative 'cop/project_path_helper'
require_relative 'cop/rspec/env_assignment'
require_relative 'cop/rspec/factories_in_migration_specs'
+require_relative 'cop/qa/element_with_pattern'
require_relative 'cop/sidekiq_options_queue'
require_relative 'cop/destroy_all'
require_relative 'cop/ruby_interpolation_in_translation'
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index a8556771edd..be3fc832008 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -685,22 +685,34 @@ describe ApplicationController do
end
context 'html' do
+ subject { get :index, text: "hi \255" }
+
it 'renders 412' do
- get :index, text: "hi \255"
+ if Gitlab.rails5?
+ expect { subject }.to raise_error(ActionController::BadRequest)
+ else
+ subject
- expect(response).to have_gitlab_http_status(412)
- expect(response).to render_template :precondition_failed
+ expect(response).to have_gitlab_http_status(412)
+ expect(response).to render_template :precondition_failed
+ end
end
end
context 'js' do
+ subject { get :index, text: "hi \255", format: :js }
+
it 'renders 412' do
- get :index, text: "hi \255", format: :js
+ if Gitlab.rails5?
+ expect { subject }.to raise_error(ActionController::BadRequest)
+ else
+ subject
- json_response = JSON.parse(response.body)
+ json_response = JSON.parse(response.body)
- expect(response).to have_gitlab_http_status(412)
- expect(json_response['error']).to eq('Invalid UTF-8')
+ expect(response).to have_gitlab_http_status(412)
+ expect(json_response['error']).to eq('Invalid UTF-8')
+ end
end
end
end
diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb
index 5c8180baf8a..1484676eea3 100644
--- a/spec/controllers/projects/jobs_controller_spec.rb
+++ b/spec/controllers/projects/jobs_controller_spec.rb
@@ -352,6 +352,10 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
expect(json_response['has_trace']).to be true
end
end
+
+ it 'exposes the stage the job belongs to' do
+ expect(json_response['stage']).to eq('test')
+ end
end
context 'when requesting JSON job is triggered' do
diff --git a/spec/controllers/projects/merge_requests/conflicts_controller_spec.rb b/spec/controllers/projects/merge_requests/conflicts_controller_spec.rb
index 397cc79bde4..1e1ea9a7144 100644
--- a/spec/controllers/projects/merge_requests/conflicts_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/conflicts_controller_spec.rb
@@ -150,7 +150,6 @@ describe Projects::MergeRequests::ConflictsController do
'new_path' => path,
'blob_icon' => 'file-text-o',
'blob_path' => a_string_ending_with(path),
- 'blob_ace_mode' => 'ruby',
'content' => content)
end
end
diff --git a/spec/features/groups/group_settings_spec.rb b/spec/features/groups/group_settings_spec.rb
index 08fd9f8af2a..2cdbdcffbc3 100644
--- a/spec/features/groups/group_settings_spec.rb
+++ b/spec/features/groups/group_settings_spec.rb
@@ -125,7 +125,7 @@ describe 'Edit group settings' do
def save_group
page.within('.gs-general') do
- click_button 'Save group'
+ click_button 'Save changes'
end
end
end
diff --git a/spec/features/groups/share_lock_spec.rb b/spec/features/groups/share_lock_spec.rb
index 5bbe77019ca..704d9f12888 100644
--- a/spec/features/groups/share_lock_spec.rb
+++ b/spec/features/groups/share_lock_spec.rb
@@ -60,14 +60,14 @@ describe 'Group share with group lock' do
def enable_group_lock
page.within('.gs-permissions') do
check 'group_share_with_group_lock'
- click_on 'Save group'
+ click_on 'Save changes'
end
end
def disable_group_lock
page.within('.gs-permissions') do
uncheck 'group_share_with_group_lock'
- click_on 'Save group'
+ click_on 'Save changes'
end
end
end
diff --git a/spec/features/groups/show_spec.rb b/spec/features/groups/show_spec.rb
index ac961e98a61..4e6f73ef58a 100644
--- a/spec/features/groups/show_spec.rb
+++ b/spec/features/groups/show_spec.rb
@@ -101,4 +101,25 @@ describe 'Group show page' do
expect(page).to have_emoji('smile')
end
end
+
+ context 'where group has projects' do
+ let(:user) { create(:user) }
+
+ before do
+ group.add_owner(user)
+ sign_in(user)
+ end
+
+ it 'allows users to sorts projects by most stars', :js do
+ project1 = create(:project, namespace: group, star_count: 2)
+ project2 = create(:project, namespace: group, star_count: 3)
+ project3 = create(:project, namespace: group, star_count: 0)
+
+ visit group_path(group, sort: :stars_desc)
+
+ expect(find('.group-row:nth-child(1) .namespace-title > a')).to have_content(project2.title)
+ expect(find('.group-row:nth-child(2) .namespace-title > a')).to have_content(project1.title)
+ expect(find('.group-row:nth-child(3) .namespace-title > a')).to have_content(project3.title)
+ end
+ end
end
diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb
index e62bd6f8187..63aa26cf5fd 100644
--- a/spec/features/groups_spec.rb
+++ b/spec/features/groups_spec.rb
@@ -140,10 +140,13 @@ describe 'Group' do
visit path
end
+ it_behaves_like 'dirty submit form', [{ form: '.js-general-settings-form', input: 'input[name="group[name]"]' },
+ { form: '.js-general-permissions-form', input: 'input[name="group[two_factor_grace_period]"]' }]
+
it 'saves new settings' do
page.within('.gs-general') do
fill_in 'group_name', with: new_name
- click_button 'Save group'
+ click_button 'Save changes'
end
expect(page).to have_content 'successfully updated'
diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb
index 2076ce7b4f7..a3a301504ff 100644
--- a/spec/features/projects/jobs_spec.rb
+++ b/spec/features/projects/jobs_spec.rb
@@ -423,6 +423,31 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
end
+ context 'when job stops environment', :js do
+ let(:environment) { create(:environment, name: 'production', project: project) }
+ let(:build) do
+ create(
+ :ci_build,
+ :success,
+ :trace_live,
+ environment: environment.name,
+ pipeline: pipeline,
+ options: { environment: { action: 'stop' } }
+ )
+ end
+
+ before do
+ visit project_job_path(project, build)
+ wait_for_requests
+ end
+
+ it 'does not show environment information banner' do
+ expect(page).not_to have_selector('.js-environment-container')
+ expect(page).not_to have_selector('.environment-information')
+ expect(page).not_to have_text(environment.name)
+ end
+ end
+
describe 'environment info in job view', :js do
before do
visit project_job_path(project, job)
@@ -663,6 +688,56 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
expect(page).to have_content('This job does not have a trace.')
end
end
+
+ context 'with erased job', :js do
+ let(:job) { create(:ci_build, :erased, pipeline: pipeline) }
+
+ it 'renders erased job warning' do
+ visit project_job_path(project, job)
+ wait_for_requests
+
+ page.within('.js-job-erased-block') do
+ expect(page).to have_content('Job has been erased')
+ end
+ end
+ end
+
+ context 'without erased job', :js do
+ let(:job) { create(:ci_build, pipeline: pipeline) }
+
+ it 'does not render erased job warning' do
+ visit project_job_path(project, job)
+ wait_for_requests
+
+ expect(page).not_to have_css('.js-job-erased-block')
+ end
+ end
+
+ context 'on mobile', :js do
+ let(:job) { create(:ci_build, pipeline: pipeline) }
+
+ it 'renders collpased sidebar' do
+ page.current_window.resize_to(600, 800)
+
+ visit project_job_path(project, job)
+ wait_for_requests
+
+ expect(page).to have_css('.js-build-sidebar.right-sidebar-collapsed', visible: false)
+ expect(page).not_to have_css('.js-build-sidebar.right-sidebar-expanded', visible: false)
+ end
+ end
+
+ context 'on desktop', :js do
+ let(:job) { create(:ci_build, pipeline: pipeline) }
+
+ it 'renders expanded sidebar' do
+ visit project_job_path(project, job)
+ wait_for_requests
+
+ expect(page).to have_css('.js-build-sidebar.right-sidebar-expanded')
+ expect(page).not_to have_css('.js-build-sidebar.right-sidebar-collpased')
+ end
+ end
end
describe "POST /:project/jobs/:id/cancel", :js do
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 6fe21579e8e..df2b492ae6b 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
@@ -350,41 +350,6 @@ describe 'Projects > Show > User sees setup shortcut buttons' do
end
end
end
-
- describe '"Set up Koding" button' do
- it 'no "Set up Koding" button if Koding disabled' do
- stub_application_setting(koding_enabled?: false)
-
- visit project_path(project)
-
- page.within('.project-stats') do
- expect(page).not_to have_link('Set up Koding')
- end
- end
-
- it 'no "Set up Koding" button if the project already has a .koding.yml' do
- stub_application_setting(koding_enabled?: true)
- allow(Gitlab::CurrentSettings.current_application_settings).to receive(:koding_url).and_return('http://koding.example.com')
- expect(project.repository.changelog).not_to be_nil
- allow_any_instance_of(Repository).to receive(:koding_yml).and_return(project.repository.changelog)
-
- visit project_path(project)
-
- page.within('.project-stats') do
- expect(page).not_to have_link('Set up Koding')
- end
- end
-
- it '"Set up Koding" button linked to new file populated for a .koding.yml' do
- stub_application_setting(koding_enabled?: true)
-
- visit project_path(project)
-
- page.within('.project-stats') do
- expect(page).to have_link('Set up Koding', href: presenter.add_koding_stack_path)
- end
- end
- end
end
end
end
diff --git a/spec/features/security/dashboard_access_spec.rb b/spec/features/security/dashboard_access_spec.rb
index 149bd32e736..0c893e65d9c 100644
--- a/spec/features/security/dashboard_access_spec.rb
+++ b/spec/features/security/dashboard_access_spec.rb
@@ -43,20 +43,6 @@ describe "Dashboard access" do
it { is_expected.to be_allowed_for :visitor }
end
- describe "GET /koding" do
- subject { koding_path }
-
- context 'with Koding enabled' do
- before do
- stub_application_setting(koding_enabled?: true)
- end
-
- it { is_expected.to be_allowed_for :admin }
- it { is_expected.to be_allowed_for :user }
- it { is_expected.to be_denied_for :visitor }
- end
- end
-
describe "GET /projects/new" do
it { expect(new_project_path).to be_allowed_for :admin }
it { expect(new_project_path).to be_allowed_for :user }
diff --git a/spec/features/uploads/user_uploads_avatar_to_group_spec.rb b/spec/features/uploads/user_uploads_avatar_to_group_spec.rb
index a07edc42eae..72b53bae46a 100644
--- a/spec/features/uploads/user_uploads_avatar_to_group_spec.rb
+++ b/spec/features/uploads/user_uploads_avatar_to_group_spec.rb
@@ -15,7 +15,7 @@ describe 'User uploads avatar to group' do
)
page.within('.gs-general') do
- click_button 'Save group'
+ click_button 'Save changes'
end
visit group_path(group)
diff --git a/spec/features/users/overview_spec.rb b/spec/features/users/overview_spec.rb
index 11f357cbaa5..b0ff53f9ccb 100644
--- a/spec/features/users/overview_spec.rb
+++ b/spec/features/users/overview_spec.rb
@@ -104,8 +104,9 @@ describe 'Overview tab on a user profile', :js do
end
describe 'user has a personal project' do
- let(:private_project) { create(:project, :private, namespace: user.namespace, creator: user) { |p| p.add_maintainer(user) } }
- let!(:private_event) { create(:event, project: private_project, author: user) }
+ before do
+ create(:project, :private, namespace: user.namespace, creator: user) { |p| p.add_maintainer(user) }
+ end
include_context 'visit overview tab'
@@ -119,5 +120,31 @@ describe 'Overview tab on a user profile', :js do
expect(find('#js-overview .projects-block')).to have_selector('.js-view-all', visible: true)
end
end
+
+ describe 'user has more than ten personal projects' do
+ before do
+ create_list(:project, 11, :private, namespace: user.namespace, creator: user) do |project|
+ project.add_maintainer(user)
+ end
+ end
+
+ include_context 'visit overview tab'
+
+ it 'it shows max. ten entries in the list of projects' do
+ page.within('.projects-block') do
+ expect(page).to have_selector('.project-row', count: 10)
+ end
+ end
+
+ it 'shows a link to the project list' do
+ expect(find('#js-overview .projects-block')).to have_selector('.js-view-all', visible: true)
+ end
+
+ it 'does not show pagination' do
+ page.within('.projects-block') do
+ expect(page).not_to have_selector('.gl-pagination')
+ end
+ end
+ end
end
end
diff --git a/spec/finders/branches_finder_spec.rb b/spec/finders/branches_finder_spec.rb
index 9e3f2c69606..7d164539d9a 100644
--- a/spec/finders/branches_finder_spec.rb
+++ b/spec/finders/branches_finder_spec.rb
@@ -66,7 +66,7 @@ describe BranchesFinder do
context 'filter and sort' do
it 'filters branches by name and sorts by recently_updated' do
- params = { sort: 'updated_desc', search: 'feature' }
+ params = { sort: 'updated_desc', search: 'feat' }
branches_finder = described_class.new(repository, params)
result = branches_finder.execute
@@ -75,6 +75,17 @@ describe BranchesFinder do
expect(result.count).to eq(2)
end
+ it 'filters branches by name and sorts by recently_updated, with exact matches first' do
+ params = { sort: 'updated_desc', search: 'feature' }
+ branches_finder = described_class.new(repository, params)
+
+ result = branches_finder.execute
+
+ expect(result.first.name).to eq('feature')
+ expect(result.second.name).to eq('feature_conflict')
+ expect(result.count).to eq(2)
+ end
+
it 'filters branches by name and sorts by last_updated' do
params = { sort: 'updated_asc', search: 'feature' }
branches_finder = described_class.new(repository, params)
@@ -84,6 +95,26 @@ describe BranchesFinder do
expect(result.first.name).to eq('feature')
expect(result.count).to eq(2)
end
+
+ it 'filters branches by name that begins with' do
+ params = { search: '^feature_' }
+ branches_finder = described_class.new(repository, params)
+
+ result = branches_finder.execute
+
+ expect(result.first.name).to eq('feature_conflict')
+ expect(result.count).to eq(1)
+ end
+
+ it 'filters branches by name that ends with' do
+ params = { search: 'feature$' }
+ branches_finder = described_class.new(repository, params)
+
+ result = branches_finder.execute
+
+ expect(result.first.name).to eq('feature')
+ expect(result.count).to eq(1)
+ end
end
end
end
diff --git a/spec/fixtures/api/schemas/job/job_details.json b/spec/fixtures/api/schemas/job/job_details.json
index 07e674216fa..8218474705c 100644
--- a/spec/fixtures/api/schemas/job/job_details.json
+++ b/spec/fixtures/api/schemas/job/job_details.json
@@ -7,7 +7,8 @@
"artifact",
"runner",
"runners",
- "has_trace"
+ "has_trace",
+ "stage"
],
"properties": {
"artifact": { "$ref": "artifact.json" },
@@ -16,6 +17,7 @@
"deployment_status": { "$ref": "deployment_status.json" },
"runner": { "$ref": "runner.json" },
"runners": { "$ref": "runners.json" },
- "has_trace": { "type": "boolean" }
+ "has_trace": { "type": "boolean" },
+ "stage": { "type": "string" }
}
}
diff --git a/spec/fixtures/valid.po b/spec/fixtures/valid.po
index e43fd5fea15..dbe2f952bad 100644
--- a/spec/fixtures/valid.po
+++ b/spec/fixtures/valid.po
@@ -790,9 +790,6 @@ msgstr "Establezca una contraseña en su cuenta para actualizar o enviar a travÃ
msgid "Set up CI"
msgstr "Configurar CI"
-msgid "Set up Koding"
-msgstr "Configurar Koding"
-
msgid "Set up auto deploy"
msgstr "Configurar auto despliegue"
diff --git a/spec/helpers/preferences_helper_spec.rb b/spec/helpers/preferences_helper_spec.rb
index 363ebc88afd..c112c8ed633 100644
--- a/spec/helpers/preferences_helper_spec.rb
+++ b/spec/helpers/preferences_helper_spec.rb
@@ -2,6 +2,13 @@ require 'spec_helper'
describe PreferencesHelper do
describe '#dashboard_choices' do
+ let(:user) { build(:user) }
+
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ allow(helper).to receive(:can?).and_return(false)
+ end
+
it 'raises an exception when defined choices may be missing' do
expect(User).to receive(:dashboards).and_return(foo: 'foo')
expect { helper.dashboard_choices }.to raise_error(RuntimeError)
diff --git a/spec/javascripts/.eslintrc.yml b/spec/javascripts/.eslintrc.yml
index 9b2c84ce9f5..1448849a0b7 100644
--- a/spec/javascripts/.eslintrc.yml
+++ b/spec/javascripts/.eslintrc.yml
@@ -37,7 +37,5 @@ rules:
- 'fixtures/blob'
# Temporarily disabled to facilitate an upgrade to eslint-plugin-jasmine
jasmine/new-line-before-expect: off
- jasmine/new-line-between-declarations: off
jasmine/no-promise-without-done-fail: off
- jasmine/prefer-jasmine-matcher: off
jasmine/prefer-toHaveBeenCalledWith: off
diff --git a/spec/javascripts/awards_handler_spec.js b/spec/javascripts/awards_handler_spec.js
index 0c5d68990d5..3f84a46e8d9 100644
--- a/spec/javascripts/awards_handler_spec.js
+++ b/spec/javascripts/awards_handler_spec.js
@@ -55,6 +55,7 @@ import '~/lib/utils/common_utils';
});
};
});
+
afterEach(function() {
// restore original url root value
gon.relative_url_root = urlRoot;
@@ -64,6 +65,7 @@ import '~/lib/utils/common_utils';
awardsHandler.destroy();
});
+
describe('::showEmojiMenu', function() {
it('should show emoji menu when Add emoji button clicked', function(done) {
$('.js-add-award')
@@ -78,6 +80,7 @@ import '~/lib/utils/common_utils';
return expect($('.js-awards-block.current').length).toBe(1);
});
});
+
it('should also show emoji menu for the smiley icon in notes', function(done) {
$('.js-add-award.note-action-button').click();
return lazyAssert(done, function() {
@@ -85,6 +88,7 @@ import '~/lib/utils/common_utils';
return expect($emojiMenu.length).toBe(1);
});
});
+
it('should remove emoji menu when body is clicked', function(done) {
$('.js-add-award')
.eq(0)
@@ -98,6 +102,7 @@ import '~/lib/utils/common_utils';
return expect($('.js-awards-block.current').length).toBe(0);
});
});
+
it('should not remove emoji menu when search is clicked', function(done) {
$('.js-add-award')
.eq(0)
@@ -123,6 +128,7 @@ import '~/lib/utils/common_utils';
expect($emojiButton.next('.js-counter').text()).toBe('1');
return expect($votesBlock.hasClass('hidden')).toBe(false);
});
+
it('should remove the emoji when we click again', function() {
var $emojiButton, $votesBlock;
$votesBlock = $('.js-awards-block').eq(0);
@@ -142,6 +148,7 @@ import '~/lib/utils/common_utils';
return expect($emojiButton.next('.js-counter').text()).toBe('4');
});
});
+
describe('::userAuthored', function() {
it('should update tooltip to user authored title', function() {
var $thumbsUpEmoji, $votesBlock;
@@ -153,6 +160,7 @@ import '~/lib/utils/common_utils';
'You cannot vote on your own issue, MR and note',
);
});
+
it('should restore tooltip back to initial vote list', function() {
var $thumbsUpEmoji, $votesBlock;
jasmine.clock().install();
@@ -165,6 +173,7 @@ import '~/lib/utils/common_utils';
return expect($thumbsUpEmoji.data('originalTitle')).toBe('sam');
});
});
+
describe('::getAwardUrl', function() {
return it('returns the url for request', function() {
return expect(awardsHandler.getAwardUrl()).toBe(
@@ -172,6 +181,7 @@ import '~/lib/utils/common_utils';
);
});
});
+
describe('::addAward and ::checkMutuality', function() {
return it('should handle :+1: and :-1: mutuality', function() {
var $thumbsDownEmoji, $thumbsUpEmoji, $votesBlock, awardUrl;
@@ -189,6 +199,7 @@ import '~/lib/utils/common_utils';
return expect($thumbsDownEmoji.hasClass('active')).toBe(true);
});
});
+
describe('::removeEmoji', function() {
return it('should remove emoji', function() {
var $votesBlock, awardUrl;
@@ -200,6 +211,7 @@ import '~/lib/utils/common_utils';
return expect($votesBlock.find('[data-name=fire]').length).toBe(0);
});
});
+
describe('::addYouToUserList', function() {
it('should prepend "You" to the award tooltip', function() {
var $thumbsUpEmoji, $votesBlock, awardUrl;
@@ -222,6 +234,7 @@ import '~/lib/utils/common_utils';
return expect($thumbsUpEmoji.data('originalTitle')).toBe('You and sam');
});
});
+
describe('::removeYouToUserList', function() {
it('removes "You" from the front of the tooltip', function() {
var $thumbsUpEmoji, $votesBlock, awardUrl;
@@ -246,6 +259,7 @@ import '~/lib/utils/common_utils';
return expect($thumbsUpEmoji.data('originalTitle')).toBe('sam');
});
});
+
describe('::searchEmojis', () => {
it('should filter the emoji', function(done) {
return openAndWaitForEmojiMenu()
@@ -263,6 +277,7 @@ import '~/lib/utils/common_utils';
done.fail(`Failed to open and build emoji menu: ${err.message}`);
});
});
+
it('should clear the search when searching for nothing', function(done) {
return openAndWaitForEmojiMenu()
.then(() => {
@@ -305,6 +320,7 @@ import '~/lib/utils/common_utils';
done.fail(`Failed to open and build emoji menu: ${err.message}`);
});
});
+
it('should remove already selected emoji', function(done) {
return openEmojiMenuAndAddEmoji()
.then(() => {
diff --git a/spec/javascripts/behaviors/quick_submit_spec.js b/spec/javascripts/behaviors/quick_submit_spec.js
index d8aa5c636da..b3a5eac8982 100644
--- a/spec/javascripts/behaviors/quick_submit_spec.js
+++ b/spec/javascripts/behaviors/quick_submit_spec.js
@@ -58,12 +58,14 @@ describe('Quick Submit behavior', function () {
expect(submitButton).toBeDisabled();
});
+
it('disables button of type submit', () => {
const submitButton = $('.js-quick-submit input[type=submit]');
this.textarea.trigger(keydownEvent());
expect(submitButton).toBeDisabled();
});
+
it('only clicks one submit', () => {
const existingSubmit = $('.js-quick-submit input[type=submit]');
// Add an extra submit button
diff --git a/spec/javascripts/bootstrap_jquery_spec.js b/spec/javascripts/bootstrap_jquery_spec.js
index 052465d8d88..cd61d920fa0 100644
--- a/spec/javascripts/bootstrap_jquery_spec.js
+++ b/spec/javascripts/bootstrap_jquery_spec.js
@@ -9,6 +9,7 @@ import '~/commons/bootstrap';
beforeEach(function() {
return setFixtures('<input type="text" />');
});
+
it('adds the disabled attribute', function() {
var $input;
$input = $('input').first();
@@ -26,6 +27,7 @@ import '~/commons/bootstrap';
beforeEach(function() {
return setFixtures('<input type="text" disabled="disabled" class="disabled" />');
});
+
it('removes the disabled attribute', function() {
var $input;
$input = $('input').first();
diff --git a/spec/javascripts/datetime_utility_spec.js b/spec/javascripts/datetime_utility_spec.js
index 6c3e73f134e..24e4871ce44 100644
--- a/spec/javascripts/datetime_utility_spec.js
+++ b/spec/javascripts/datetime_utility_spec.js
@@ -158,9 +158,9 @@ describe('getTimeframeWindowFrom', () => {
const timeframe = datetimeUtility.getTimeframeWindowFrom(startDate, 5);
expect(timeframe.length).toBe(5);
timeframe.forEach((timeframeItem, index) => {
- expect(timeframeItem.getFullYear() === mockTimeframe[index].getFullYear()).toBe(true);
- expect(timeframeItem.getMonth() === mockTimeframe[index].getMonth()).toBe(true);
- expect(timeframeItem.getDate() === mockTimeframe[index].getDate()).toBeTruthy();
+ expect(timeframeItem.getFullYear()).toBe(mockTimeframe[index].getFullYear());
+ expect(timeframeItem.getMonth()).toBe(mockTimeframe[index].getMonth());
+ expect(timeframeItem.getDate()).toBe(mockTimeframe[index].getDate());
});
});
});
diff --git a/spec/javascripts/diffs/components/diff_file_header_spec.js b/spec/javascripts/diffs/components/diff_file_header_spec.js
index c986ea604b2..1f7d5f42322 100644
--- a/spec/javascripts/diffs/components/diff_file_header_spec.js
+++ b/spec/javascripts/diffs/components/diff_file_header_spec.js
@@ -6,6 +6,8 @@ import DiffFileHeader from '~/diffs/components/diff_file_header.vue';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+Vue.use(Vuex);
+
const discussionFixture = 'merge_requests/diff_discussion.json';
describe('diff_file_header', () => {
@@ -58,19 +60,19 @@ describe('diff_file_header', () => {
describe('titleLink', () => {
beforeEach(() => {
+ props.discussionPath = 'link://to/discussion';
Object.assign(props.diffFile, {
- fileHash: 'badc0ffee',
submoduleLink: 'link://to/submodule',
submoduleTreeUrl: 'some://tree/url',
});
});
- it('returns the fileHash for files', () => {
+ it('returns the discussionPath for files', () => {
props.diffFile.submodule = false;
vm = mountComponentWithStore(Component, { props, store });
- expect(vm.titleLink).toBe(`#${props.diffFile.fileHash}`);
+ expect(vm.titleLink).toBe(props.discussionPath);
});
it('returns the submoduleTreeUrl for submodules', () => {
@@ -91,6 +93,13 @@ describe('diff_file_header', () => {
expect(vm.titleLink).toBe(props.diffFile.submoduleLink);
});
+
+ it('sets the correct path to the discussion', () => {
+ props.discussionPath = 'link://to/discussion';
+ vm = mountComponentWithStore(Component, { props, store });
+ const href = vm.$el.querySelector('.js-title-wrapper').getAttribute('href');
+ expect(href).toBe(vm.discussionPath);
+ });
});
describe('filePath', () => {
diff --git a/spec/javascripts/diffs/components/diff_file_spec.js b/spec/javascripts/diffs/components/diff_file_spec.js
index 13859f43e98..b8d4b31ee04 100644
--- a/spec/javascripts/diffs/components/diff_file_spec.js
+++ b/spec/javascripts/diffs/components/diff_file_spec.js
@@ -24,14 +24,14 @@ describe('DiffFile', () => {
expect(el.querySelectorAll('.diff-content.hidden').length).toEqual(0);
expect(el.querySelector('.js-file-title')).toBeDefined();
- expect(el.querySelector('.file-title-name').innerText.indexOf(filePath) > -1).toEqual(true);
+ expect(el.querySelector('.file-title-name').innerText.indexOf(filePath)).toBeGreaterThan(-1);
expect(el.querySelector('.js-syntax-highlight')).toBeDefined();
expect(vm.file.renderIt).toEqual(false);
vm.file.renderIt = true;
vm.$nextTick(() => {
- expect(el.querySelectorAll('.line_content').length > 5).toEqual(true);
+ expect(el.querySelectorAll('.line_content').length).toBeGreaterThan(5);
});
});
@@ -98,9 +98,7 @@ describe('DiffFile', () => {
'This source diff could not be displayed because it is too large',
);
expect(vm.$el.querySelector('.js-too-large-diff')).toBeDefined();
- expect(vm.$el.querySelector('.js-too-large-diff a').href.indexOf(BLOB_LINK) > -1).toEqual(
- true,
- );
+ expect(vm.$el.querySelector('.js-too-large-diff a').href.indexOf(BLOB_LINK)).toBeGreaterThan(-1);
done();
});
diff --git a/spec/javascripts/diffs/components/diff_line_gutter_content_spec.js b/spec/javascripts/diffs/components/diff_line_gutter_content_spec.js
index 663c0680845..f36454cc23e 100644
--- a/spec/javascripts/diffs/components/diff_line_gutter_content_spec.js
+++ b/spec/javascripts/diffs/components/diff_line_gutter_content_spec.js
@@ -94,7 +94,7 @@ describe('DiffLineGutterContent', () => {
const component = createComponent({ lineNumber, lineCode });
const link = component.$el.querySelector('a');
- expect(link.href.indexOf(`#${lineCode}`) > -1).toEqual(true);
+ expect(link.href.indexOf(`#${lineCode}`)).toBeGreaterThan(-1);
expect(link.dataset.linenumber).toEqual(lineNumber.toString());
});
diff --git a/spec/javascripts/diffs/components/inline_diff_view_spec.js b/spec/javascripts/diffs/components/inline_diff_view_spec.js
index b02328dd359..705558e860b 100644
--- a/spec/javascripts/diffs/components/inline_diff_view_spec.js
+++ b/spec/javascripts/diffs/components/inline_diff_view_spec.js
@@ -27,7 +27,7 @@ describe('InlineDiffView', () => {
expect(el.querySelectorAll('tr.line_holder').length).toEqual(6);
expect(el.querySelectorAll('tr.line_holder.new').length).toEqual(2);
expect(el.querySelectorAll('tr.line_holder.match').length).toEqual(1);
- expect(el.textContent.indexOf('Bad dates') > -1).toEqual(true);
+ expect(el.textContent.indexOf('Bad dates')).toBeGreaterThan(-1);
});
it('should render discussions', done => {
@@ -37,7 +37,7 @@ describe('InlineDiffView', () => {
Vue.nextTick(() => {
expect(el.querySelectorAll('.notes_holder').length).toEqual(1);
expect(el.querySelectorAll('.notes_holder .note-discussion li').length).toEqual(5);
- expect(el.innerText.indexOf('comment 5') > -1).toEqual(true);
+ expect(el.innerText.indexOf('comment 5')).toBeGreaterThan(-1);
component.$store.dispatch('setInitialNotes', []);
done();
diff --git a/spec/javascripts/dirty_submit/dirty_submit_collection_spec.js b/spec/javascripts/dirty_submit/dirty_submit_collection_spec.js
new file mode 100644
index 00000000000..87a26183b63
--- /dev/null
+++ b/spec/javascripts/dirty_submit/dirty_submit_collection_spec.js
@@ -0,0 +1,25 @@
+import DirtySubmitCollection from '~/dirty_submit/dirty_submit_collection';
+import { setInput, createForm } from './helper';
+
+describe('DirtySubmitCollection', () => {
+ it('disables submits until there are changes', done => {
+ const testElementsCollection = [createForm(), createForm()];
+ const forms = testElementsCollection.map(testElements => testElements.form);
+
+ new DirtySubmitCollection(forms); // eslint-disable-line no-new
+
+ testElementsCollection.forEach(testElements => {
+ const { input, submit } = testElements;
+ const originalValue = input.value;
+
+ expect(submit.disabled).toBe(true);
+
+ return setInput(input, `${originalValue} changes`)
+ .then(() => expect(submit.disabled).toBe(false))
+ .then(() => setInput(input, originalValue))
+ .then(() => expect(submit.disabled).toBe(true))
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+});
diff --git a/spec/javascripts/dirty_submit/dirty_submit_factory_spec.js b/spec/javascripts/dirty_submit/dirty_submit_factory_spec.js
new file mode 100644
index 00000000000..40843a68582
--- /dev/null
+++ b/spec/javascripts/dirty_submit/dirty_submit_factory_spec.js
@@ -0,0 +1,18 @@
+import dirtySubmitFactory from '~/dirty_submit/dirty_submit_factory';
+import DirtySubmitForm from '~/dirty_submit/dirty_submit_form';
+import DirtySubmitCollection from '~/dirty_submit/dirty_submit_collection';
+import { createForm } from './helper';
+
+describe('DirtySubmitCollection', () => {
+ it('returns a DirtySubmitForm instance for single form elements', () => {
+ const { form } = createForm();
+
+ expect(dirtySubmitFactory(form) instanceof DirtySubmitForm).toBe(true);
+ });
+
+ it('returns a DirtySubmitCollection instance for a collection of form elements', () => {
+ const forms = [createForm().form, createForm().form];
+
+ expect(dirtySubmitFactory(forms) instanceof DirtySubmitCollection).toBe(true);
+ });
+});
diff --git a/spec/javascripts/dirty_submit/dirty_submit_form_spec.js b/spec/javascripts/dirty_submit/dirty_submit_form_spec.js
new file mode 100644
index 00000000000..86d53fa984a
--- /dev/null
+++ b/spec/javascripts/dirty_submit/dirty_submit_form_spec.js
@@ -0,0 +1,21 @@
+
+import DirtySubmitForm from '~/dirty_submit/dirty_submit_form';
+import { setInput, createForm } from './helper';
+
+describe('DirtySubmitForm', () => {
+ it('disables submit until there are changes', done => {
+ const { form, input, submit } = createForm();
+ const originalValue = input.value;
+
+ new DirtySubmitForm(form); // eslint-disable-line no-new
+
+ expect(submit.disabled).toBe(true);
+
+ return setInput(input, `${originalValue} changes`)
+ .then(() => expect(submit.disabled).toBe(false))
+ .then(() => setInput(input, originalValue))
+ .then(() => expect(submit.disabled).toBe(true))
+ .then(done)
+ .catch(done.fail);
+ });
+});
diff --git a/spec/javascripts/dirty_submit/helper.js b/spec/javascripts/dirty_submit/helper.js
new file mode 100644
index 00000000000..6d1e643553c
--- /dev/null
+++ b/spec/javascripts/dirty_submit/helper.js
@@ -0,0 +1,31 @@
+import DirtySubmitForm from '~/dirty_submit/dirty_submit_form';
+import setTimeoutPromiseHelper from '../helpers/set_timeout_promise_helper';
+
+export function setInput(element, value) {
+ element.value = value;
+
+ element.dispatchEvent(
+ new Event('input', {
+ bubbles: true,
+ cancelable: true,
+ }),
+ );
+
+ return setTimeoutPromiseHelper(DirtySubmitForm.THROTTLE_DURATION);
+}
+
+export function createForm() {
+ const form = document.createElement('form');
+ form.innerHTML = `
+ <input type="text" value="original" class="js-input" name="input" />
+ <button type="submit" class="js-dirty-submit"></button>
+ `;
+ const input = form.querySelector('.js-input');
+ const submit = form.querySelector('.js-dirty-submit');
+
+ return {
+ form,
+ input,
+ submit,
+ };
+}
diff --git a/spec/javascripts/emoji_spec.js b/spec/javascripts/emoji_spec.js
index 124d91f4477..629422780e8 100644
--- a/spec/javascripts/emoji_spec.js
+++ b/spec/javascripts/emoji_spec.js
@@ -140,6 +140,7 @@ describe('gl_emoji', () => {
},
);
});
+
it('bomb emoji with sprite fallback', () => {
const emojiKey = 'bomb';
const markup = glEmojiTag(emojiFixtureMap[emojiKey].name, {
@@ -195,24 +196,31 @@ describe('gl_emoji', () => {
it('should gracefully handle empty string', () => {
expect(isFlagEmoji('')).toBeFalsy();
});
+
it('should detect flag_ac', () => {
expect(isFlagEmoji('🇦🇨')).toBeTruthy();
});
+
it('should detect flag_us', () => {
expect(isFlagEmoji('🇺🇸')).toBeTruthy();
});
+
it('should detect flag_zw', () => {
expect(isFlagEmoji('🇿🇼')).toBeTruthy();
});
+
it('should not detect flags', () => {
expect(isFlagEmoji('ðŸŽ')).toBeFalsy();
});
+
it('should not detect triangular_flag_on_post', () => {
expect(isFlagEmoji('🚩')).toBeFalsy();
});
+
it('should not detect single letter', () => {
expect(isFlagEmoji('🇦')).toBeFalsy();
});
+
it('should not detect >2 letters', () => {
expect(isFlagEmoji('🇦🇧🇨')).toBeFalsy();
});
@@ -222,15 +230,19 @@ describe('gl_emoji', () => {
it('should gracefully handle empty string', () => {
expect(isRainbowFlagEmoji('')).toBeFalsy();
});
+
it('should detect rainbow_flag', () => {
expect(isRainbowFlagEmoji('ðŸ³ðŸŒˆ')).toBeTruthy();
});
+
it('should not detect flag_white on its\' own', () => {
expect(isRainbowFlagEmoji('ðŸ³')).toBeFalsy();
});
+
it('should not detect rainbow on its\' own', () => {
expect(isRainbowFlagEmoji('🌈')).toBeFalsy();
});
+
it('should not detect flag_white with something else', () => {
expect(isRainbowFlagEmoji('ðŸ³ðŸ”µ')).toBeFalsy();
});
@@ -240,15 +252,19 @@ describe('gl_emoji', () => {
it('should gracefully handle empty string', () => {
expect(isKeycapEmoji('')).toBeFalsy();
});
+
it('should detect one(keycap)', () => {
expect(isKeycapEmoji('1ï¸âƒ£')).toBeTruthy();
});
+
it('should detect nine(keycap)', () => {
expect(isKeycapEmoji('9ï¸âƒ£')).toBeTruthy();
});
+
it('should not detect ten(keycap)', () => {
expect(isKeycapEmoji('🔟')).toBeFalsy();
});
+
it('should not detect hash(keycap)', () => {
expect(isKeycapEmoji('#⃣')).toBeFalsy();
});
@@ -258,24 +274,31 @@ describe('gl_emoji', () => {
it('should gracefully handle empty string', () => {
expect(isSkinToneComboEmoji('')).toBeFalsy();
});
+
it('should detect hand_splayed_tone5', () => {
expect(isSkinToneComboEmoji('ðŸ–ðŸ¿')).toBeTruthy();
});
+
it('should not detect hand_splayed', () => {
expect(isSkinToneComboEmoji('ðŸ–')).toBeFalsy();
});
+
it('should detect lifter_tone1', () => {
expect(isSkinToneComboEmoji('ðŸ‹ðŸ»')).toBeTruthy();
});
+
it('should not detect lifter', () => {
expect(isSkinToneComboEmoji('ðŸ‹')).toBeFalsy();
});
+
it('should detect rowboat_tone4', () => {
expect(isSkinToneComboEmoji('🚣ðŸ¾')).toBeTruthy();
});
+
it('should not detect rowboat', () => {
expect(isSkinToneComboEmoji('🚣')).toBeFalsy();
});
+
it('should not detect individual tone emoji', () => {
expect(isSkinToneComboEmoji('ðŸ»')).toBeFalsy();
});
@@ -285,9 +308,11 @@ describe('gl_emoji', () => {
it('should gracefully handle empty string', () => {
expect(isHorceRacingSkinToneComboEmoji('')).toBeFalsy();
});
+
it('should detect horse_racing_tone2', () => {
expect(isHorceRacingSkinToneComboEmoji('ðŸ‡ðŸ¼')).toBeTruthy();
});
+
it('should not detect horse_racing', () => {
expect(isHorceRacingSkinToneComboEmoji('ðŸ‡')).toBeFalsy();
});
@@ -297,36 +322,47 @@ describe('gl_emoji', () => {
it('should gracefully handle empty string', () => {
expect(isPersonZwjEmoji('')).toBeFalsy();
});
+
it('should detect couple_mm', () => {
expect(isPersonZwjEmoji('👨â€â¤ï¸â€ðŸ‘¨')).toBeTruthy();
});
+
it('should not detect couple_with_heart', () => {
expect(isPersonZwjEmoji('💑')).toBeFalsy();
});
+
it('should not detect couplekiss', () => {
expect(isPersonZwjEmoji('ðŸ’')).toBeFalsy();
});
+
it('should detect family_mmb', () => {
expect(isPersonZwjEmoji('👨â€ðŸ‘¨â€ðŸ‘¦')).toBeTruthy();
});
+
it('should detect family_mwgb', () => {
expect(isPersonZwjEmoji('👨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦')).toBeTruthy();
});
+
it('should not detect family', () => {
expect(isPersonZwjEmoji('👪')).toBeFalsy();
});
+
it('should detect kiss_ww', () => {
expect(isPersonZwjEmoji('👩â€â¤ï¸â€ðŸ’‹â€ðŸ‘©')).toBeTruthy();
});
+
it('should not detect girl', () => {
expect(isPersonZwjEmoji('👧')).toBeFalsy();
});
+
it('should not detect girl_tone5', () => {
expect(isPersonZwjEmoji('👧ðŸ¿')).toBeFalsy();
});
+
it('should not detect man', () => {
expect(isPersonZwjEmoji('👨')).toBeFalsy();
});
+
it('should not detect woman', () => {
expect(isPersonZwjEmoji('👩')).toBeFalsy();
});
@@ -341,6 +377,7 @@ describe('gl_emoji', () => {
);
expect(isSupported).toBeTruthy();
});
+
it('should gracefully handle empty string without unicode support', () => {
const isSupported = isEmojiUnicodeSupported(
{},
@@ -349,6 +386,7 @@ describe('gl_emoji', () => {
);
expect(isSupported).toBeFalsy();
});
+
it('bomb(6.0) with 6.0 support', () => {
const emojiKey = 'bomb';
const unicodeSupportMap = Object.assign({}, emptySupportMap, {
diff --git a/spec/javascripts/environments/environments_app_spec.js b/spec/javascripts/environments/environments_app_spec.js
index 6968fbc7ce7..60787b4c88d 100644
--- a/spec/javascripts/environments/environments_app_spec.js
+++ b/spec/javascripts/environments/environments_app_spec.js
@@ -158,12 +158,7 @@ describe('Environment', () => {
component.$el.querySelector('.folder-name').click();
Vue.nextTick(() => {
- expect(
- component.$el.querySelector('.folder-icon i.fa-caret-right').getAttribute('style'),
- ).toContain('display: none');
- expect(
- component.$el.querySelector('.folder-icon i.fa-caret-down').getAttribute('style'),
- ).not.toContain('display: none');
+ expect(component.$el.querySelector('.folder-icon.ic-chevron-right')).toBe(null);
done();
});
}, 0);
@@ -179,12 +174,7 @@ describe('Environment', () => {
component.$el.querySelector('.folder-name').click();
Vue.nextTick(() => {
- expect(
- component.$el.querySelector('.folder-icon i.fa-caret-down').getAttribute('style'),
- ).toContain('display: none');
- expect(
- component.$el.querySelector('.folder-icon i.fa-caret-right').getAttribute('style'),
- ).not.toContain('display: none');
+ expect(component.$el.querySelector('.folder-icon.ic-chevron-down')).toBe(null);
done();
});
});
diff --git a/spec/javascripts/filtered_search/dropdown_utils_spec.js b/spec/javascripts/filtered_search/dropdown_utils_spec.js
index 68bbbf838da..3dc8089cd83 100644
--- a/spec/javascripts/filtered_search/dropdown_utils_spec.js
+++ b/spec/javascripts/filtered_search/dropdown_utils_spec.js
@@ -237,7 +237,7 @@ describe('Dropdown Utils', () => {
it('should not linear-gradient more than 4 colors', () => {
const gradient = DropdownUtils.duplicateLabelColor(['#FFFFFF', '#000000', '#333333', '#DDDDDD', '#EEEEEE']);
- expect(gradient.indexOf('#EEEEEE') === -1).toEqual(true);
+ expect(gradient.indexOf('#EEEEEE')).toBe(-1);
});
});
diff --git a/spec/javascripts/filtered_search/filtered_search_token_keys_spec.js b/spec/javascripts/filtered_search/filtered_search_token_keys_spec.js
index ab0ab72720e..cf7789a1d57 100644
--- a/spec/javascripts/filtered_search/filtered_search_token_keys_spec.js
+++ b/spec/javascripts/filtered_search/filtered_search_token_keys_spec.js
@@ -19,7 +19,7 @@ describe('Filtered Search Token Keys', () => {
describe('get', () => {
it('should return tokenKeys', () => {
- expect(new FilteredSearchTokenKeys().get() !== null).toBe(true);
+ expect(new FilteredSearchTokenKeys().get()).not.toBeNull();
});
it('should return tokenKeys as an array', () => {
@@ -40,7 +40,7 @@ describe('Filtered Search Token Keys', () => {
describe('getConditions', () => {
it('should return conditions', () => {
- expect(new FilteredSearchTokenKeys().getConditions() !== null).toBe(true);
+ expect(new FilteredSearchTokenKeys().getConditions()).not.toBeNull();
});
it('should return conditions as an array', () => {
@@ -51,7 +51,7 @@ describe('Filtered Search Token Keys', () => {
describe('searchByKey', () => {
it('should return null when key not found', () => {
const tokenKey = new FilteredSearchTokenKeys(tokenKeys).searchByKey('notakey');
- expect(tokenKey === null).toBe(true);
+ expect(tokenKey).toBeNull();
});
it('should return tokenKey when found by key', () => {
@@ -63,7 +63,7 @@ describe('Filtered Search Token Keys', () => {
describe('searchBySymbol', () => {
it('should return null when symbol not found', () => {
const tokenKey = new FilteredSearchTokenKeys(tokenKeys).searchBySymbol('notasymbol');
- expect(tokenKey === null).toBe(true);
+ expect(tokenKey).toBeNull();
});
it('should return tokenKey when found by symbol', () => {
@@ -75,7 +75,7 @@ describe('Filtered Search Token Keys', () => {
describe('searchByKeyParam', () => {
it('should return null when key param not found', () => {
const tokenKey = new FilteredSearchTokenKeys(tokenKeys).searchByKeyParam('notakeyparam');
- expect(tokenKey === null).toBe(true);
+ expect(tokenKey).toBeNull();
});
it('should return tokenKey when found by key param', () => {
@@ -92,7 +92,7 @@ describe('Filtered Search Token Keys', () => {
describe('searchByConditionUrl', () => {
it('should return null when condition url not found', () => {
const condition = new FilteredSearchTokenKeys([], [], conditions).searchByConditionUrl(null);
- expect(condition === null).toBe(true);
+ expect(condition).toBeNull();
});
it('should return condition when found by url', () => {
@@ -106,7 +106,7 @@ describe('Filtered Search Token Keys', () => {
it('should return null when condition tokenKey and value not found', () => {
const condition = new FilteredSearchTokenKeys([], [], conditions)
.searchByConditionKeyValue(null, null);
- expect(condition === null).toBe(true);
+ expect(condition).toBeNull();
});
it('should return condition when found by tokenKey and value', () => {
diff --git a/spec/javascripts/fixtures/groups.rb b/spec/javascripts/fixtures/groups.rb
index a2035ceae15..b42f442557c 100644
--- a/spec/javascripts/fixtures/groups.rb
+++ b/spec/javascripts/fixtures/groups.rb
@@ -17,6 +17,16 @@ describe 'Groups (JavaScript fixtures)', type: :controller do
sign_in(admin)
end
+ describe GroupsController, '(JavaScript fixtures)', type: :controller do
+ it 'groups/edit.html.raw' do |example|
+ get :edit,
+ id: group
+
+ expect(response).to be_success
+ store_frontend_fixture(response, example.description)
+ end
+ end
+
describe Groups::Settings::CiCdController, '(JavaScript fixtures)', type: :controller do
it 'groups/ci_cd_settings.html.raw' do |example|
get :show,
diff --git a/spec/javascripts/gl_dropdown_spec.js b/spec/javascripts/gl_dropdown_spec.js
index 25b819543da..62c87642184 100644
--- a/spec/javascripts/gl_dropdown_spec.js
+++ b/spec/javascripts/gl_dropdown_spec.js
@@ -168,9 +168,9 @@ describe('glDropdown', function describeDropdown() {
it('should show loading indicator while search results are being fetched by backend', () => {
const dropdownMenu = document.querySelector('.dropdown-menu');
- expect(dropdownMenu.className.indexOf('is-loading') !== -1).toEqual(true);
+ expect(dropdownMenu.className.indexOf('is-loading')).not.toBe(-1);
remoteCallback();
- expect(dropdownMenu.className.indexOf('is-loading') !== -1).toEqual(false);
+ expect(dropdownMenu.className.indexOf('is-loading')).toBe(-1);
});
it('should not focus search input while remote task is not complete', () => {
diff --git a/spec/javascripts/graphs/stat_graph_contributors_util_spec.js b/spec/javascripts/graphs/stat_graph_contributors_util_spec.js
index 02d1ca1cc3b..8854d3d554a 100644
--- a/spec/javascripts/graphs/stat_graph_contributors_util_spec.js
+++ b/spec/javascripts/graphs/stat_graph_contributors_util_spec.js
@@ -205,10 +205,12 @@ describe("ContributorsStatGraphUtil", function () {
it("returns true if date_range is null", function () {
expect(ContributorsStatGraphUtil.in_range(date, null)).toEqual(true);
});
+
it("returns true if date is in range", function () {
var date_range = [new Date("2013-01-01"), new Date("2013-12-12")];
expect(ContributorsStatGraphUtil.in_range(date, date_range)).toEqual(true);
});
+
it("returns false if date is not in range", function () {
var date_range = [new Date("1999-12-01"), new Date("2000-12-01")];
expect(ContributorsStatGraphUtil.in_range(date, date_range)).toEqual(false);
diff --git a/spec/javascripts/groups/components/group_item_spec.js b/spec/javascripts/groups/components/group_item_spec.js
index d0cac5efc40..49d4f7efd72 100644
--- a/spec/javascripts/groups/components/group_item_spec.js
+++ b/spec/javascripts/groups/components/group_item_spec.js
@@ -45,7 +45,7 @@ describe('GroupItemComponent', () => {
expect(Object.keys(rowClass).length).toBe(classes.length);
Object.keys(rowClass).forEach((className) => {
- expect(classes.indexOf(className) > -1).toBeTruthy();
+ expect(classes.indexOf(className)).toBeGreaterThan(-1);
});
});
});
diff --git a/spec/javascripts/groups/components/groups_spec.js b/spec/javascripts/groups/components/groups_spec.js
index 793c4909d89..5af86b55532 100644
--- a/spec/javascripts/groups/components/groups_spec.js
+++ b/spec/javascripts/groups/components/groups_spec.js
@@ -53,7 +53,7 @@ describe('GroupsComponent', () => {
expect(vm.$el.querySelector('.groups-list-tree-container')).toBeDefined();
expect(vm.$el.querySelector('.group-list-tree')).toBeDefined();
expect(vm.$el.querySelector('.gl-pagination')).toBeDefined();
- expect(vm.$el.querySelectorAll('.has-no-search-results').length === 0).toBeTruthy();
+ expect(vm.$el.querySelectorAll('.has-no-search-results').length).toBe(0);
done();
});
});
diff --git a/spec/javascripts/groups/components/item_stats_spec.js b/spec/javascripts/groups/components/item_stats_spec.js
index ee7ee18259e..e6a57495eb1 100644
--- a/spec/javascripts/groups/components/item_stats_spec.js
+++ b/spec/javascripts/groups/components/item_stats_spec.js
@@ -107,7 +107,7 @@ describe('ItemStatsComponent', () => {
const visibilityIconEl = vm.$el.querySelector('.item-visibility');
expect(visibilityIconEl).not.toBe(null);
expect(visibilityIconEl.dataset.originalTitle).toBe(vm.visibilityTooltip);
- expect(visibilityIconEl.querySelectorAll('svg').length > 0).toBeTruthy();
+ expect(visibilityIconEl.querySelectorAll('svg').length).toBeGreaterThan(0);
vm.$destroy();
});
@@ -120,10 +120,10 @@ describe('ItemStatsComponent', () => {
const vm = createComponent(item);
const projectStarIconEl = vm.$el.querySelector('.project-stars');
- expect(projectStarIconEl).not.toBe(null);
- expect(projectStarIconEl.querySelectorAll('svg').length > 0).toBeTruthy();
- expect(projectStarIconEl.querySelectorAll('.stat-value').length > 0).toBeTruthy();
- expect(vm.$el.querySelectorAll('.last-updated').length > 0).toBeTruthy();
+ expect(projectStarIconEl).not.toBeNull();
+ expect(projectStarIconEl.querySelectorAll('svg').length).toBeGreaterThan(0);
+ expect(projectStarIconEl.querySelectorAll('.stat-value').length).toBeGreaterThan(0);
+ expect(vm.$el.querySelectorAll('.last-updated').length).toBeGreaterThan(0);
vm.$destroy();
});
diff --git a/spec/javascripts/groups/components/item_stats_value_spec.js b/spec/javascripts/groups/components/item_stats_value_spec.js
index 5e35ae4d36c..2a995e8efe6 100644
--- a/spec/javascripts/groups/components/item_stats_value_spec.js
+++ b/spec/javascripts/groups/components/item_stats_value_spec.js
@@ -57,8 +57,8 @@ describe('ItemStatsValueComponent', () => {
it('renders component element correctly', () => {
expect(vm.$el.classList.contains('number-subgroups')).toBeTruthy();
- expect(vm.$el.querySelectorAll('svg').length > 0).toBeTruthy();
- expect(vm.$el.querySelectorAll('.stat-value').length > 0).toBeTruthy();
+ expect(vm.$el.querySelectorAll('svg').length).toBeGreaterThan(0);
+ expect(vm.$el.querySelectorAll('.stat-value').length).toBeGreaterThan(0);
});
it('renders element tooltip correctly', () => {
diff --git a/spec/javascripts/groups/store/groups_store_spec.js b/spec/javascripts/groups/store/groups_store_spec.js
index d74f38f476e..78caf8f80bf 100644
--- a/spec/javascripts/groups/store/groups_store_spec.js
+++ b/spec/javascripts/groups/store/groups_store_spec.js
@@ -29,7 +29,7 @@ describe('ProjectsStore', () => {
store.setGroups(mockGroups);
expect(store.state.groups.length).toBe(mockGroups.length);
expect(store.formatGroupItem).toHaveBeenCalledWith(jasmine.any(Object));
- expect(Object.keys(store.state.groups[0]).indexOf('fullName') > -1).toBeTruthy();
+ expect(Object.keys(store.state.groups[0]).indexOf('fullName')).toBeGreaterThan(-1);
});
});
@@ -41,8 +41,8 @@ describe('ProjectsStore', () => {
store.setSearchedGroups(mockSearchedGroups);
expect(store.state.groups.length).toBe(mockSearchedGroups.length);
expect(store.formatGroupItem).toHaveBeenCalledWith(jasmine.any(Object));
- expect(Object.keys(store.state.groups[0]).indexOf('fullName') > -1).toBeTruthy();
- expect(Object.keys(store.state.groups[0].children[0]).indexOf('fullName') > -1).toBeTruthy();
+ expect(Object.keys(store.state.groups[0]).indexOf('fullName')).toBeGreaterThan(-1);
+ expect(Object.keys(store.state.groups[0].children[0]).indexOf('fullName')).toBeGreaterThan(-1);
});
});
@@ -54,7 +54,7 @@ describe('ProjectsStore', () => {
store.setGroupChildren(mockParentGroupItem, mockRawChildren);
expect(store.formatGroupItem).toHaveBeenCalledWith(jasmine.any(Object));
expect(mockParentGroupItem.children.length).toBe(1);
- expect(Object.keys(mockParentGroupItem.children[0]).indexOf('fullName') > -1).toBeTruthy();
+ expect(Object.keys(mockParentGroupItem.children[0]).indexOf('fullName')).toBeGreaterThan(-1);
expect(mockParentGroupItem.isOpen).toBeTruthy();
expect(mockParentGroupItem.isChildrenLoading).toBeFalsy();
});
@@ -81,14 +81,14 @@ describe('ProjectsStore', () => {
store = new GroupsStore();
updatedGroupItem = store.formatGroupItem(mockRawChildren[0]);
- expect(Object.keys(updatedGroupItem).indexOf('fullName') > -1).toBeTruthy();
+ expect(Object.keys(updatedGroupItem).indexOf('fullName')).toBeGreaterThan(-1);
expect(updatedGroupItem.childrenCount).toBe(mockRawChildren[0].children_count);
expect(updatedGroupItem.isChildrenLoading).toBe(false);
expect(updatedGroupItem.isBeingRemoved).toBe(false);
store = new GroupsStore(true);
updatedGroupItem = store.formatGroupItem(mockRawChildren[0]);
- expect(Object.keys(updatedGroupItem).indexOf('fullName') > -1).toBeTruthy();
+ expect(Object.keys(updatedGroupItem).indexOf('fullName')).toBeGreaterThan(-1);
expect(updatedGroupItem.childrenCount).toBe(mockRawChildren[0].subgroup_count);
});
});
diff --git a/spec/javascripts/image_diff/helpers/comment_indicator_helper_spec.js b/spec/javascripts/image_diff/helpers/comment_indicator_helper_spec.js
index a284b981d2a..9d05c6859df 100644
--- a/spec/javascripts/image_diff/helpers/comment_indicator_helper_spec.js
+++ b/spec/javascripts/image_diff/helpers/comment_indicator_helper_spec.js
@@ -32,7 +32,7 @@ describe('commentIndicatorHelper', () => {
expect(svgEl).toBeDefined();
const svgLink = svgEl.querySelector('use').getAttribute('xlink:href');
- expect(svgLink.indexOf('image-comment-dark') !== -1).toEqual(true);
+ expect(svgLink.indexOf('image-comment-dark')).not.toBe(-1);
});
});
});
diff --git a/spec/javascripts/jobs/components/job_app_spec.js b/spec/javascripts/jobs/components/job_app_spec.js
index e02eb9723fe..6e0bcf801cd 100644
--- a/spec/javascripts/jobs/components/job_app_spec.js
+++ b/spec/javascripts/jobs/components/job_app_spec.js
@@ -41,7 +41,7 @@ describe('Job App ', () => {
};
const props = {
- runnerHelpUrl: 'help/runners',
+ runnerSettingsUrl: 'settings/ci-cd/runners',
};
beforeEach(() => {
@@ -223,7 +223,6 @@ describe('Job App ', () => {
store.dispatch(
'receiveJobSuccess',
Object.assign({}, job, {
- erased: true,
erased_by: {
username: 'root',
web_url: 'gitlab.com/root',
@@ -237,18 +236,18 @@ describe('Job App ', () => {
store,
});
- expect(vm.$el.querySelector('.js-job-erased')).not.toBeNull();
+ expect(vm.$el.querySelector('.js-job-erased-block')).not.toBeNull();
});
it('does not render erased block when `erased` is false', () => {
- store.dispatch('receiveJobSuccess', Object.assign({}, job, { erased: false }));
+ store.dispatch('receiveJobSuccess', Object.assign({}, job, { erased_at: null }));
vm = mountComponentWithStore(Component, {
props,
store,
});
- expect(vm.$el.querySelector('.js-job-erased')).toBeNull();
+ expect(vm.$el.querySelector('.js-job-erased-block')).toBeNull();
});
});
diff --git a/spec/javascripts/jobs/components/job_log_controllers_spec.js b/spec/javascripts/jobs/components/job_log_controllers_spec.js
index 099aca602c4..3dcb57d23ce 100644
--- a/spec/javascripts/jobs/components/job_log_controllers_spec.js
+++ b/spec/javascripts/jobs/components/job_log_controllers_spec.js
@@ -25,6 +25,7 @@ describe('Job log controllers', () => {
beforeEach(() => {
vm = mountComponent(Component, props);
});
+
it('renders size information', () => {
expect(vm.$el.querySelector('.js-truncated-info').textContent).toContain('499.95 KiB');
});
diff --git a/spec/javascripts/jobs/components/sidebar_spec.js b/spec/javascripts/jobs/components/sidebar_spec.js
index 2f5c4245ced..a113377b19f 100644
--- a/spec/javascripts/jobs/components/sidebar_spec.js
+++ b/spec/javascripts/jobs/components/sidebar_spec.js
@@ -161,9 +161,9 @@ describe('Sidebar details block', () => {
vm = mountComponentWithStore(SidebarComponent, { store });
});
- it('renders first stage as selected', () => {
+ it('renders value provided as selectedStage as selected', () => {
expect(vm.$el.querySelector('.js-selected-stage').textContent.trim()).toEqual(
- stages[0].name,
+ vm.selectedStage,
);
});
});
diff --git a/spec/javascripts/jobs/components/stages_dropdown_spec.js b/spec/javascripts/jobs/components/stages_dropdown_spec.js
index aa6cc0f1b1a..fcff78b943e 100644
--- a/spec/javascripts/jobs/components/stages_dropdown_spec.js
+++ b/spec/javascripts/jobs/components/stages_dropdown_spec.js
@@ -2,7 +2,7 @@ import Vue from 'vue';
import component from '~/jobs/components/stages_dropdown.vue';
import mountComponent from '../../helpers/vue_mount_component_helper';
-describe('Artifacts block', () => {
+describe('Stages Dropdown', () => {
const Component = Vue.extend(component);
let vm;
@@ -23,10 +23,6 @@ describe('Artifacts block', () => {
},
path: 'pipeline/28029444',
},
- ref: {
- path: 'commits/50101-truncated-job-information',
- name: '50101-truncated-job-information',
- },
stages: [
{
name: 'build',
@@ -35,6 +31,7 @@ describe('Artifacts block', () => {
name: 'test',
},
],
+ selectedStage: 'deploy'
});
});
@@ -53,17 +50,10 @@ describe('Artifacts block', () => {
});
it('renders dropdown with stages', () => {
- expect(vm.$el.querySelector('.dropdown button').textContent).toContain('build');
+ expect(vm.$el.querySelector('.dropdown .js-stage-item').textContent).toContain('build');
});
- it('updates selected stage on click', done => {
- vm.$el.querySelectorAll('.stage-item')[1].click();
- vm
- .$nextTick()
- .then(() => {
- expect(vm.$el.querySelector('.dropdown button').textContent).toContain('test');
- })
- .then(done)
- .catch(done.fail);
+ it('rendes selected stage', () => {
+ expect(vm.$el.querySelector('.dropdown .js-selected-stage').textContent).toContain('deploy');
});
});
diff --git a/spec/javascripts/jobs/store/actions_spec.js b/spec/javascripts/jobs/store/actions_spec.js
index 5ab1f75d0d6..bc410ae614c 100644
--- a/spec/javascripts/jobs/store/actions_spec.js
+++ b/spec/javascripts/jobs/store/actions_spec.js
@@ -422,8 +422,9 @@ describe('Job State actions', () => {
beforeEach(() => {
mockedState.job.pipeline = {
- path: `${TEST_HOST}/endpoint.json/stages`,
+ path: `${TEST_HOST}/endpoint`,
};
+ mockedState.selectedStage = 'deploy'
mock = new MockAdapter(axios);
});
@@ -434,8 +435,8 @@ describe('Job State actions', () => {
describe('success', () => {
it('dispatches requestStages and receiveStagesSuccess, fetchJobsForStage ', done => {
mock
- .onGet(`${TEST_HOST}/endpoint.json/stages`)
- .replyOnce(200, { details: { stages: [{ id: 121212, name: 'build' }] } });
+ .onGet(`${TEST_HOST}/endpoint.json`)
+ .replyOnce(200, { details: { stages: [{ name: 'build' }, { name: 'deploy' }] } });
testAction(
fetchStages,
@@ -447,11 +448,11 @@ describe('Job State actions', () => {
type: 'requestStages',
},
{
- payload: [{ id: 121212, name: 'build' }],
+ payload: [{ name: 'build' }, { name: 'deploy' }],
type: 'receiveStagesSuccess',
},
{
- payload: { id: 121212, name: 'build' },
+ payload: { name: 'deploy' },
type: 'fetchJobsForStage',
},
],
@@ -515,9 +516,9 @@ describe('Job State actions', () => {
it('should commit REQUEST_JOBS_FOR_STAGE mutation ', done => {
testAction(
requestJobsForStage,
- null,
+ { name: 'deploy' },
mockedState,
- [{ type: types.REQUEST_JOBS_FOR_STAGE }],
+ [{ type: types.REQUEST_JOBS_FOR_STAGE, payload: { name: 'deploy' } }],
[],
done,
);
@@ -549,6 +550,7 @@ describe('Job State actions', () => {
[
{
type: 'requestJobsForStage',
+ payload: { dropdown_path: `${TEST_HOST}/jobs.json` },
},
{
payload: [{ id: 121212, name: 'build' }],
@@ -574,6 +576,7 @@ describe('Job State actions', () => {
[
{
type: 'requestJobsForStage',
+ payload: { dropdown_path: `${TEST_HOST}/jobs.json` },
},
{
type: 'receiveJobsForStageError',
diff --git a/spec/javascripts/jobs/store/getters_spec.js b/spec/javascripts/jobs/store/getters_spec.js
index 160b2f4b34a..e262a47b837 100644
--- a/spec/javascripts/jobs/store/getters_spec.js
+++ b/spec/javascripts/jobs/store/getters_spec.js
@@ -77,18 +77,18 @@ describe('Job Store Getters', () => {
});
});
- describe('jobHasStarted', () => {
- describe('when started equals false', () => {
+ describe('shouldRenderTriggeredLabel', () => {
+ describe('when started equals null', () => {
it('returns false', () => {
- localState.job.started = false;
- expect(getters.jobHasStarted(localState)).toEqual(false);
+ localState.job.started = null;
+ expect(getters.shouldRenderTriggeredLabel(localState)).toEqual(false);
});
});
describe('when started equals string', () => {
it('returns true', () => {
localState.job.started = '2018-08-31T16:20:49.023Z';
- expect(getters.jobHasStarted(localState)).toEqual(true);
+ expect(getters.shouldRenderTriggeredLabel(localState)).toEqual(true);
});
});
});
diff --git a/spec/javascripts/jobs/store/mutations_spec.js b/spec/javascripts/jobs/store/mutations_spec.js
index 9ba543d32a8..701fcc7f4c8 100644
--- a/spec/javascripts/jobs/store/mutations_spec.js
+++ b/spec/javascripts/jobs/store/mutations_spec.js
@@ -108,21 +108,33 @@ describe('Jobs Store Mutations', () => {
});
describe('RECEIVE_JOB_SUCCESS', () => {
- beforeEach(() => {
- mutations[types.RECEIVE_JOB_SUCCESS](stateCopy, { id: 1312321 });
- });
-
it('sets is loading to false', () => {
+ mutations[types.RECEIVE_JOB_SUCCESS](stateCopy, { id: 1312321 });
expect(stateCopy.isLoading).toEqual(false);
});
it('sets hasError to false', () => {
+ mutations[types.RECEIVE_JOB_SUCCESS](stateCopy, { id: 1312321 });
expect(stateCopy.hasError).toEqual(false);
});
it('sets job data', () => {
+ mutations[types.RECEIVE_JOB_SUCCESS](stateCopy, { id: 1312321 });
expect(stateCopy.job).toEqual({ id: 1312321 });
});
+
+ it('sets selectedStage when the selectedStage is More', () => {
+ expect(stateCopy.selectedStage).toEqual('More');
+ mutations[types.RECEIVE_JOB_SUCCESS](stateCopy, { id: 1312321, stage: 'deploy' });
+ expect(stateCopy.selectedStage).toEqual('deploy');
+ });
+
+ it('does not set selectedStage when the selectedStage is not More', () => {
+ stateCopy.selectedStage = 'notify'
+ expect(stateCopy.selectedStage).toEqual('notify');
+ mutations[types.RECEIVE_JOB_SUCCESS](stateCopy, { id: 1312321, stage: 'deploy' });
+ expect(stateCopy.selectedStage).toEqual('notify');
+ });
});
describe('RECEIVE_JOB_ERROR', () => {
@@ -200,9 +212,14 @@ describe('Jobs Store Mutations', () => {
describe('REQUEST_JOBS_FOR_STAGE', () => {
it('sets isLoadingStages to true', () => {
- mutations[types.REQUEST_JOBS_FOR_STAGE](stateCopy);
+ mutations[types.REQUEST_JOBS_FOR_STAGE](stateCopy, { name: 'deploy' });
expect(stateCopy.isLoadingJobs).toEqual(true);
});
+
+ it('sets selectedStage', () => {
+ mutations[types.REQUEST_JOBS_FOR_STAGE](stateCopy, { name: 'deploy' });
+ expect(stateCopy.selectedStage).toEqual('deploy');
+ })
});
describe('RECEIVE_JOBS_FOR_STAGE_SUCCESS', () => {
diff --git a/spec/javascripts/lib/utils/common_utils_spec.js b/spec/javascripts/lib/utils/common_utils_spec.js
index 28151c7e658..c34622203f7 100644
--- a/spec/javascripts/lib/utils/common_utils_spec.js
+++ b/spec/javascripts/lib/utils/common_utils_spec.js
@@ -9,6 +9,7 @@ describe('common_utils', () => {
it('returns an anchor tag with url', () => {
expect(commonUtils.parseUrl('/some/absolute/url').pathname).toContain('some/absolute/url');
});
+
it('url is escaped', () => {
// IE11 will return a relative pathname while other browsers will return a full pathname.
// parseUrl uses an anchor element for parsing an url. With relative urls, the anchor
@@ -42,7 +43,7 @@ describe('common_utils', () => {
it('should remove the question mark from the search params', () => {
const paramsArray = commonUtils.urlParamsToArray('?test=thing');
- expect(paramsArray[0][0] !== '?').toBe(true);
+ expect(paramsArray[0][0]).not.toBe('?');
});
});
diff --git a/spec/javascripts/line_highlighter_spec.js b/spec/javascripts/line_highlighter_spec.js
index c32ecb17e89..15bb78032b2 100644
--- a/spec/javascripts/line_highlighter_spec.js
+++ b/spec/javascripts/line_highlighter_spec.js
@@ -23,17 +23,20 @@ import LineHighlighter from '~/line_highlighter';
__setLocationHash__: spyOn(this["class"], '__setLocationHash__').and.callFake(function() {})
};
});
+
describe('behavior', function() {
it('highlights one line given in the URL hash', function() {
new LineHighlighter({ hash: '#L13' });
return expect($('#LC13')).toHaveClass(this.css);
});
+
it('highlights one line given in the URL hash with given CSS class name', function() {
const hiliter = new LineHighlighter({ hash: '#L13', highlightLineClass: 'hilite' });
expect(hiliter.highlightLineClass).toBe('hilite');
expect($('#LC13')).toHaveClass('hilite');
expect($('#LC13')).not.toHaveClass('hll');
});
+
it('highlights a range of lines given in the URL hash', function() {
var line, results;
new LineHighlighter({ hash: '#L5-25' });
@@ -44,18 +47,21 @@ import LineHighlighter from '~/line_highlighter';
}
return results;
});
+
it('scrolls to the first highlighted line on initial load', function() {
var spy;
spy = spyOn($, 'scrollTo');
new LineHighlighter({ hash: '#L5-25' });
return expect(spy).toHaveBeenCalledWith('#L5', jasmine.anything());
});
+
it('discards click events', function() {
var spy;
spy = spyOnEvent('a[data-line-number]', 'click');
clickLine(13);
return expect(spy).toHaveBeenPrevented();
});
+
it('handles garbage input from the hash', function() {
var func;
func = function() {
@@ -64,6 +70,7 @@ import LineHighlighter from '~/line_highlighter';
return expect(func).not.toThrow();
});
});
+
describe('clickHandler', function() {
it('handles clicking on a child icon element', function() {
var spy;
@@ -72,11 +79,13 @@ import LineHighlighter from '~/line_highlighter';
expect(spy).toHaveBeenCalledWith(13);
return expect($('#LC13')).toHaveClass(this.css);
});
+
describe('without shiftKey', function() {
it('highlights one line when clicked', function() {
clickLine(13);
return expect($('#LC13')).toHaveClass(this.css);
});
+
it('unhighlights previously highlighted lines', function() {
clickLine(13);
clickLine(20);
@@ -101,6 +110,7 @@ import LineHighlighter from '~/line_highlighter';
expect(spy).toHaveBeenCalledWith(13);
return expect(spy).toHaveBeenCalledWith(13, 20);
});
+
describe('without existing highlight', function() {
it('highlights the clicked line', function() {
clickLine(13, {
@@ -118,6 +128,7 @@ import LineHighlighter from '~/line_highlighter';
return expect(spy).toHaveBeenCalledWith(13);
});
});
+
describe('with existing single-line highlight', function() {
it('uses existing line as last line when target is lesser', function() {
var line, results;
@@ -155,6 +166,7 @@ import LineHighlighter from '~/line_highlighter';
shiftKey: true
});
});
+
it('uses target as first line when it is less than existing first line', function() {
var line, results;
clickLine(5, {
@@ -182,13 +194,16 @@ import LineHighlighter from '~/line_highlighter';
});
});
});
+
describe('hashToRange', function() {
beforeEach(function() {
return this.subject = this["class"].hashToRange;
});
+
it('extracts a single line number from the hash', function() {
return expect(this.subject('#L5')).toEqual([5, null]);
});
+
it('extracts a range of line numbers from the hash', function() {
return expect(this.subject('#L5-15')).toEqual([5, 15]);
});
@@ -196,10 +211,12 @@ import LineHighlighter from '~/line_highlighter';
return expect(this.subject('#foo')).toEqual([null, null]);
});
});
+
describe('highlightLine', function() {
beforeEach(function() {
return this.subject = this["class"].highlightLine;
});
+
it('highlights the specified line', function() {
this.subject(13);
return expect($('#LC13')).toHaveClass(this.css);
@@ -213,6 +230,7 @@ import LineHighlighter from '~/line_highlighter';
beforeEach(function() {
return this.subject = this["class"].setHash;
});
+
it('sets the location hash for a single line', function() {
this.subject(5);
return expect(this.spies.__setLocationHash__).toHaveBeenCalledWith('#L5');
diff --git a/spec/javascripts/new_branch_spec.js b/spec/javascripts/new_branch_spec.js
index e52ac686435..85419e640d8 100644
--- a/spec/javascripts/new_branch_spec.js
+++ b/spec/javascripts/new_branch_spec.js
@@ -21,18 +21,22 @@ import NewBranchForm from '~/new_branch_form';
});
return this.form = new NewBranchForm($('.js-create-branch-form'), []);
});
+
it("can't start with a dot", function() {
fillNameWith('.foo');
return expectToHaveError("can't start with '.'");
});
+
it("can't start with a slash", function() {
fillNameWith('/foo');
return expectToHaveError("can't start with '/'");
});
+
it("can't have two consecutive dots", function() {
fillNameWith('foo..bar');
return expectToHaveError("can't contain '..'");
});
+
it("can't have spaces anywhere", function() {
fillNameWith(' foo');
expectToHaveError("can't contain spaces");
@@ -41,6 +45,7 @@ import NewBranchForm from '~/new_branch_form';
fillNameWith('foo ');
return expectToHaveError("can't contain spaces");
});
+
it("can't have ~ anywhere", function() {
fillNameWith('~foo');
expectToHaveError("can't contain '~'");
@@ -49,6 +54,7 @@ import NewBranchForm from '~/new_branch_form';
fillNameWith('foo~');
return expectToHaveError("can't contain '~'");
});
+
it("can't have tilde anwhere", function() {
fillNameWith('~foo');
expectToHaveError("can't contain '~'");
@@ -57,6 +63,7 @@ import NewBranchForm from '~/new_branch_form';
fillNameWith('foo~');
return expectToHaveError("can't contain '~'");
});
+
it("can't have caret anywhere", function() {
fillNameWith('^foo');
expectToHaveError("can't contain '^'");
@@ -65,6 +72,7 @@ import NewBranchForm from '~/new_branch_form';
fillNameWith('foo^');
return expectToHaveError("can't contain '^'");
});
+
it("can't have : anywhere", function() {
fillNameWith(':foo');
expectToHaveError("can't contain ':'");
@@ -73,6 +81,7 @@ import NewBranchForm from '~/new_branch_form';
fillNameWith(':foo');
return expectToHaveError("can't contain ':'");
});
+
it("can't have question mark anywhere", function() {
fillNameWith('?foo');
expectToHaveError("can't contain '?'");
@@ -81,6 +90,7 @@ import NewBranchForm from '~/new_branch_form';
fillNameWith('foo?');
return expectToHaveError("can't contain '?'");
});
+
it("can't have asterisk anywhere", function() {
fillNameWith('*foo');
expectToHaveError("can't contain '*'");
@@ -89,6 +99,7 @@ import NewBranchForm from '~/new_branch_form';
fillNameWith('foo*');
return expectToHaveError("can't contain '*'");
});
+
it("can't have open bracket anywhere", function() {
fillNameWith('[foo');
expectToHaveError("can't contain '['");
@@ -97,6 +108,7 @@ import NewBranchForm from '~/new_branch_form';
fillNameWith('foo[');
return expectToHaveError("can't contain '['");
});
+
it("can't have a backslash anywhere", function() {
fillNameWith('\\foo');
expectToHaveError("can't contain '\\'");
@@ -105,6 +117,7 @@ import NewBranchForm from '~/new_branch_form';
fillNameWith('foo\\');
return expectToHaveError("can't contain '\\'");
});
+
it("can't contain a sequence @{ anywhere", function() {
fillNameWith('@{foo');
expectToHaveError("can't contain '@{'");
@@ -113,48 +126,59 @@ import NewBranchForm from '~/new_branch_form';
fillNameWith('foo@{');
return expectToHaveError("can't contain '@{'");
});
+
it("can't have consecutive slashes", function() {
fillNameWith('foo//bar');
return expectToHaveError("can't contain consecutive slashes");
});
+
it("can't end with a slash", function() {
fillNameWith('foo/');
return expectToHaveError("can't end in '/'");
});
+
it("can't end with a dot", function() {
fillNameWith('foo.');
return expectToHaveError("can't end in '.'");
});
+
it("can't end with .lock", function() {
fillNameWith('foo.lock');
return expectToHaveError("can't end in '.lock'");
});
+
it("can't be the single character @", function() {
fillNameWith('@');
return expectToHaveError("can't be '@'");
});
+
it("concatenates all error messages", function() {
fillNameWith('/foo bar?~.');
return expectToHaveError("can't start with '/', can't contain spaces, '?', '~', can't end in '.'");
});
+
it("doesn't duplicate error messages", function() {
fillNameWith('?foo?bar?zoo?');
return expectToHaveError("can't contain '?'");
});
+
it("removes the error message when is a valid name", function() {
fillNameWith('foo?bar');
expect($('.js-branch-name-error span').length).toEqual(1);
fillNameWith('foobar');
return expect($('.js-branch-name-error span').length).toEqual(0);
});
+
it("can have dashes anywhere", function() {
fillNameWith('-foo-bar-zoo-');
return expect($('.js-branch-name-error span').length).toEqual(0);
});
+
it("can have underscores anywhere", function() {
fillNameWith('_foo_bar_zoo_');
return expect($('.js-branch-name-error span').length).toEqual(0);
});
+
it("can have numbers anywhere", function() {
fillNameWith('1foo2bar3zoo4');
return expect($('.js-branch-name-error span').length).toEqual(0);
diff --git a/spec/javascripts/notes/components/note_form_spec.js b/spec/javascripts/notes/components/note_form_spec.js
index 147ffcf1b81..eefd9ddd63c 100644
--- a/spec/javascripts/notes/components/note_form_spec.js
+++ b/spec/javascripts/notes/components/note_form_spec.js
@@ -100,6 +100,7 @@ describe('issue_note_form component', () => {
expect(vm.handleUpdate).toHaveBeenCalled();
});
+
it('should save note when ctrl+enter is pressed', () => {
spyOn(vm, 'handleUpdate').and.callThrough();
vm.$el.querySelector('textarea').value = 'Foo';
diff --git a/spec/javascripts/notes_spec.js b/spec/javascripts/notes_spec.js
index faeedae40e9..7bfbca83c77 100644
--- a/spec/javascripts/notes_spec.js
+++ b/spec/javascripts/notes_spec.js
@@ -538,7 +538,7 @@ import timeoutPromise from './helpers/set_timeout_promise_helper';
mockNotesPost();
$('.js-comment-button').click();
- expect($notesContainer.find('.note.being-posted').length > 0).toEqual(true);
+ expect($notesContainer.find('.note.being-posted').length).toBeGreaterThan(0);
});
it('should remove placeholder note when new comment is done posting', done => {
@@ -582,7 +582,7 @@ import timeoutPromise from './helpers/set_timeout_promise_helper';
$('.js-comment-button').click();
setTimeout(() => {
- expect($notesContainer.find(`#note_${note.id}`).length > 0).toEqual(true);
+ expect($notesContainer.find(`#note_${note.id}`).length).toBeGreaterThan(0);
done();
});
@@ -776,7 +776,7 @@ import timeoutPromise from './helpers/set_timeout_promise_helper';
$form.find('textarea.js-note-text').val(sampleComment);
const { formData, formContent, formAction } = this.notes.getFormData($form);
- expect(formData.indexOf(sampleComment) > -1).toBe(true);
+ expect(formData.indexOf(sampleComment)).toBeGreaterThan(-1);
expect(formContent).toEqual(sampleComment);
expect(formAction).toEqual($form.attr('action'));
});
diff --git a/spec/javascripts/reports/components/report_section_spec.js b/spec/javascripts/reports/components/report_section_spec.js
index 6f6eb161d14..bf11dbea386 100644
--- a/spec/javascripts/reports/components/report_section_spec.js
+++ b/spec/javascripts/reports/components/report_section_spec.js
@@ -86,6 +86,7 @@ describe('Report section', () => {
});
});
});
+
describe('when it is loading', () => {
it('should render loading indicator', () => {
vm = mountComponent(ReportSection, {
diff --git a/spec/javascripts/right_sidebar_spec.js b/spec/javascripts/right_sidebar_spec.js
index f9395eedfea..43e4db4c712 100644
--- a/spec/javascripts/right_sidebar_spec.js
+++ b/spec/javascripts/right_sidebar_spec.js
@@ -1,4 +1,4 @@
-/* eslint-disable no-var, one-var, no-return-assign, vars-on-top, jasmine/no-unsafe-spy */
+/* eslint-disable no-var, one-var, no-return-assign, vars-on-top */
import $ from 'jquery';
import MockAdapter from 'axios-mock-adapter';
@@ -60,10 +60,12 @@ import Sidebar from '~/right_sidebar';
$toggle.click();
assertSidebarState('expanded');
});
+
it('should float over the page and when sidebar icons clicked', function() {
$labelsIcon.click();
return assertSidebarState('expanded');
});
+
it('should collapse when the icon arrow clicked while it is floating on page', function() {
$labelsIcon.click();
assertSidebarState('expanded');
@@ -92,33 +94,5 @@ import Sidebar from '~/right_sidebar';
});
});
});
-
- describe('sidebarToggleClicked', () => {
- const event = jasmine.createSpyObj('event', ['preventDefault']);
-
- beforeEach(() => {
- spyOn($.fn, 'hasClass').and.returnValue(false);
- });
-
- afterEach(() => {
- gl.lazyLoader = undefined;
- });
-
- it('calls loadCheck if lazyLoader is set', () => {
- gl.lazyLoader = jasmine.createSpyObj('lazyLoader', ['loadCheck']);
-
- Sidebar.prototype.sidebarToggleClicked(event);
-
- expect(gl.lazyLoader.loadCheck).toHaveBeenCalled();
- });
-
- it('does not throw if lazyLoader is not defined', () => {
- gl.lazyLoader = undefined;
-
- const toggle = Sidebar.prototype.sidebarToggleClicked.bind(null, event);
-
- expect(toggle).not.toThrow();
- });
- });
});
}).call(window);
diff --git a/spec/javascripts/search_autocomplete_spec.js b/spec/javascripts/search_autocomplete_spec.js
index b96023a33c4..bc1bb50dc5c 100644
--- a/spec/javascripts/search_autocomplete_spec.js
+++ b/spec/javascripts/search_autocomplete_spec.js
@@ -140,6 +140,7 @@ describe('Search autocomplete dropdown', () => {
removeBodyAttributes();
window.gon = {};
});
+
it('should show Dashboard specific dropdown menu', function() {
var list;
addBodyAttributes();
@@ -148,6 +149,7 @@ describe('Search autocomplete dropdown', () => {
list = widget.wrap.find('.dropdown-menu').find('ul');
return assertLinks(list, dashboardIssuesPath, dashboardMRsPath);
});
+
it('should show Group specific dropdown menu', function() {
var list;
addBodyAttributes('group');
@@ -156,6 +158,7 @@ describe('Search autocomplete dropdown', () => {
list = widget.wrap.find('.dropdown-menu').find('ul');
return assertLinks(list, groupIssuesPath, groupMRsPath);
});
+
it('should show Project specific dropdown menu', function() {
var list;
addBodyAttributes('project');
@@ -164,6 +167,7 @@ describe('Search autocomplete dropdown', () => {
list = widget.wrap.find('.dropdown-menu').find('ul');
return assertLinks(list, projectIssuesPath, projectMRsPath);
});
+
it('should show only Project mergeRequest dropdown menu items when project issues are disabled', function() {
addBodyAttributes('project');
disableProjectIssues();
@@ -172,6 +176,7 @@ describe('Search autocomplete dropdown', () => {
const list = widget.wrap.find('.dropdown-menu').find('ul');
assertLinks(list, null, projectMRsPath);
});
+
it('should not show category related menu if there is text in the input', function() {
var link, list;
addBodyAttributes('project');
@@ -182,6 +187,7 @@ describe('Search autocomplete dropdown', () => {
link = "a[href='" + projectIssuesPath + '/?assignee_id=' + userId + "']";
return expect(list.find(link).length).toBe(0);
});
+
it('should not submit the search form when selecting an autocomplete row with the keyboard', function() {
var ENTER = 13;
var DOWN = 40;
diff --git a/spec/javascripts/settings_panels_spec.js b/spec/javascripts/settings_panels_spec.js
index c1a69bd7018..3b681a9ff28 100644
--- a/spec/javascripts/settings_panels_spec.js
+++ b/spec/javascripts/settings_panels_spec.js
@@ -1,10 +1,11 @@
+import $ from 'jquery';
import initSettingsPanels from '~/settings_panels';
describe('Settings Panels', () => {
- preloadFixtures('projects/ci_cd_settings.html.raw');
+ preloadFixtures('groups/edit.html.raw');
beforeEach(() => {
- loadFixtures('projects/ci_cd_settings.html.raw');
+ loadFixtures('groups/edit.html.raw');
});
describe('initSettingsPane', () => {
@@ -13,17 +14,32 @@ describe('Settings Panels', () => {
});
it('should expand linked hash fragment panel', () => {
- window.location.hash = '#autodevops-settings';
+ window.location.hash = '#js-general-settings';
- const pipelineSettingsPanel = document.querySelector('#autodevops-settings');
+ const panel = document.querySelector('#js-general-settings');
// Our test environment automatically expands everything so we need to clear that out first
- pipelineSettingsPanel.classList.remove('expanded');
+ panel.classList.remove('expanded');
- expect(pipelineSettingsPanel.classList.contains('expanded')).toBe(false);
+ expect(panel.classList.contains('expanded')).toBe(false);
initSettingsPanels();
- expect(pipelineSettingsPanel.classList.contains('expanded')).toBe(true);
+ expect(panel.classList.contains('expanded')).toBe(true);
});
});
+
+ it('does not change the text content of triggers', () => {
+ const panel = document.querySelector('#js-general-settings');
+ const trigger = panel.querySelector('.js-settings-toggle-trigger-only');
+ const originalText = trigger.textContent;
+
+ initSettingsPanels();
+
+ expect(panel.classList.contains('expanded')).toBe(true);
+
+ $(trigger).click();
+
+ expect(panel.classList.contains('expanded')).toBe(false);
+ expect(trigger.textContent).toEqual(originalText);
+ });
});
diff --git a/spec/javascripts/syntax_highlight_spec.js b/spec/javascripts/syntax_highlight_spec.js
index af3a5d58ba7..512be88c24c 100644
--- a/spec/javascripts/syntax_highlight_spec.js
+++ b/spec/javascripts/syntax_highlight_spec.js
@@ -25,6 +25,7 @@ describe('Syntax Highlighter', function() {
beforeEach(function() {
return setFixtures("<div class=\"parent\">\n <div class=\"js-syntax-highlight\"></div>\n <div class=\"foo\"></div>\n <div class=\"js-syntax-highlight\"></div>\n</div>");
});
+
it('applies highlighting to all applicable children', function() {
stubUserColorScheme('monokai');
syntaxHighlight($('.parent'));
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_memory_usage_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_memory_usage_spec.js
index 91e81a0675a..305cee94f57 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_memory_usage_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_memory_usage_spec.js
@@ -137,7 +137,7 @@ describe('MemoryUsage', () => {
} = vm;
expect(hasMetrics).toBeTruthy();
- expect(memoryMetrics.length > 0).toBeTruthy();
+ expect(memoryMetrics.length).toBeGreaterThan(0);
expect(deploymentTime).toEqual(deployment_time);
expect(memoryFrom).toEqual('9.13');
expect(memoryTo).toEqual('4.28');
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js
index efa5c878678..033cb694249 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js
@@ -157,6 +157,16 @@ describe('MRWidgetMerged', () => {
expect(selectors.copyMergeShaButton.getAttribute('data-clipboard-text')).toBe(vm.mr.mergeCommitSha);
});
+ it('hides button to copy commit SHA if SHA does not exist', (done) => {
+ vm.mr.mergeCommitSha = null;
+
+ Vue.nextTick(() => {
+ expect(selectors.copyMergeShaButton).not.toExist();
+ expect(vm.$el.querySelector('.mr-info-list').innerText).not.toContain('with');
+ done();
+ });
+ });
+
it('shows merge commit SHA link', () => {
expect(selectors.mergeCommitShaLink).toExist();
expect(selectors.mergeCommitShaLink.text).toContain(vm.mr.shortMergeCommitSha);
diff --git a/spec/javascripts/vue_shared/components/memory_graph_spec.js b/spec/javascripts/vue_shared/components/memory_graph_spec.js
index 65d8ed39ade..0982b3e1f38 100644
--- a/spec/javascripts/vue_shared/components/memory_graph_spec.js
+++ b/spec/javascripts/vue_shared/components/memory_graph_spec.js
@@ -52,8 +52,8 @@ describe('MemoryGraph', () => {
it('should show human readable median value based on provided median timestamp', () => {
vm.deploymentTime = mockMedian;
const formattedMedian = vm.getFormattedMedian;
- expect(formattedMedian.indexOf('Deployed') > -1).toBeTruthy();
- expect(formattedMedian.indexOf('ago') > -1).toBeTruthy();
+ expect(formattedMedian.indexOf('Deployed')).toBeGreaterThan(-1);
+ expect(formattedMedian.indexOf('ago')).toBeGreaterThan(-1);
});
});
});
diff --git a/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb b/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb
index ed6fa3d229f..e2bee22cf1f 100644
--- a/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb
+++ b/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb
@@ -11,7 +11,7 @@ describe Gitlab::BitbucketImport::ProjectCreator do
owner: "asd",
full_name: 'Vim repo',
visibility_level: Gitlab::VisibilityLevel::PRIVATE,
- clone_url: 'ssh://git@bitbucket.org/asd/vim.git',
+ clone_url: 'http://bitbucket.org/asd/vim.git',
has_wiki?: false)
end
@@ -32,7 +32,7 @@ describe Gitlab::BitbucketImport::ProjectCreator do
project_creator = described_class.new(repo, 'vim', namespace, user, access_params)
project = project_creator.execute
- expect(project.import_url).to eq("ssh://git@bitbucket.org/asd/vim.git")
+ expect(project.import_url).to eq("http://bitbucket.org/asd/vim.git")
expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
end
end
diff --git a/spec/lib/gitlab/blob_helper_spec.rb b/spec/lib/gitlab/blob_helper_spec.rb
new file mode 100644
index 00000000000..0b56f8687c3
--- /dev/null
+++ b/spec/lib/gitlab/blob_helper_spec.rb
@@ -0,0 +1,125 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::BlobHelper do
+ include FakeBlobHelpers
+
+ let(:project) { create(:project) }
+ let(:blob) { fake_blob(path: 'file.txt') }
+ let(:large_blob) { fake_blob(path: 'test.pdf', size: 2.megabytes, binary: true) }
+
+ describe '#extname' do
+ it 'returns the extension' do
+ expect(blob.extname).to eq('.txt')
+ end
+ end
+
+ describe '#known_extension?' do
+ it 'returns true' do
+ expect(blob.known_extension?).to be_truthy
+ end
+ end
+
+ describe '#viewable' do
+ it 'returns true' do
+ expect(blob.viewable?).to be_truthy
+ end
+
+ it 'returns false' do
+ expect(large_blob.viewable?).to be_falsey
+ end
+ end
+
+ describe '#large?' do
+ it 'returns false' do
+ expect(blob.large?).to be_falsey
+ end
+
+ it 'returns true' do
+ expect(large_blob.large?).to be_truthy
+ end
+ end
+
+ describe '#binary?' do
+ it 'returns true' do
+ expect(large_blob.binary?).to be_truthy
+ end
+
+ it 'returns false' do
+ expect(blob.binary?).to be_falsey
+ end
+ end
+
+ describe '#text?' do
+ it 'returns true' do
+ expect(blob.text?).to be_truthy
+ end
+
+ it 'returns false' do
+ expect(large_blob.text?).to be_falsey
+ end
+ end
+
+ describe '#image?' do
+ it 'returns false' do
+ expect(blob.image?).to be_falsey
+ end
+ end
+
+ describe '#mime_type' do
+ it 'returns text/plain' do
+ expect(blob.mime_type).to eq('text/plain')
+ end
+
+ it 'returns application/pdf' do
+ expect(large_blob.mime_type).to eq('application/pdf')
+ end
+ end
+
+ describe '#binary_mime_type?' do
+ it 'returns false' do
+ expect(blob.binary_mime_type?).to be_falsey
+ end
+ end
+
+ describe '#lines' do
+ it 'returns the payload in an Array' do
+ expect(blob.lines).to eq(['foo'])
+ end
+ end
+
+ describe '#content_type' do
+ it 'returns text/plain' do
+ expect(blob.content_type).to eq('text/plain; charset=utf-8')
+ end
+
+ it 'returns text/plain' do
+ expect(large_blob.content_type).to eq('application/pdf')
+ end
+ end
+
+ describe '#encoded_newlines_re' do
+ it 'returns a regular expression' do
+ expect(blob.encoded_newlines_re).to eq(/\r\n|\r|\n/)
+ end
+ end
+
+ describe '#ruby_encoding' do
+ it 'returns UTF-8' do
+ expect(blob.ruby_encoding).to eq('UTF-8')
+ end
+ end
+
+ describe '#encoding' do
+ it 'returns UTF-8' do
+ expect(blob.ruby_encoding).to eq('UTF-8')
+ end
+ end
+
+ describe '#empty?' do
+ it 'returns false' do
+ expect(blob.empty?).to be_falsey
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/status/pipeline/factory_spec.rb b/spec/lib/gitlab/ci/status/pipeline/factory_spec.rb
index 694d4ce160a..d97fdc01109 100644
--- a/spec/lib/gitlab/ci/status/pipeline/factory_spec.rb
+++ b/spec/lib/gitlab/ci/status/pipeline/factory_spec.rb
@@ -11,7 +11,7 @@ describe Gitlab::Ci::Status::Pipeline::Factory do
end
context 'when pipeline has a core status' do
- HasStatus::AVAILABLE_STATUSES.each do |simple_status|
+ (HasStatus::AVAILABLE_STATUSES - HasStatus::BLOCKED_STATUS).each do |simple_status|
context "when core status is #{simple_status}" do
let(:pipeline) { create(:ci_pipeline, status: simple_status) }
@@ -23,24 +23,12 @@ describe Gitlab::Ci::Status::Pipeline::Factory do
expect(factory.core_status).to be_a expected_status
end
- if simple_status == 'manual'
- it 'matches a correct extended statuses' do
- expect(factory.extended_statuses)
- .to eq [Gitlab::Ci::Status::Pipeline::Blocked]
- end
- elsif simple_status == 'scheduled'
- it 'matches a correct extended statuses' do
- expect(factory.extended_statuses)
- .to eq [Gitlab::Ci::Status::Pipeline::Scheduled]
- end
- else
- it 'does not match extended statuses' do
- expect(factory.extended_statuses).to be_empty
- end
-
- it "fabricates a core status #{simple_status}" do
- expect(status).to be_a expected_status
- end
+ it 'does not match extended statuses' do
+ expect(factory.extended_statuses).to be_empty
+ end
+
+ it "fabricates a core status #{simple_status}" do
+ expect(status).to be_a expected_status
end
it 'extends core status with common pipeline methods' do
@@ -51,6 +39,48 @@ describe Gitlab::Ci::Status::Pipeline::Factory do
end
end
end
+
+ context "when core status is manual" do
+ let(:pipeline) { create(:ci_pipeline, status: :manual) }
+
+ it "matches manual core status" do
+ expect(factory.core_status)
+ .to be_a Gitlab::Ci::Status::Manual
+ end
+
+ it 'matches a correct extended statuses' do
+ expect(factory.extended_statuses)
+ .to eq [Gitlab::Ci::Status::Pipeline::Blocked]
+ end
+
+ it 'extends core status with common pipeline methods' do
+ expect(status).to have_details
+ expect(status).not_to have_action
+ expect(status.details_path)
+ .to include "pipelines/#{pipeline.id}"
+ end
+ end
+
+ context "when core status is scheduled" do
+ let(:pipeline) { create(:ci_pipeline, status: :scheduled) }
+
+ it "matches scheduled core status" do
+ expect(factory.core_status)
+ .to be_a Gitlab::Ci::Status::Scheduled
+ end
+
+ it 'matches a correct extended statuses' do
+ expect(factory.extended_statuses)
+ .to eq [Gitlab::Ci::Status::Pipeline::Scheduled]
+ end
+
+ it 'extends core status with common pipeline methods' do
+ expect(status).to have_details
+ expect(status).not_to have_action
+ expect(status.details_path)
+ .to include "pipelines/#{pipeline.id}"
+ end
+ end
end
context 'when pipeline has warnings' do
diff --git a/spec/lib/gitlab/conflict/file_spec.rb b/spec/lib/gitlab/conflict/file_spec.rb
index 1bd077ddbdf..a955ce54e85 100644
--- a/spec/lib/gitlab/conflict/file_spec.rb
+++ b/spec/lib/gitlab/conflict/file_spec.rb
@@ -267,11 +267,6 @@ FILE
it 'includes the full content of the conflict' do
expect(conflict_file.as_json(full_content: true)).to have_key(:content)
end
-
- it 'includes the detected language of the conflict file' do
- expect(conflict_file.as_json(full_content: true)[:blob_ace_mode])
- .to eq('ruby')
- end
end
end
end
diff --git a/spec/lib/gitlab/file_detector_spec.rb b/spec/lib/gitlab/file_detector_spec.rb
index 9e351368b22..294ec2c2fd6 100644
--- a/spec/lib/gitlab/file_detector_spec.rb
+++ b/spec/lib/gitlab/file_detector_spec.rb
@@ -46,10 +46,6 @@ describe Gitlab::FileDetector do
expect(described_class.type_of('.gitignore')).to eq(:gitignore)
end
- it 'returns the type of a Koding config file' do
- expect(described_class.type_of('.koding.yml')).to eq(:koding)
- end
-
it 'returns the type of a GitLab CI config file' do
expect(described_class.type_of('.gitlab-ci.yml')).to eq(:gitlab_ci)
end
diff --git a/spec/lib/gitlab/git/blob_snippet_spec.rb b/spec/lib/gitlab/git/blob_snippet_spec.rb
deleted file mode 100644
index 6effec8295c..00000000000
--- a/spec/lib/gitlab/git/blob_snippet_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# encoding: UTF-8
-
-require "spec_helper"
-
-describe Gitlab::Git::BlobSnippet, :seed_helper do
- describe '#data' do
- context 'empty lines' do
- let(:snippet) { Gitlab::Git::BlobSnippet.new('master', nil, nil, nil) }
-
- it { expect(snippet.data).to be_nil }
- end
-
- context 'present lines' do
- let(:snippet) { Gitlab::Git::BlobSnippet.new('master', %w(wow much), 1, 'wow.rb') }
-
- it { expect(snippet.data).to eq("wow\nmuch") }
- end
- end
-end
diff --git a/spec/lib/gitlab/gon_helper_spec.rb b/spec/lib/gitlab/gon_helper_spec.rb
new file mode 100644
index 00000000000..c6f09ca2112
--- /dev/null
+++ b/spec/lib/gitlab/gon_helper_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::GonHelper do
+ let(:helper) do
+ Class.new do
+ include Gitlab::GonHelper
+ end.new
+ end
+
+ describe '#push_frontend_feature_flag' do
+ it 'pushes a feature flag to the frontend' do
+ gon = instance_double('gon')
+
+ allow(helper)
+ .to receive(:gon)
+ .and_return(gon)
+
+ expect(Feature)
+ .to receive(:enabled?)
+ .with(:my_feature_flag, 10)
+ .and_return(true)
+
+ expect(gon)
+ .to receive(:push)
+ .with({ features: { 'myFeatureFlag' => true } }, true)
+
+ helper.push_frontend_feature_flag(:my_feature_flag, 10)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/language_data_spec.rb b/spec/lib/gitlab/language_data_spec.rb
new file mode 100644
index 00000000000..b08150855fe
--- /dev/null
+++ b/spec/lib/gitlab/language_data_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::LanguageData do
+ describe '#extensions' do
+ before do
+ described_class.clear_extensions!
+ end
+
+ it 'loads the extensions once' do
+ expect(YAML).to receive(:load_file).once.and_call_original
+
+ 2.times do
+ expect(described_class.extensions).to be_a(Set)
+ expect(described_class.extensions.count).to be > 0
+ # Sanity check for known extensions
+ expect(described_class.extensions).to include(*%w(.rb .yml .json))
+ end
+ end
+ end
+end
diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb
index b335e0fbeb3..182070781dd 100644
--- a/spec/models/deployment_spec.rb
+++ b/spec/models/deployment_spec.rb
@@ -39,6 +39,29 @@ describe Deployment do
end
end
+ describe 'scopes' do
+ describe 'last_for_environment' do
+ let(:production) { create(:environment) }
+ let(:staging) { create(:environment) }
+ let(:testing) { create(:environment) }
+
+ let!(:deployments) do
+ [
+ create(:deployment, environment: production),
+ create(:deployment, environment: staging),
+ create(:deployment, environment: production)
+ ]
+ end
+
+ it 'retrieves last deployments for environments' do
+ last_deployments = described_class.last_for_environment([staging, production, testing])
+
+ expect(last_deployments.size).to eq(2)
+ expect(last_deployments).to eq(deployments.last(2))
+ end
+ end
+ end
+
describe '#includes_commit?' do
let(:project) { create(:project, :repository) }
let(:environment) { create(:environment, project: project) }
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 3fecddefff2..a807c336165 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -229,54 +229,75 @@ describe Project do
end
it 'does not allow an invalid URI as import_url' do
- project2 = build(:project, import_url: 'invalid://')
+ project = build(:project, import_url: 'invalid://')
- expect(project2).not_to be_valid
+ expect(project).not_to be_valid
+ end
+
+ it 'does allow a SSH URI as import_url for persisted projects' do
+ project = create(:project)
+ project.import_url = 'ssh://test@gitlab.com/project.git'
+
+ expect(project).to be_valid
+ end
+
+ it 'does not allow a SSH URI as import_url for new projects' do
+ project = build(:project, import_url: 'ssh://test@gitlab.com/project.git')
+
+ expect(project).not_to be_valid
end
it 'does allow a valid URI as import_url' do
- project2 = build(:project, import_url: 'ssh://test@gitlab.com/project.git')
+ project = build(:project, import_url: 'http://gitlab.com/project.git')
- expect(project2).to be_valid
+ expect(project).to be_valid
end
it 'allows an empty URI' do
- project2 = build(:project, import_url: '')
+ project = build(:project, import_url: '')
- expect(project2).to be_valid
+ expect(project).to be_valid
end
it 'does not produce import data on an empty URI' do
- project2 = build(:project, import_url: '')
+ project = build(:project, import_url: '')
- expect(project2.import_data).to be_nil
+ expect(project.import_data).to be_nil
end
it 'does not produce import data on an invalid URI' do
- project2 = build(:project, import_url: 'test://')
+ project = build(:project, import_url: 'test://')
- expect(project2.import_data).to be_nil
+ expect(project.import_data).to be_nil
end
it "does not allow import_url pointing to localhost" do
- project2 = build(:project, import_url: 'http://localhost:9000/t.git')
+ project = build(:project, import_url: 'http://localhost:9000/t.git')
+
+ expect(project).to be_invalid
+ expect(project.errors[:import_url].first).to include('Requests to localhost are not allowed')
+ end
+
+ it "does not allow import_url with invalid ports for new projects" do
+ project = build(:project, import_url: 'http://github.com:25/t.git')
- expect(project2).to be_invalid
- expect(project2.errors[:import_url].first).to include('Requests to localhost are not allowed')
+ expect(project).to be_invalid
+ expect(project.errors[:import_url].first).to include('Only allowed ports are 80, 443')
end
- it "does not allow import_url with invalid ports" do
- project2 = build(:project, import_url: 'http://github.com:25/t.git')
+ it "does not allow import_url with invalid ports for persisted projects" do
+ project = create(:project)
+ project.import_url = 'http://github.com:25/t.git'
- expect(project2).to be_invalid
- expect(project2.errors[:import_url].first).to include('Only allowed ports are 22, 80, 443')
+ expect(project).to be_invalid
+ expect(project.errors[:import_url].first).to include('Only allowed ports are 22, 80, 443')
end
it "does not allow import_url with invalid user" do
- project2 = build(:project, import_url: 'http://$user:password@github.com/t.git')
+ project = build(:project, import_url: 'http://$user:password@github.com/t.git')
- expect(project2).to be_invalid
- expect(project2.errors[:import_url].first).to include('Username needs to start with an alphanumeric character')
+ expect(project).to be_invalid
+ expect(project.errors[:import_url].first).to include('Username needs to start with an alphanumeric character')
end
describe 'project pending deletion' do
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index aed8e02cc23..fb16a321e4b 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -1567,7 +1567,6 @@ describe Repository do
:license_blob,
:license_key,
:gitignore,
- :koding_yml,
:gitlab_ci_yml,
:branch_names,
:tag_names,
@@ -1921,19 +1920,6 @@ describe Repository do
end
end
- describe '#koding_yml', :use_clean_rails_memory_store_caching do
- it 'returns and caches the output' do
- expect(repository).to receive(:file_on_head)
- .with(:koding)
- .and_return(Gitlab::Git::Tree.new(path: '.koding.yml'))
- .once
-
- 2.times do
- expect(repository.koding_yml).to be_an_instance_of(Gitlab::Git::Tree)
- end
- end
- end
-
describe '#readme', :use_clean_rails_memory_store_caching do
context 'with a non-existing repository' do
it 'returns nil' do
@@ -2386,4 +2372,15 @@ describe Repository do
end
end
end
+
+ describe '#merge_base' do
+ set(:project) { create(:project, :repository) }
+ subject(:repository) { project.repository }
+
+ it 'only makes one gitaly call' do
+ expect(Gitlab::GitalyClient).to receive(:call).once.and_call_original
+
+ repository.merge_base('master', 'fix')
+ end
+ end
end
diff --git a/spec/presenters/project_presenter_spec.rb b/spec/presenters/project_presenter_spec.rb
index 96193784072..3eb2f149311 100644
--- a/spec/presenters/project_presenter_spec.rb
+++ b/spec/presenters/project_presenter_spec.rb
@@ -410,36 +410,5 @@ describe ProjectPresenter do
end
end
end
-
- describe '#koding_anchor_data' do
- it 'returns link to set up Koding if user can push and no koding YML exists' do
- project.add_developer(user)
- allow(project.repository).to receive(:koding_yml).and_return(nil)
- allow(Gitlab::CurrentSettings).to receive(:koding_enabled?).and_return(true)
-
- expect(presenter.koding_anchor_data).to have_attributes(enabled: false,
- label: 'Set up Koding',
- link: presenter.add_koding_stack_path)
- end
-
- it 'returns nil if user cannot push' do
- expect(presenter.koding_anchor_data).to be_nil
- end
-
- it 'returns nil if koding is not enabled' do
- project.add_developer(user)
- allow(Gitlab::CurrentSettings).to receive(:koding_enabled?).and_return(false)
-
- expect(presenter.koding_anchor_data).to be_nil
- end
-
- it 'returns nil if koding YML already exists' do
- project.add_developer(user)
- allow(project.repository).to receive(:koding_yml).and_return(double)
- allow(Gitlab::CurrentSettings).to receive(:koding_enabled?).and_return(true)
-
- expect(presenter.koding_anchor_data).to be_nil
- end
- end
end
end
diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb
index 519638ebb82..fa38751fe58 100644
--- a/spec/requests/api/repositories_spec.rb
+++ b/spec/requests/api/repositories_spec.rb
@@ -468,7 +468,7 @@ describe API::Repositories do
describe 'GET :id/repository/merge_base' do
let(:refs) do
- %w(304d257dcb821665ab5110318fc58a007bd104ed 0031876facac3f2b2702a0e53a26e89939a42209)
+ %w(304d257dcb821665ab5110318fc58a007bd104ed 0031876facac3f2b2702a0e53a26e89939a42209 570e7b2abdd848b95f2f578043fc23bd6f6fd24d)
end
subject(:request) do
@@ -534,7 +534,7 @@ describe API::Repositories do
request
expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['message']).to eq('Provide exactly 2 refs')
+ expect(json_response['message']).to eq('Provide at least 2 refs')
end
end
end
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index fb1be16a111..84c7210f6bb 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -13,8 +13,6 @@ describe API::Settings, 'Settings' do
expect(json_response['default_projects_limit']).to eq(42)
expect(json_response['password_authentication_enabled_for_web']).to be_truthy
expect(json_response['repository_storages']).to eq(['default'])
- expect(json_response['koding_enabled']).to be_falsey
- expect(json_response['koding_url']).to be_nil
expect(json_response['plantuml_enabled']).to be_falsey
expect(json_response['plantuml_url']).to be_nil
expect(json_response['default_project_visibility']).to be_a String
@@ -47,8 +45,6 @@ describe API::Settings, 'Settings' do
default_projects_limit: 3,
password_authentication_enabled_for_web: false,
repository_storages: ['custom'],
- koding_enabled: true,
- koding_url: 'http://koding.example.com',
plantuml_enabled: true,
plantuml_url: 'http://plantuml.example.com',
default_snippet_visibility: 'internal',
@@ -72,8 +68,6 @@ describe API::Settings, 'Settings' do
expect(json_response['default_projects_limit']).to eq(3)
expect(json_response['password_authentication_enabled_for_web']).to be_falsey
expect(json_response['repository_storages']).to eq(['custom'])
- expect(json_response['koding_enabled']).to be_truthy
- expect(json_response['koding_url']).to eq('http://koding.example.com')
expect(json_response['plantuml_enabled']).to be_truthy
expect(json_response['plantuml_url']).to eq('http://plantuml.example.com')
expect(json_response['default_snippet_visibility']).to eq('internal')
@@ -112,15 +106,6 @@ describe API::Settings, 'Settings' do
expect(json_response['performance_bar_allowed_group_id']).to be_nil
end
- context "missing koding_url value when koding_enabled is true" do
- it "returns a blank parameter error message" do
- put api("/application/settings", admin), koding_enabled: true
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['error']).to eq('koding_url is missing')
- end
- end
-
context "missing plantuml_url value when plantuml_enabled is true" do
it "returns a blank parameter error message" do
put api("/application/settings", admin), plantuml_enabled: true
diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb
index dd8f6239587..a170bb14144 100644
--- a/spec/routing/routing_spec.rb
+++ b/spec/routing/routing_spec.rb
@@ -140,13 +140,6 @@ describe HelpController, "routing" do
end
end
-# koding GET /koding(.:format) koding#index
-describe KodingController, "routing" do
- it "to #index" do
- expect(get("/koding")).to route_to('koding#index')
- end
-end
-
# profile_account GET /profile/account(.:format) profile#account
# profile_history GET /profile/history(.:format) profile#history
# profile_password PUT /profile/password(.:format) profile#password_update
diff --git a/spec/rubocop/cop/qa/element_with_pattern_spec.rb b/spec/rubocop/cop/qa/element_with_pattern_spec.rb
new file mode 100644
index 00000000000..c5beb40f9fd
--- /dev/null
+++ b/spec/rubocop/cop/qa/element_with_pattern_spec.rb
@@ -0,0 +1,50 @@
+require 'spec_helper'
+
+require 'rubocop'
+require 'rubocop/rspec/support'
+
+require_relative '../../../../rubocop/cop/qa/element_with_pattern'
+
+describe RuboCop::Cop::QA::ElementWithPattern do
+ include CopHelper
+
+ let(:source_file) { 'qa/page.rb' }
+
+ subject(:cop) { described_class.new }
+
+ context 'in a QA file' do
+ before do
+ allow(cop).to receive(:in_qa_file?).and_return(true)
+ end
+
+ it "registers an offense for elements with a pattern" do
+ expect_offense(<<-RUBY)
+ view 'app/views/shared/groups/_search_form.html.haml' do
+ element :groups_filter, 'search_field_tag :filter'
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't use a pattern for element, create a corresponding `qa-groups-filter` instead.
+ element :groups_filter_placeholder, /Search by name/
+ ^^^^^^^^^^^^^^^^ Don't use a pattern for element, create a corresponding `qa-groups-filter-placeholder` instead.
+ end
+ RUBY
+ end
+
+ it "does not register an offense for element without a pattern" do
+ expect_no_offenses(<<-RUBY)
+ view 'app/views/shared/groups/_search_form.html.haml' do
+ element :groups_filter
+ element :groups_filter_placeholder
+ end
+ RUBY
+ end
+ end
+
+ context 'outside of a migration spec file' do
+ it "does not register an offense" do
+ expect_no_offenses(<<-RUBY)
+ describe 'foo' do
+ let(:user) { create(:user) }
+ end
+ RUBY
+ end
+ end
+end
diff --git a/spec/rubocop/qa_helpers_spec.rb b/spec/rubocop/qa_helpers_spec.rb
new file mode 100644
index 00000000000..26e4c1ca6f0
--- /dev/null
+++ b/spec/rubocop/qa_helpers_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require 'rubocop'
+require_relative '../../rubocop/qa_helpers'
+
+describe RuboCop::QAHelpers do
+ def parse_source(source, path = 'foo.rb')
+ buffer = Parser::Source::Buffer.new(path)
+ buffer.source = source
+
+ builder = RuboCop::AST::Builder.new
+ parser = Parser::CurrentRuby.new(builder)
+
+ parser.parse(buffer)
+ end
+
+ let(:cop) do
+ Class.new do
+ include RuboCop::QAHelpers
+ end.new
+ end
+
+ describe '#in_qa_file?' do
+ it 'returns true for a node in the qa/ directory' do
+ node = parse_source('10', Rails.root.join('qa', 'qa', 'page', 'dashboard', 'groups.rb'))
+
+ expect(cop.in_qa_file?(node)).to eq(true)
+ end
+
+ it 'returns false for a node outside the qa/ directory' do
+ node = parse_source('10', Rails.root.join('app', 'foo', 'foo.rb'))
+
+ expect(cop.in_qa_file?(node)).to eq(false)
+ end
+ end
+end
diff --git a/spec/services/applications/create_service_spec.rb b/spec/services/applications/create_service_spec.rb
index 9c43b56744b..c8134087fa1 100644
--- a/spec/services/applications/create_service_spec.rb
+++ b/spec/services/applications/create_service_spec.rb
@@ -1,17 +1,14 @@
+# frozen_string_literal: true
+
require "spec_helper"
describe ::Applications::CreateService do
+ include TestRequestHelpers
+
let(:user) { create(:user) }
let(:params) { attributes_for(:application) }
- let(:request) do
- if Gitlab.rails5?
- ActionController::TestRequest.new({ remote_ip: "127.0.0.1" }, ActionController::TestSession.new)
- else
- ActionController::TestRequest.new(remote_ip: "127.0.0.1")
- end
- end
subject { described_class.new(user, params) }
- it { expect { subject.execute(request) }.to change { Doorkeeper::Application.count }.by(1) }
+ it { expect { subject.execute(test_request) }.to change { Doorkeeper::Application.count }.by(1) }
end
diff --git a/spec/services/clusters/applications/create_service_spec.rb b/spec/services/clusters/applications/create_service_spec.rb
new file mode 100644
index 00000000000..056db0c5486
--- /dev/null
+++ b/spec/services/clusters/applications/create_service_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Clusters::Applications::CreateService do
+ include TestRequestHelpers
+
+ let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:user) { create(:user) }
+ let(:params) { { application: 'helm' } }
+ let(:service) { described_class.new(cluster, user, params) }
+
+ describe '#execute' do
+ before do
+ allow(ClusterInstallAppWorker).to receive(:perform_async)
+ end
+
+ subject { service.execute(test_request) }
+
+ it 'creates an application' do
+ expect do
+ subject
+
+ cluster.reload
+ end.to change(cluster, :application_helm)
+ end
+
+ it 'schedules an install via worker' do
+ expect(ClusterInstallAppWorker).to receive(:perform_async).with('helm', anything).once
+
+ subject
+ end
+
+ context 'jupyter application' do
+ let(:params) do
+ {
+ application: 'jupyter',
+ hostname: 'example.com'
+ }
+ end
+
+ before do
+ allow_any_instance_of(Clusters::Applications::ScheduleInstallationService).to receive(:execute)
+ end
+
+ it 'creates the application' do
+ expect do
+ subject
+
+ cluster.reload
+ end.to change(cluster, :application_jupyter)
+ end
+
+ it 'sets the hostname' do
+ expect(subject.hostname).to eq('example.com')
+ end
+
+ it 'sets the oauth_application' do
+ expect(subject.oauth_application).to be_present
+ end
+ end
+
+ context 'invalid application' do
+ let(:params) { { application: 'non-existent' } }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Clusters::Applications::CreateService::InvalidApplicationError)
+ end
+ end
+ end
+end
diff --git a/spec/services/clusters/applications/schedule_installation_service_spec.rb b/spec/services/clusters/applications/schedule_installation_service_spec.rb
index bca1e71bef2..21797edd533 100644
--- a/spec/services/clusters/applications/schedule_installation_service_spec.rb
+++ b/spec/services/clusters/applications/schedule_installation_service_spec.rb
@@ -10,14 +10,13 @@ describe Clusters::Applications::ScheduleInstallationService do
expect(ClusterInstallAppWorker).not_to receive(:perform_async)
count_before = count_scheduled
- expect { service.execute(application) }.to raise_error(StandardError)
+ expect { service.execute }.to raise_error(StandardError)
expect(count_scheduled).to eq(count_before)
end
end
describe '#execute' do
- let(:project) { double(:project) }
- let(:service) { described_class.new(project, nil) }
+ let(:service) { described_class.new(application) }
context 'when application is installable' do
let(:application) { create(:clusters_applications_helm, :installable) }
@@ -25,7 +24,7 @@ describe Clusters::Applications::ScheduleInstallationService do
it 'make the application scheduled' do
expect(ClusterInstallAppWorker).to receive(:perform_async).with(application.name, kind_of(Numeric)).once
- expect { service.execute(application) }.to change { application.class.with_status(:scheduled).count }.by(1)
+ expect { service.execute }.to change { application.class.with_status(:scheduled).count }.by(1)
end
end
diff --git a/spec/services/clusters/create_service_spec.rb b/spec/services/clusters/create_service_spec.rb
index 1685dc748bd..3959295c13e 100644
--- a/spec/services/clusters/create_service_spec.rb
+++ b/spec/services/clusters/create_service_spec.rb
@@ -5,7 +5,7 @@ describe Clusters::CreateService do
let(:project) { create(:project) }
let(:user) { create(:user) }
- subject { described_class.new(project, user, params).execute(access_token) }
+ subject { described_class.new(user, params).execute(project: project, access_token: access_token) }
context 'when provider is gcp' do
context 'when project has no clusters' do
diff --git a/spec/services/clusters/update_service_spec.rb b/spec/services/clusters/update_service_spec.rb
index 2d91a21035d..dcd75b6912d 100644
--- a/spec/services/clusters/update_service_spec.rb
+++ b/spec/services/clusters/update_service_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe Clusters::UpdateService do
describe '#execute' do
- subject { described_class.new(cluster.project, cluster.user, params).execute(cluster) }
+ subject { described_class.new(cluster.user, params).execute(cluster) }
let(:cluster) { create(:cluster, :project, :provided_by_user) }
diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb
index beff499f2be..1d31d26f418 100644
--- a/spec/services/projects/destroy_service_spec.rb
+++ b/spec/services/projects/destroy_service_spec.rb
@@ -65,10 +65,12 @@ describe Projects::DestroyService do
context 'Sidekiq inline' do
before do
- # Run sidekiq immediatly to check that renamed repository will be removed
+ # Run sidekiq immediately to check that renamed repository will be removed
perform_enqueued_jobs { destroy_project(project, user, {}) }
end
+ it_behaves_like 'deleting the project'
+
context 'when has remote mirrors' do
let!(:project) do
create(:project, :repository, namespace: user.namespace).tap do |project|
@@ -82,13 +84,28 @@ describe Projects::DestroyService do
end
end
- it_behaves_like 'deleting the project'
-
it 'invalidates personal_project_count cache' do
expect(user).to receive(:invalidate_personal_projects_count)
destroy_project(project, user)
end
+
+ context 'when project has exports' do
+ let!(:project_with_export) do
+ create(:project, :repository, namespace: user.namespace).tap do |project|
+ create(:import_export_upload,
+ project: project,
+ export_file: fixture_file_upload('spec/fixtures/project_export.tar.gz'))
+ end
+ end
+ let!(:async) { true }
+
+ it 'destroys project and export' do
+ expect { destroy_project(project_with_export, user) }.to change(ImportExportUpload, :count).by(-1)
+
+ expect(Project.all).not_to include(project_with_export)
+ end
+ end
end
context 'Sidekiq fake' do
diff --git a/spec/services/projects/import_service_spec.rb b/spec/services/projects/import_service_spec.rb
index e2a600d12d1..e6ffa2b957b 100644
--- a/spec/services/projects/import_service_spec.rb
+++ b/spec/services/projects/import_service_spec.rb
@@ -235,7 +235,7 @@ describe Projects::ImportService do
result = described_class.new(project, user).execute
expect(result[:status]).to eq :error
- expect(result[:message]).to include('Only allowed ports are 22, 80, 443')
+ expect(result[:message]).to include('Only allowed ports are 80, 443')
end
end
diff --git a/spec/support/features/issuable_quick_actions_shared_examples.rb b/spec/support/features/issuable_quick_actions_shared_examples.rb
index 846e697eb96..2a883ce1074 100644
--- a/spec/support/features/issuable_quick_actions_shared_examples.rb
+++ b/spec/support/features/issuable_quick_actions_shared_examples.rb
@@ -77,6 +77,15 @@ shared_examples 'issuable record that supports quick actions in its description
expect(issuable.labels).to eq [label_bug]
expect(issuable.milestone).to eq milestone
end
+
+ it 'removes the quick action from note and explains it in the preview' do
+ preview_note("Awesome!\n\n/close")
+
+ expect(page).to have_content 'Awesome!'
+ expect(page).not_to have_content '/close'
+ issuable_name = issuable.is_a?(Issue) ? 'issue' : 'merge request'
+ expect(page).to have_content "Closes this #{issuable_name}."
+ end
end
context 'with a note containing only commands' do
diff --git a/spec/support/helpers/test_request_helpers.rb b/spec/support/helpers/test_request_helpers.rb
new file mode 100644
index 00000000000..187a0e07891
--- /dev/null
+++ b/spec/support/helpers/test_request_helpers.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module TestRequestHelpers
+ def test_request(remote_ip: '127.0.0.1')
+ if Gitlab.rails5?
+ ActionController::TestRequest.new({ remote_ip: remote_ip }, ActionController::TestSession.new)
+ else
+ ActionController::TestRequest.new(remote_ip: remote_ip)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/dirty_submit_form_shared_examples.rb b/spec/support/shared_examples/dirty_submit_form_shared_examples.rb
new file mode 100644
index 00000000000..ba363593120
--- /dev/null
+++ b/spec/support/shared_examples/dirty_submit_form_shared_examples.rb
@@ -0,0 +1,24 @@
+shared_examples 'dirty submit form' do |selector_args|
+ selectors = selector_args.is_a?(Array) ? selector_args : [selector_args]
+
+ selectors.each do |selector|
+ it "disables #{selector[:form]} submit until there are changes", :js do
+ form = find(selector[:form])
+ submit = form.first('.js-dirty-submit')
+ input = form.first(selector[:input])
+ original_value = input.value
+
+ expect(submit.disabled?).to be true
+
+ input.set("#{original_value} changes")
+
+ form.find('.js-dirty-submit:not([disabled])', match: :first)
+ expect(submit.disabled?).to be false
+
+ input.set(original_value)
+
+ form.find('.js-dirty-submit[disabled]', match: :first)
+ expect(submit.disabled?).to be true
+ end
+ end
+end
diff --git a/vendor/languages.yml b/vendor/languages.yml
new file mode 100755
index 00000000000..a6edb0415b2
--- /dev/null
+++ b/vendor/languages.yml
@@ -0,0 +1,5488 @@
+# Extracted from https://github.com/github/linguist/blob/master/lib/linguist/languages.yml
+
+# Defines all Languages known to GitHub.
+#
+# type - Either data, programming, markup, prose, or nil
+# aliases - An Array of additional aliases (implicitly
+# includes name.downcase)
+# ace_mode - A String name of the Ace Mode used for highlighting whenever
+# a file is edited. This must match one of the filenames in http://git.io/3XO_Cg.
+# Use "text" if a mode does not exist.
+# codemirror_mode - A String name of the CodeMirror Mode used for highlighting whenever a file is edited.
+# This must match a mode from https://git.io/vi9Fx
+# codemirror_mime_type - A String name of the file mime type used for highlighting whenever a file is edited.
+# This should match the `mime` associated with the mode from https://git.io/f4SoQ
+# wrap - Boolean wrap to enable line wrapping (default: false)
+# extensions - An Array of associated extensions (the first one is
+# considered the primary extension, the others should be
+# listed alphabetically)
+# filenames - An Array of filenames commonly associated with the language
+# interpreters - An Array of associated interpreters
+# searchable - Boolean flag to enable searching (defaults to true)
+# language_id - Integer used as a language-name-independent indexed field so that we can rename
+# languages in Linguist without reindexing all the code on GitHub. Must not be
+# changed for existing languages without the explicit permission of GitHub staff.
+# color - CSS hex color to represent the language. Only used if type is "programming" or "prose".
+# tm_scope - The TextMate scope that represents this programming
+# language. This should match one of the scopes listed in
+# the grammars.yml file. Use "none" if there is no grammar
+# for this language.
+# group - Name of the parent language. Languages in a group are counted
+# in the statistics as the parent language.
+#
+# Any additions or modifications (even trivial) should have corresponding
+# test changes in `test/test_blob.rb`.
+#
+# Please keep this list alphabetized. Capitalization comes before lowercase.
+
+---
+1C Enterprise:
+ type: programming
+ color: "#814CCC"
+ extensions:
+ - ".bsl"
+ - ".os"
+ tm_scope: source.bsl
+ ace_mode: text
+ language_id: 0
+ABAP:
+ type: programming
+ color: "#E8274B"
+ extensions:
+ - ".abap"
+ ace_mode: abap
+ language_id: 1
+ABNF:
+ type: data
+ ace_mode: text
+ extensions:
+ - ".abnf"
+ tm_scope: source.abnf
+ language_id: 429
+AGS Script:
+ type: programming
+ color: "#B9D9FF"
+ aliases:
+ - ags
+ extensions:
+ - ".asc"
+ - ".ash"
+ tm_scope: source.c++
+ ace_mode: c_cpp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-c++src
+ language_id: 2
+AMPL:
+ type: programming
+ color: "#E6EFBB"
+ extensions:
+ - ".ampl"
+ - ".mod"
+ tm_scope: source.ampl
+ ace_mode: text
+ language_id: 3
+ANTLR:
+ type: programming
+ color: "#9DC3FF"
+ extensions:
+ - ".g4"
+ ace_mode: text
+ language_id: 4
+API Blueprint:
+ type: markup
+ color: "#2ACCA8"
+ ace_mode: markdown
+ extensions:
+ - ".apib"
+ tm_scope: text.html.markdown.source.gfm.apib
+ language_id: 5
+APL:
+ type: programming
+ color: "#5A8164"
+ extensions:
+ - ".apl"
+ - ".dyalog"
+ interpreters:
+ - apl
+ - aplx
+ - dyalog
+ tm_scope: source.apl
+ ace_mode: text
+ codemirror_mode: apl
+ codemirror_mime_type: text/apl
+ language_id: 6
+ASN.1:
+ type: data
+ extensions:
+ - ".asn"
+ - ".asn1"
+ tm_scope: source.asn
+ ace_mode: text
+ codemirror_mode: asn.1
+ codemirror_mime_type: text/x-ttcn-asn
+ language_id: 7
+ASP:
+ type: programming
+ color: "#6a40fd"
+ tm_scope: text.html.asp
+ aliases:
+ - aspx
+ - aspx-vb
+ extensions:
+ - ".asp"
+ - ".asax"
+ - ".ascx"
+ - ".ashx"
+ - ".asmx"
+ - ".aspx"
+ - ".axd"
+ ace_mode: text
+ codemirror_mode: htmlembedded
+ codemirror_mime_type: application/x-aspx
+ language_id: 8
+ATS:
+ type: programming
+ color: "#1ac620"
+ aliases:
+ - ats2
+ extensions:
+ - ".dats"
+ - ".hats"
+ - ".sats"
+ tm_scope: source.ats
+ ace_mode: ocaml
+ language_id: 9
+ActionScript:
+ type: programming
+ tm_scope: source.actionscript.3
+ color: "#882B0F"
+ aliases:
+ - actionscript 3
+ - actionscript3
+ - as3
+ extensions:
+ - ".as"
+ ace_mode: actionscript
+ language_id: 10
+Ada:
+ type: programming
+ color: "#02f88c"
+ extensions:
+ - ".adb"
+ - ".ada"
+ - ".ads"
+ aliases:
+ - ada95
+ - ada2005
+ ace_mode: ada
+ language_id: 11
+Adobe Font Metrics:
+ type: data
+ tm_scope: source.afm
+ extensions:
+ - ".afm"
+ aliases:
+ - acfm
+ - adobe composite font metrics
+ - adobe multiple font metrics
+ - amfm
+ ace_mode: text
+ language_id: 147198098
+Agda:
+ type: programming
+ color: "#315665"
+ extensions:
+ - ".agda"
+ ace_mode: text
+ language_id: 12
+Alloy:
+ type: programming
+ color: "#64C800"
+ extensions:
+ - ".als"
+ ace_mode: text
+ language_id: 13
+Alpine Abuild:
+ type: programming
+ group: Shell
+ aliases:
+ - abuild
+ - apkbuild
+ filenames:
+ - APKBUILD
+ tm_scope: source.shell
+ ace_mode: sh
+ codemirror_mode: shell
+ codemirror_mime_type: text/x-sh
+ language_id: 14
+AngelScript:
+ type: programming
+ color: "#C7D7DC"
+ extensions:
+ - ".as"
+ - ".angelscript"
+ tm_scope: source.angelscript
+ ace_mode: text
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-c++src
+ language_id: 389477596
+Ant Build System:
+ type: data
+ tm_scope: text.xml.ant
+ filenames:
+ - ant.xml
+ - build.xml
+ ace_mode: xml
+ codemirror_mode: xml
+ codemirror_mime_type: application/xml
+ language_id: 15
+ApacheConf:
+ type: data
+ aliases:
+ - aconf
+ - apache
+ extensions:
+ - ".apacheconf"
+ - ".vhost"
+ filenames:
+ - ".htaccess"
+ - apache2.conf
+ - httpd.conf
+ tm_scope: source.apache-config
+ ace_mode: apache_conf
+ language_id: 16
+Apex:
+ type: programming
+ extensions:
+ - ".cls"
+ tm_scope: source.java
+ ace_mode: java
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-java
+ language_id: 17
+Apollo Guidance Computer:
+ type: programming
+ group: Assembly
+ extensions:
+ - ".agc"
+ tm_scope: source.agc
+ ace_mode: assembly_x86
+ language_id: 18
+AppleScript:
+ type: programming
+ aliases:
+ - osascript
+ extensions:
+ - ".applescript"
+ - ".scpt"
+ interpreters:
+ - osascript
+ ace_mode: applescript
+ color: "#101F1F"
+ language_id: 19
+Arc:
+ type: programming
+ color: "#aa2afe"
+ extensions:
+ - ".arc"
+ tm_scope: none
+ ace_mode: text
+ language_id: 20
+AsciiDoc:
+ type: prose
+ ace_mode: asciidoc
+ wrap: true
+ extensions:
+ - ".asciidoc"
+ - ".adoc"
+ - ".asc"
+ tm_scope: text.html.asciidoc
+ language_id: 22
+AspectJ:
+ type: programming
+ color: "#a957b0"
+ extensions:
+ - ".aj"
+ tm_scope: source.aspectj
+ ace_mode: text
+ language_id: 23
+Assembly:
+ type: programming
+ color: "#6E4C13"
+ aliases:
+ - asm
+ - nasm
+ extensions:
+ - ".asm"
+ - ".a51"
+ - ".inc"
+ - ".nasm"
+ tm_scope: source.assembly
+ ace_mode: assembly_x86
+ language_id: 24
+Augeas:
+ type: programming
+ extensions:
+ - ".aug"
+ tm_scope: none
+ ace_mode: text
+ language_id: 25
+AutoHotkey:
+ type: programming
+ color: "#6594b9"
+ aliases:
+ - ahk
+ extensions:
+ - ".ahk"
+ - ".ahkl"
+ tm_scope: source.ahk
+ ace_mode: autohotkey
+ language_id: 26
+AutoIt:
+ type: programming
+ color: "#1C3552"
+ aliases:
+ - au3
+ - AutoIt3
+ - AutoItScript
+ extensions:
+ - ".au3"
+ tm_scope: source.autoit
+ ace_mode: autohotkey
+ language_id: 27
+Awk:
+ type: programming
+ extensions:
+ - ".awk"
+ - ".auk"
+ - ".gawk"
+ - ".mawk"
+ - ".nawk"
+ interpreters:
+ - awk
+ - gawk
+ - mawk
+ - nawk
+ ace_mode: text
+ language_id: 28
+Ballerina:
+ type: programming
+ extensions:
+ - ".bal"
+ tm_scope: source.ballerina
+ ace_mode: text
+ color: "#FF5000"
+ language_id: 720859680
+Batchfile:
+ type: programming
+ aliases:
+ - bat
+ - batch
+ - dosbatch
+ - winbatch
+ extensions:
+ - ".bat"
+ - ".cmd"
+ tm_scope: source.batchfile
+ ace_mode: batchfile
+ color: "#C1F12E"
+ language_id: 29
+Befunge:
+ type: programming
+ extensions:
+ - ".befunge"
+ ace_mode: text
+ language_id: 30
+Bison:
+ type: programming
+ group: Yacc
+ tm_scope: source.bison
+ extensions:
+ - ".bison"
+ ace_mode: text
+ language_id: 31
+BitBake:
+ type: programming
+ tm_scope: none
+ extensions:
+ - ".bb"
+ ace_mode: text
+ language_id: 32
+Blade:
+ type: markup
+ group: HTML
+ extensions:
+ - ".blade"
+ - ".blade.php"
+ tm_scope: text.html.php.blade
+ ace_mode: text
+ language_id: 33
+BlitzBasic:
+ type: programming
+ aliases:
+ - b3d
+ - blitz3d
+ - blitzplus
+ - bplus
+ extensions:
+ - ".bb"
+ - ".decls"
+ tm_scope: source.blitzmax
+ ace_mode: text
+ language_id: 34
+BlitzMax:
+ type: programming
+ color: "#cd6400"
+ extensions:
+ - ".bmx"
+ aliases:
+ - bmax
+ ace_mode: text
+ language_id: 35
+Bluespec:
+ type: programming
+ extensions:
+ - ".bsv"
+ tm_scope: source.bsv
+ ace_mode: verilog
+ language_id: 36
+Boo:
+ type: programming
+ color: "#d4bec1"
+ extensions:
+ - ".boo"
+ ace_mode: text
+ tm_scope: source.boo
+ language_id: 37
+Brainfuck:
+ type: programming
+ color: "#2F2530"
+ extensions:
+ - ".b"
+ - ".bf"
+ tm_scope: source.bf
+ ace_mode: text
+ codemirror_mode: brainfuck
+ codemirror_mime_type: text/x-brainfuck
+ language_id: 38
+Brightscript:
+ type: programming
+ extensions:
+ - ".brs"
+ tm_scope: source.brightscript
+ ace_mode: text
+ language_id: 39
+Bro:
+ type: programming
+ extensions:
+ - ".bro"
+ ace_mode: text
+ language_id: 40
+C:
+ type: programming
+ color: "#555555"
+ extensions:
+ - ".c"
+ - ".cats"
+ - ".h"
+ - ".idc"
+ interpreters:
+ - tcc
+ ace_mode: c_cpp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-csrc
+ language_id: 41
+C#:
+ type: programming
+ ace_mode: csharp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-csharp
+ tm_scope: source.cs
+ color: "#178600"
+ aliases:
+ - csharp
+ extensions:
+ - ".cs"
+ - ".cake"
+ - ".cshtml"
+ - ".csx"
+ language_id: 42
+C++:
+ type: programming
+ ace_mode: c_cpp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-c++src
+ color: "#f34b7d"
+ aliases:
+ - cpp
+ extensions:
+ - ".cpp"
+ - ".c++"
+ - ".cc"
+ - ".cp"
+ - ".cxx"
+ - ".h"
+ - ".h++"
+ - ".hh"
+ - ".hpp"
+ - ".hxx"
+ - ".inc"
+ - ".inl"
+ - ".ino"
+ - ".ipp"
+ - ".re"
+ - ".tcc"
+ - ".tpp"
+ language_id: 43
+C-ObjDump:
+ type: data
+ extensions:
+ - ".c-objdump"
+ tm_scope: objdump.x86asm
+ ace_mode: assembly_x86
+ language_id: 44
+C2hs Haskell:
+ type: programming
+ group: Haskell
+ aliases:
+ - c2hs
+ extensions:
+ - ".chs"
+ tm_scope: source.haskell
+ ace_mode: haskell
+ codemirror_mode: haskell
+ codemirror_mime_type: text/x-haskell
+ language_id: 45
+CLIPS:
+ type: programming
+ extensions:
+ - ".clp"
+ tm_scope: source.clips
+ ace_mode: text
+ language_id: 46
+CMake:
+ type: programming
+ extensions:
+ - ".cmake"
+ - ".cmake.in"
+ filenames:
+ - CMakeLists.txt
+ ace_mode: text
+ codemirror_mode: cmake
+ codemirror_mime_type: text/x-cmake
+ language_id: 47
+COBOL:
+ type: programming
+ extensions:
+ - ".cob"
+ - ".cbl"
+ - ".ccp"
+ - ".cobol"
+ - ".cpy"
+ ace_mode: cobol
+ codemirror_mode: cobol
+ codemirror_mime_type: text/x-cobol
+ language_id: 48
+COLLADA:
+ type: data
+ extensions:
+ - ".dae"
+ tm_scope: text.xml
+ ace_mode: xml
+ codemirror_mode: xml
+ codemirror_mime_type: text/xml
+ language_id: 49
+CSON:
+ type: data
+ group: CoffeeScript
+ tm_scope: source.coffee
+ ace_mode: coffee
+ codemirror_mode: coffeescript
+ codemirror_mime_type: text/x-coffeescript
+ searchable: false
+ extensions:
+ - ".cson"
+ language_id: 424
+CSS:
+ type: markup
+ tm_scope: source.css
+ ace_mode: css
+ codemirror_mode: css
+ codemirror_mime_type: text/css
+ color: "#563d7c"
+ extensions:
+ - ".css"
+ language_id: 50
+CSV:
+ type: data
+ ace_mode: text
+ tm_scope: none
+ extensions:
+ - ".csv"
+ language_id: 51
+CWeb:
+ type: programming
+ extensions:
+ - ".w"
+ tm_scope: none
+ ace_mode: text
+ language_id: 657332628
+Cap'n Proto:
+ type: programming
+ tm_scope: source.capnp
+ extensions:
+ - ".capnp"
+ ace_mode: text
+ language_id: 52
+CartoCSS:
+ type: programming
+ aliases:
+ - Carto
+ extensions:
+ - ".mss"
+ ace_mode: text
+ tm_scope: source.css.mss
+ language_id: 53
+Ceylon:
+ type: programming
+ color: "#dfa535"
+ extensions:
+ - ".ceylon"
+ tm_scope: source.ceylon
+ ace_mode: text
+ language_id: 54
+Chapel:
+ type: programming
+ color: "#8dc63f"
+ aliases:
+ - chpl
+ extensions:
+ - ".chpl"
+ ace_mode: text
+ language_id: 55
+Charity:
+ type: programming
+ extensions:
+ - ".ch"
+ tm_scope: none
+ ace_mode: text
+ language_id: 56
+ChucK:
+ type: programming
+ extensions:
+ - ".ck"
+ tm_scope: source.java
+ ace_mode: java
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-java
+ language_id: 57
+Cirru:
+ type: programming
+ color: "#ccccff"
+ ace_mode: cirru
+ extensions:
+ - ".cirru"
+ language_id: 58
+Clarion:
+ type: programming
+ color: "#db901e"
+ ace_mode: text
+ extensions:
+ - ".clw"
+ tm_scope: source.clarion
+ language_id: 59
+Clean:
+ type: programming
+ color: "#3F85AF"
+ extensions:
+ - ".icl"
+ - ".dcl"
+ tm_scope: source.clean
+ ace_mode: text
+ language_id: 60
+Click:
+ type: programming
+ color: "#E4E6F3"
+ extensions:
+ - ".click"
+ tm_scope: source.click
+ ace_mode: text
+ language_id: 61
+Clojure:
+ type: programming
+ ace_mode: clojure
+ codemirror_mode: clojure
+ codemirror_mime_type: text/x-clojure
+ color: "#db5855"
+ extensions:
+ - ".clj"
+ - ".boot"
+ - ".cl2"
+ - ".cljc"
+ - ".cljs"
+ - ".cljs.hl"
+ - ".cljscm"
+ - ".cljx"
+ - ".hic"
+ filenames:
+ - riemann.config
+ language_id: 62
+Closure Templates:
+ type: markup
+ group: HTML
+ ace_mode: soy_template
+ codemirror_mode: soy
+ codemirror_mime_type: text/x-soy
+ aliases:
+ - soy
+ extensions:
+ - ".soy"
+ tm_scope: text.html.soy
+ language_id: 357046146
+Cloud Firestore Security Rules:
+ type: data
+ ace_mode: less
+ codemirror_mode: css
+ codemirror_mime_type: text/css
+ tm_scope: source.firestore
+ filenames:
+ - firestore.rules
+ language_id: 407996372
+CoNLL-U:
+ type: data
+ extensions:
+ - ".conllu"
+ - ".conll"
+ tm_scope: text.conllu
+ ace_mode: text
+ aliases:
+ - CoNLL
+ - CoNLL-X
+ language_id: 421026389
+CoffeeScript:
+ type: programming
+ tm_scope: source.coffee
+ ace_mode: coffee
+ codemirror_mode: coffeescript
+ codemirror_mime_type: text/x-coffeescript
+ color: "#244776"
+ aliases:
+ - coffee
+ - coffee-script
+ extensions:
+ - ".coffee"
+ - "._coffee"
+ - ".cake"
+ - ".cjsx"
+ - ".iced"
+ filenames:
+ - Cakefile
+ interpreters:
+ - coffee
+ language_id: 63
+ColdFusion:
+ type: programming
+ ace_mode: coldfusion
+ color: "#ed2cd6"
+ aliases:
+ - cfm
+ - cfml
+ - coldfusion html
+ extensions:
+ - ".cfm"
+ - ".cfml"
+ tm_scope: text.html.cfm
+ language_id: 64
+ColdFusion CFC:
+ type: programming
+ group: ColdFusion
+ ace_mode: coldfusion
+ aliases:
+ - cfc
+ extensions:
+ - ".cfc"
+ tm_scope: source.cfscript
+ language_id: 65
+Common Lisp:
+ type: programming
+ tm_scope: source.lisp
+ color: "#3fb68b"
+ aliases:
+ - lisp
+ extensions:
+ - ".lisp"
+ - ".asd"
+ - ".cl"
+ - ".l"
+ - ".lsp"
+ - ".ny"
+ - ".podsl"
+ - ".sexp"
+ interpreters:
+ - lisp
+ - sbcl
+ - ccl
+ - clisp
+ - ecl
+ ace_mode: lisp
+ codemirror_mode: commonlisp
+ codemirror_mime_type: text/x-common-lisp
+ language_id: 66
+Common Workflow Language:
+ aliases:
+ - cwl
+ type: programming
+ ace_mode: yaml
+ codemirror_mode: yaml
+ codemirror_mime_type: text/x-yaml
+ extensions:
+ - ".cwl"
+ interpreters:
+ - cwl-runner
+ color: "#B5314C"
+ tm_scope: source.cwl
+ language_id: 988547172
+Component Pascal:
+ type: programming
+ color: "#B0CE4E"
+ extensions:
+ - ".cp"
+ - ".cps"
+ tm_scope: source.pascal
+ aliases:
+ - delphi
+ - objectpascal
+ ace_mode: pascal
+ codemirror_mode: pascal
+ codemirror_mime_type: text/x-pascal
+ language_id: 67
+Cool:
+ type: programming
+ extensions:
+ - ".cl"
+ tm_scope: source.cool
+ ace_mode: text
+ language_id: 68
+Coq:
+ type: programming
+ extensions:
+ - ".coq"
+ - ".v"
+ ace_mode: text
+ language_id: 69
+Cpp-ObjDump:
+ type: data
+ extensions:
+ - ".cppobjdump"
+ - ".c++-objdump"
+ - ".c++objdump"
+ - ".cpp-objdump"
+ - ".cxx-objdump"
+ tm_scope: objdump.x86asm
+ aliases:
+ - c++-objdump
+ ace_mode: assembly_x86
+ language_id: 70
+Creole:
+ type: prose
+ wrap: true
+ extensions:
+ - ".creole"
+ tm_scope: text.html.creole
+ ace_mode: text
+ language_id: 71
+Crystal:
+ type: programming
+ color: "#776791"
+ extensions:
+ - ".cr"
+ ace_mode: ruby
+ codemirror_mode: crystal
+ codemirror_mime_type: text/x-crystal
+ tm_scope: source.crystal
+ interpreters:
+ - crystal
+ language_id: 72
+Csound:
+ type: programming
+ aliases:
+ - csound-orc
+ extensions:
+ - ".orc"
+ - ".udo"
+ tm_scope: source.csound
+ ace_mode: csound_orchestra
+ language_id: 73
+Csound Document:
+ type: programming
+ aliases:
+ - csound-csd
+ extensions:
+ - ".csd"
+ tm_scope: source.csound-document
+ ace_mode: csound_document
+ language_id: 74
+Csound Score:
+ type: programming
+ aliases:
+ - csound-sco
+ extensions:
+ - ".sco"
+ tm_scope: source.csound-score
+ ace_mode: csound_score
+ language_id: 75
+Cuda:
+ type: programming
+ extensions:
+ - ".cu"
+ - ".cuh"
+ tm_scope: source.cuda-c++
+ ace_mode: c_cpp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-c++src
+ color: "#3A4E3A"
+ language_id: 77
+Cycript:
+ type: programming
+ extensions:
+ - ".cy"
+ tm_scope: source.js
+ ace_mode: javascript
+ codemirror_mode: javascript
+ codemirror_mime_type: text/javascript
+ language_id: 78
+Cython:
+ type: programming
+ group: Python
+ extensions:
+ - ".pyx"
+ - ".pxd"
+ - ".pxi"
+ aliases:
+ - pyrex
+ ace_mode: text
+ codemirror_mode: python
+ codemirror_mime_type: text/x-cython
+ language_id: 79
+D:
+ type: programming
+ color: "#ba595e"
+ extensions:
+ - ".d"
+ - ".di"
+ ace_mode: d
+ codemirror_mode: d
+ codemirror_mime_type: text/x-d
+ language_id: 80
+D-ObjDump:
+ type: data
+ extensions:
+ - ".d-objdump"
+ tm_scope: objdump.x86asm
+ ace_mode: assembly_x86
+ language_id: 81
+DIGITAL Command Language:
+ type: programming
+ aliases:
+ - dcl
+ extensions:
+ - ".com"
+ tm_scope: none
+ ace_mode: text
+ language_id: 82
+DM:
+ type: programming
+ color: "#447265"
+ extensions:
+ - ".dm"
+ aliases:
+ - byond
+ tm_scope: source.dm
+ ace_mode: c_cpp
+ language_id: 83
+DNS Zone:
+ type: data
+ extensions:
+ - ".zone"
+ - ".arpa"
+ tm_scope: text.zone_file
+ ace_mode: text
+ language_id: 84
+DTrace:
+ type: programming
+ aliases:
+ - dtrace-script
+ extensions:
+ - ".d"
+ interpreters:
+ - dtrace
+ tm_scope: source.c
+ ace_mode: c_cpp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-csrc
+ language_id: 85
+Darcs Patch:
+ type: data
+ aliases:
+ - dpatch
+ extensions:
+ - ".darcspatch"
+ - ".dpatch"
+ tm_scope: none
+ ace_mode: text
+ language_id: 86
+Dart:
+ type: programming
+ color: "#00B4AB"
+ extensions:
+ - ".dart"
+ interpreters:
+ - dart
+ ace_mode: dart
+ codemirror_mode: dart
+ codemirror_mime_type: application/dart
+ language_id: 87
+DataWeave:
+ type: programming
+ color: "#003a52"
+ extensions:
+ - ".dwl"
+ ace_mode: text
+ tm_scope: source.data-weave
+ language_id: 974514097
+Diff:
+ type: data
+ extensions:
+ - ".diff"
+ - ".patch"
+ aliases:
+ - udiff
+ tm_scope: source.diff
+ ace_mode: diff
+ codemirror_mode: diff
+ codemirror_mime_type: text/x-diff
+ language_id: 88
+Dockerfile:
+ type: programming
+ color: "#0db7ed"
+ tm_scope: source.dockerfile
+ extensions:
+ - ".dockerfile"
+ filenames:
+ - Dockerfile
+ ace_mode: dockerfile
+ codemirror_mode: dockerfile
+ codemirror_mime_type: text/x-dockerfile
+ language_id: 89
+Dogescript:
+ type: programming
+ color: "#cca760"
+ extensions:
+ - ".djs"
+ tm_scope: none
+ ace_mode: text
+ language_id: 90
+Dylan:
+ type: programming
+ color: "#6c616e"
+ extensions:
+ - ".dylan"
+ - ".dyl"
+ - ".intr"
+ - ".lid"
+ ace_mode: text
+ codemirror_mode: dylan
+ codemirror_mime_type: text/x-dylan
+ language_id: 91
+E:
+ type: programming
+ color: "#ccce35"
+ extensions:
+ - ".E"
+ interpreters:
+ - rune
+ tm_scope: none
+ ace_mode: text
+ language_id: 92
+EBNF:
+ type: data
+ extensions:
+ - ".ebnf"
+ tm_scope: source.ebnf
+ ace_mode: text
+ codemirror_mode: ebnf
+ codemirror_mime_type: text/x-ebnf
+ language_id: 430
+ECL:
+ type: programming
+ color: "#8a1267"
+ extensions:
+ - ".ecl"
+ - ".eclxml"
+ tm_scope: none
+ ace_mode: text
+ codemirror_mode: ecl
+ codemirror_mime_type: text/x-ecl
+ language_id: 93
+ECLiPSe:
+ type: programming
+ group: prolog
+ extensions:
+ - ".ecl"
+ tm_scope: source.prolog.eclipse
+ ace_mode: prolog
+ language_id: 94
+EJS:
+ type: markup
+ group: HTML
+ extensions:
+ - ".ejs"
+ tm_scope: text.html.js
+ ace_mode: ejs
+ language_id: 95
+EQ:
+ type: programming
+ color: "#a78649"
+ extensions:
+ - ".eq"
+ tm_scope: source.cs
+ ace_mode: csharp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-csharp
+ language_id: 96
+Eagle:
+ type: data
+ extensions:
+ - ".sch"
+ - ".brd"
+ tm_scope: text.xml
+ ace_mode: xml
+ codemirror_mode: xml
+ codemirror_mime_type: text/xml
+ language_id: 97
+Easybuild:
+ type: data
+ group: Python
+ ace_mode: python
+ codemirror_mode: python
+ codemirror_mime_type: text/x-python
+ tm_scope: source.python
+ extensions:
+ - ".eb"
+ language_id: 342840477
+Ecere Projects:
+ type: data
+ group: JavaScript
+ extensions:
+ - ".epj"
+ tm_scope: source.json
+ ace_mode: json
+ codemirror_mode: javascript
+ codemirror_mime_type: application/json
+ language_id: 98
+Edje Data Collection:
+ type: data
+ extensions:
+ - ".edc"
+ tm_scope: source.json
+ ace_mode: json
+ codemirror_mode: javascript
+ codemirror_mime_type: application/json
+ language_id: 342840478
+Eiffel:
+ type: programming
+ color: "#946d57"
+ extensions:
+ - ".e"
+ ace_mode: eiffel
+ codemirror_mode: eiffel
+ codemirror_mime_type: text/x-eiffel
+ language_id: 99
+Elixir:
+ type: programming
+ color: "#6e4a7e"
+ extensions:
+ - ".ex"
+ - ".exs"
+ ace_mode: elixir
+ filenames:
+ - mix.lock
+ interpreters:
+ - elixir
+ language_id: 100
+Elm:
+ type: programming
+ color: "#60B5CC"
+ extensions:
+ - ".elm"
+ tm_scope: source.elm
+ ace_mode: elm
+ codemirror_mode: elm
+ codemirror_mime_type: text/x-elm
+ language_id: 101
+Emacs Lisp:
+ type: programming
+ tm_scope: source.emacs.lisp
+ color: "#c065db"
+ aliases:
+ - elisp
+ - emacs
+ filenames:
+ - ".abbrev_defs"
+ - ".emacs"
+ - ".emacs.desktop"
+ - ".gnus"
+ - ".spacemacs"
+ - ".viper"
+ - Cask
+ - Project.ede
+ - _emacs
+ - abbrev_defs
+ extensions:
+ - ".el"
+ - ".emacs"
+ - ".emacs.desktop"
+ ace_mode: lisp
+ codemirror_mode: commonlisp
+ codemirror_mime_type: text/x-common-lisp
+ language_id: 102
+EmberScript:
+ type: programming
+ color: "#FFF4F3"
+ extensions:
+ - ".em"
+ - ".emberscript"
+ tm_scope: source.coffee
+ ace_mode: coffee
+ codemirror_mode: coffeescript
+ codemirror_mime_type: text/x-coffeescript
+ language_id: 103
+Erlang:
+ type: programming
+ color: "#B83998"
+ extensions:
+ - ".erl"
+ - ".app.src"
+ - ".es"
+ - ".escript"
+ - ".hrl"
+ - ".xrl"
+ - ".yrl"
+ filenames:
+ - Emakefile
+ - rebar.config
+ - rebar.config.lock
+ - rebar.lock
+ ace_mode: erlang
+ codemirror_mode: erlang
+ codemirror_mime_type: text/x-erlang
+ interpreters:
+ - escript
+ language_id: 104
+F#:
+ type: programming
+ color: "#b845fc"
+ aliases:
+ - fsharp
+ extensions:
+ - ".fs"
+ - ".fsi"
+ - ".fsx"
+ tm_scope: source.fsharp
+ ace_mode: text
+ codemirror_mode: mllike
+ codemirror_mime_type: text/x-fsharp
+ language_id: 105
+FLUX:
+ type: programming
+ color: "#88ccff"
+ extensions:
+ - ".fx"
+ - ".flux"
+ tm_scope: none
+ ace_mode: text
+ language_id: 106
+Factor:
+ type: programming
+ color: "#636746"
+ extensions:
+ - ".factor"
+ filenames:
+ - ".factor-boot-rc"
+ - ".factor-rc"
+ ace_mode: text
+ codemirror_mode: factor
+ codemirror_mime_type: text/x-factor
+ language_id: 108
+Fancy:
+ type: programming
+ color: "#7b9db4"
+ extensions:
+ - ".fy"
+ - ".fancypack"
+ filenames:
+ - Fakefile
+ ace_mode: text
+ language_id: 109
+Fantom:
+ type: programming
+ color: "#14253c"
+ extensions:
+ - ".fan"
+ tm_scope: source.fan
+ ace_mode: text
+ language_id: 110
+Filebench WML:
+ type: programming
+ extensions:
+ - ".f"
+ tm_scope: none
+ ace_mode: text
+ language_id: 111
+Filterscript:
+ type: programming
+ group: RenderScript
+ extensions:
+ - ".fs"
+ tm_scope: none
+ ace_mode: text
+ language_id: 112
+Formatted:
+ type: data
+ extensions:
+ - ".for"
+ - ".eam.fs"
+ tm_scope: none
+ ace_mode: text
+ language_id: 113
+Forth:
+ type: programming
+ color: "#341708"
+ extensions:
+ - ".fth"
+ - ".4th"
+ - ".f"
+ - ".for"
+ - ".forth"
+ - ".fr"
+ - ".frt"
+ - ".fs"
+ ace_mode: forth
+ codemirror_mode: forth
+ codemirror_mime_type: text/x-forth
+ language_id: 114
+Fortran:
+ type: programming
+ color: "#4d41b1"
+ extensions:
+ - ".f90"
+ - ".f"
+ - ".f03"
+ - ".f08"
+ - ".f77"
+ - ".f95"
+ - ".for"
+ - ".fpp"
+ tm_scope: source.fortran.modern
+ ace_mode: text
+ codemirror_mode: fortran
+ codemirror_mime_type: text/x-fortran
+ language_id: 107
+FreeMarker:
+ type: programming
+ color: "#0050b2"
+ aliases:
+ - ftl
+ extensions:
+ - ".ftl"
+ tm_scope: text.html.ftl
+ ace_mode: ftl
+ language_id: 115
+Frege:
+ type: programming
+ color: "#00cafe"
+ extensions:
+ - ".fr"
+ tm_scope: source.haskell
+ ace_mode: haskell
+ language_id: 116
+G-code:
+ type: data
+ extensions:
+ - ".g"
+ - ".gco"
+ - ".gcode"
+ tm_scope: source.gcode
+ ace_mode: gcode
+ language_id: 117
+GAMS:
+ type: programming
+ extensions:
+ - ".gms"
+ tm_scope: none
+ ace_mode: text
+ language_id: 118
+GAP:
+ type: programming
+ extensions:
+ - ".g"
+ - ".gap"
+ - ".gd"
+ - ".gi"
+ - ".tst"
+ tm_scope: source.gap
+ ace_mode: text
+ language_id: 119
+GCC Machine Description:
+ type: programming
+ extensions:
+ - ".md"
+ tm_scope: source.lisp
+ ace_mode: lisp
+ codemirror_mode: commonlisp
+ codemirror_mime_type: text/x-common-lisp
+ language_id: 121
+GDB:
+ type: programming
+ extensions:
+ - ".gdb"
+ - ".gdbinit"
+ tm_scope: source.gdb
+ ace_mode: text
+ language_id: 122
+GDScript:
+ type: programming
+ color: "#355570"
+ extensions:
+ - ".gd"
+ tm_scope: source.gdscript
+ ace_mode: text
+ language_id: 123
+GLSL:
+ type: programming
+ extensions:
+ - ".glsl"
+ - ".fp"
+ - ".frag"
+ - ".frg"
+ - ".fs"
+ - ".fsh"
+ - ".fshader"
+ - ".geo"
+ - ".geom"
+ - ".glslv"
+ - ".gshader"
+ - ".shader"
+ - ".tesc"
+ - ".tese"
+ - ".vert"
+ - ".vrx"
+ - ".vsh"
+ - ".vshader"
+ ace_mode: glsl
+ language_id: 124
+GN:
+ type: data
+ extensions:
+ - ".gn"
+ - ".gni"
+ interpreters:
+ - gn
+ filenames:
+ - ".gn"
+ tm_scope: source.gn
+ ace_mode: python
+ codemirror_mode: python
+ codemirror_mime_type: text/x-python
+ language_id: 302957008
+Game Maker Language:
+ type: programming
+ color: "#8fb200"
+ extensions:
+ - ".gml"
+ tm_scope: source.c++
+ ace_mode: c_cpp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-c++src
+ language_id: 125
+Genie:
+ type: programming
+ ace_mode: text
+ extensions:
+ - ".gs"
+ color: "#fb855d"
+ tm_scope: none
+ language_id: 792408528
+Genshi:
+ type: programming
+ extensions:
+ - ".kid"
+ tm_scope: text.xml.genshi
+ aliases:
+ - xml+genshi
+ - xml+kid
+ ace_mode: xml
+ codemirror_mode: xml
+ codemirror_mime_type: text/xml
+ language_id: 126
+Gentoo Ebuild:
+ type: programming
+ group: Shell
+ extensions:
+ - ".ebuild"
+ tm_scope: source.shell
+ ace_mode: sh
+ codemirror_mode: shell
+ codemirror_mime_type: text/x-sh
+ language_id: 127
+Gentoo Eclass:
+ type: programming
+ group: Shell
+ extensions:
+ - ".eclass"
+ tm_scope: source.shell
+ ace_mode: sh
+ codemirror_mode: shell
+ codemirror_mime_type: text/x-sh
+ language_id: 128
+Gerber Image:
+ type: data
+ aliases:
+ - rs-274x
+ extensions:
+ - ".gbr"
+ - ".gbl"
+ - ".gbo"
+ - ".gbp"
+ - ".gbs"
+ - ".gko"
+ - ".gpb"
+ - ".gpt"
+ - ".gtl"
+ - ".gto"
+ - ".gtp"
+ - ".gts"
+ interpreters:
+ - gerbv
+ - gerbview
+ tm_scope: source.gerber
+ ace_mode: text
+ language_id: 404627610
+Gettext Catalog:
+ type: prose
+ searchable: false
+ aliases:
+ - pot
+ extensions:
+ - ".po"
+ - ".pot"
+ tm_scope: source.po
+ ace_mode: text
+ language_id: 129
+Gherkin:
+ type: programming
+ extensions:
+ - ".feature"
+ tm_scope: text.gherkin.feature
+ aliases:
+ - cucumber
+ ace_mode: text
+ color: "#5B2063"
+ language_id: 76
+Glyph:
+ type: programming
+ color: "#c1ac7f"
+ extensions:
+ - ".glf"
+ tm_scope: source.tcl
+ ace_mode: tcl
+ codemirror_mode: tcl
+ codemirror_mime_type: text/x-tcl
+ language_id: 130
+Gnuplot:
+ type: programming
+ color: "#f0a9f0"
+ extensions:
+ - ".gp"
+ - ".gnu"
+ - ".gnuplot"
+ - ".plot"
+ - ".plt"
+ interpreters:
+ - gnuplot
+ ace_mode: text
+ language_id: 131
+Go:
+ type: programming
+ color: "#375eab"
+ aliases:
+ - golang
+ extensions:
+ - ".go"
+ ace_mode: golang
+ codemirror_mode: go
+ codemirror_mime_type: text/x-go
+ language_id: 132
+Golo:
+ type: programming
+ color: "#88562A"
+ extensions:
+ - ".golo"
+ tm_scope: source.golo
+ ace_mode: text
+ language_id: 133
+Gosu:
+ type: programming
+ color: "#82937f"
+ extensions:
+ - ".gs"
+ - ".gst"
+ - ".gsx"
+ - ".vark"
+ tm_scope: source.gosu.2
+ ace_mode: text
+ language_id: 134
+Grace:
+ type: programming
+ extensions:
+ - ".grace"
+ tm_scope: source.grace
+ ace_mode: text
+ language_id: 135
+Gradle:
+ type: data
+ extensions:
+ - ".gradle"
+ tm_scope: source.groovy.gradle
+ ace_mode: text
+ language_id: 136
+Grammatical Framework:
+ type: programming
+ aliases:
+ - gf
+ wrap: false
+ extensions:
+ - ".gf"
+ searchable: true
+ color: "#79aa7a"
+ tm_scope: source.haskell
+ ace_mode: haskell
+ codemirror_mode: haskell
+ codemirror_mime_type: text/x-haskell
+ language_id: 137
+Graph Modeling Language:
+ type: data
+ extensions:
+ - ".gml"
+ tm_scope: none
+ ace_mode: text
+ language_id: 138
+GraphQL:
+ type: data
+ extensions:
+ - ".graphql"
+ - ".gql"
+ tm_scope: source.graphql
+ ace_mode: text
+ language_id: 139
+Graphviz (DOT):
+ type: data
+ tm_scope: source.dot
+ extensions:
+ - ".dot"
+ - ".gv"
+ ace_mode: text
+ language_id: 140
+Groovy:
+ type: programming
+ ace_mode: groovy
+ codemirror_mode: groovy
+ codemirror_mime_type: text/x-groovy
+ color: "#e69f56"
+ extensions:
+ - ".groovy"
+ - ".grt"
+ - ".gtpl"
+ - ".gvy"
+ interpreters:
+ - groovy
+ filenames:
+ - Jenkinsfile
+ language_id: 142
+Groovy Server Pages:
+ type: programming
+ group: Groovy
+ aliases:
+ - gsp
+ - java server page
+ extensions:
+ - ".gsp"
+ tm_scope: text.html.jsp
+ ace_mode: jsp
+ codemirror_mode: htmlembedded
+ codemirror_mime_type: application/x-jsp
+ language_id: 143
+HCL:
+ type: programming
+ extensions:
+ - ".hcl"
+ - ".tf"
+ - ".tfvars"
+ ace_mode: ruby
+ codemirror_mode: ruby
+ codemirror_mime_type: text/x-ruby
+ tm_scope: source.terraform
+ language_id: 144
+HLSL:
+ type: programming
+ extensions:
+ - ".hlsl"
+ - ".cginc"
+ - ".fx"
+ - ".fxh"
+ - ".hlsli"
+ ace_mode: text
+ tm_scope: source.hlsl
+ language_id: 145
+HTML:
+ type: markup
+ tm_scope: text.html.basic
+ ace_mode: html
+ codemirror_mode: htmlmixed
+ codemirror_mime_type: text/html
+ color: "#e34c26"
+ aliases:
+ - xhtml
+ extensions:
+ - ".html"
+ - ".htm"
+ - ".html.hl"
+ - ".inc"
+ - ".st"
+ - ".xht"
+ - ".xhtml"
+ language_id: 146
+HTML+Django:
+ type: markup
+ tm_scope: text.html.django
+ group: HTML
+ extensions:
+ - ".jinja"
+ - ".jinja2"
+ - ".mustache"
+ - ".njk"
+ aliases:
+ - django
+ - html+django/jinja
+ - html+jinja
+ - htmldjango
+ - njk
+ - nunjucks
+ ace_mode: django
+ codemirror_mode: django
+ codemirror_mime_type: text/x-django
+ language_id: 147
+HTML+ECR:
+ type: markup
+ tm_scope: text.html.ecr
+ group: HTML
+ aliases:
+ - ecr
+ extensions:
+ - ".ecr"
+ ace_mode: text
+ codemirror_mode: htmlmixed
+ codemirror_mime_type: text/html
+ language_id: 148
+HTML+EEX:
+ type: markup
+ tm_scope: text.html.elixir
+ group: HTML
+ aliases:
+ - eex
+ extensions:
+ - ".eex"
+ ace_mode: text
+ codemirror_mode: htmlmixed
+ codemirror_mime_type: text/html
+ language_id: 149
+HTML+ERB:
+ type: markup
+ tm_scope: text.html.erb
+ group: HTML
+ aliases:
+ - erb
+ extensions:
+ - ".erb"
+ - ".erb.deface"
+ ace_mode: text
+ codemirror_mode: htmlembedded
+ codemirror_mime_type: application/x-erb
+ language_id: 150
+HTML+PHP:
+ type: markup
+ tm_scope: text.html.php
+ group: HTML
+ extensions:
+ - ".phtml"
+ ace_mode: php
+ codemirror_mode: php
+ codemirror_mime_type: application/x-httpd-php
+ language_id: 151
+HTTP:
+ type: data
+ extensions:
+ - ".http"
+ tm_scope: source.httpspec
+ ace_mode: text
+ codemirror_mode: http
+ codemirror_mime_type: message/http
+ language_id: 152
+HXML:
+ type: data
+ ace_mode: text
+ extensions:
+ - ".hxml"
+ tm_scope: source.hxml
+ language_id: 786683730
+Hack:
+ type: programming
+ ace_mode: php
+ codemirror_mode: php
+ codemirror_mime_type: application/x-httpd-php
+ extensions:
+ - ".hh"
+ - ".php"
+ tm_scope: text.html.php
+ color: "#878787"
+ language_id: 153
+Haml:
+ group: HTML
+ type: markup
+ extensions:
+ - ".haml"
+ - ".haml.deface"
+ ace_mode: haml
+ codemirror_mode: haml
+ codemirror_mime_type: text/x-haml
+ language_id: 154
+Handlebars:
+ type: markup
+ group: HTML
+ aliases:
+ - hbs
+ - htmlbars
+ extensions:
+ - ".handlebars"
+ - ".hbs"
+ tm_scope: text.html.handlebars
+ ace_mode: handlebars
+ language_id: 155
+Harbour:
+ type: programming
+ color: "#0e60e3"
+ extensions:
+ - ".hb"
+ tm_scope: source.harbour
+ ace_mode: text
+ language_id: 156
+Haskell:
+ type: programming
+ color: "#5e5086"
+ extensions:
+ - ".hs"
+ - ".hsc"
+ interpreters:
+ - runhaskell
+ ace_mode: haskell
+ codemirror_mode: haskell
+ codemirror_mime_type: text/x-haskell
+ language_id: 157
+Haxe:
+ type: programming
+ ace_mode: haxe
+ codemirror_mode: haxe
+ codemirror_mime_type: text/x-haxe
+ color: "#df7900"
+ extensions:
+ - ".hx"
+ - ".hxsl"
+ tm_scope: source.hx
+ language_id: 158
+HiveQL:
+ type: programming
+ extensions:
+ - ".q"
+ color: "#dce200"
+ tm_scope: source.hql
+ ace_mode: sql
+ language_id: 931814087
+Hy:
+ type: programming
+ ace_mode: text
+ color: "#7790B2"
+ extensions:
+ - ".hy"
+ interpreters:
+ - "hy"
+ aliases:
+ - hylang
+ tm_scope: none
+ language_id: 159
+HyPhy:
+ type: programming
+ ace_mode: text
+ extensions:
+ - ".bf"
+ tm_scope: none
+ language_id: 160
+IDL:
+ type: programming
+ color: "#a3522f"
+ extensions:
+ - ".pro"
+ - ".dlm"
+ ace_mode: text
+ codemirror_mode: idl
+ codemirror_mime_type: text/x-idl
+ language_id: 161
+IGOR Pro:
+ type: programming
+ extensions:
+ - ".ipf"
+ aliases:
+ - igor
+ - igorpro
+ tm_scope: none
+ ace_mode: text
+ language_id: 162
+INI:
+ type: data
+ extensions:
+ - ".ini"
+ - ".cfg"
+ - ".prefs"
+ - ".pro"
+ - ".properties"
+ filenames:
+ - ".editorconfig"
+ - ".gitconfig"
+ - buildozer.spec
+ tm_scope: source.ini
+ aliases:
+ - dosini
+ ace_mode: ini
+ codemirror_mode: properties
+ codemirror_mime_type: text/x-properties
+ language_id: 163
+IRC log:
+ type: data
+ aliases:
+ - irc
+ - irc logs
+ extensions:
+ - ".irclog"
+ - ".weechatlog"
+ tm_scope: none
+ ace_mode: text
+ codemirror_mode: mirc
+ codemirror_mime_type: text/mirc
+ language_id: 164
+Idris:
+ type: programming
+ color: "#b30000"
+ extensions:
+ - ".idr"
+ - ".lidr"
+ ace_mode: text
+ tm_scope: source.idris
+ language_id: 165
+Inform 7:
+ type: programming
+ wrap: true
+ extensions:
+ - ".ni"
+ - ".i7x"
+ tm_scope: source.inform7
+ aliases:
+ - i7
+ - inform7
+ ace_mode: text
+ language_id: 166
+Inno Setup:
+ type: programming
+ extensions:
+ - ".iss"
+ tm_scope: none
+ ace_mode: text
+ language_id: 167
+Io:
+ type: programming
+ color: "#a9188d"
+ extensions:
+ - ".io"
+ interpreters:
+ - io
+ ace_mode: io
+ language_id: 168
+Ioke:
+ type: programming
+ color: "#078193"
+ extensions:
+ - ".ik"
+ interpreters:
+ - ioke
+ ace_mode: text
+ language_id: 169
+Isabelle:
+ type: programming
+ color: "#FEFE00"
+ extensions:
+ - ".thy"
+ tm_scope: source.isabelle.theory
+ ace_mode: text
+ language_id: 170
+Isabelle ROOT:
+ type: programming
+ group: Isabelle
+ filenames:
+ - ROOT
+ tm_scope: source.isabelle.root
+ ace_mode: text
+ language_id: 171
+J:
+ type: programming
+ color: "#9EEDFF"
+ extensions:
+ - ".ijs"
+ interpreters:
+ - jconsole
+ tm_scope: source.j
+ ace_mode: text
+ language_id: 172
+JFlex:
+ type: programming
+ group: Lex
+ extensions:
+ - ".flex"
+ - ".jflex"
+ tm_scope: source.jflex
+ ace_mode: text
+ language_id: 173
+JSON:
+ type: data
+ tm_scope: source.json
+ group: JavaScript
+ ace_mode: json
+ codemirror_mode: javascript
+ codemirror_mime_type: application/json
+ searchable: false
+ extensions:
+ - ".json"
+ - ".avsc"
+ - ".geojson"
+ - ".gltf"
+ - ".JSON-tmLanguage"
+ - ".jsonl"
+ - ".tfstate"
+ - ".tfstate.backup"
+ - ".topojson"
+ - ".webapp"
+ - ".webmanifest"
+ filenames:
+ - ".arcconfig"
+ - ".htmlhintrc"
+ - ".tern-config"
+ - ".tern-project"
+ - composer.lock
+ - mcmod.info
+ language_id: 174
+JSON with Comments:
+ type: data
+ group: JSON
+ tm_scope: source.js
+ ace_mode: javascript
+ codemirror_mode: javascript
+ codemirror_mime_type: text/javascript
+ aliases:
+ - jsonc
+ extensions:
+ - ".sublime-build"
+ - ".sublime-commands"
+ - ".sublime-completions"
+ - ".sublime-keymap"
+ - ".sublime-macro"
+ - ".sublime-menu"
+ - ".sublime-mousemap"
+ - ".sublime-project"
+ - ".sublime-settings"
+ - ".sublime-theme"
+ - ".sublime-workspace"
+ - ".sublime_metrics"
+ - ".sublime_session"
+ filenames:
+ - ".babelrc"
+ - ".eslintrc.json"
+ - ".jscsrc"
+ - ".jshintrc"
+ - ".jslintrc"
+ - tsconfig.json
+ language_id: 423
+JSON5:
+ type: data
+ extensions:
+ - ".json5"
+ tm_scope: source.js
+ ace_mode: javascript
+ codemirror_mode: javascript
+ codemirror_mime_type: application/json
+ language_id: 175
+JSONLD:
+ type: data
+ group: JavaScript
+ ace_mode: javascript
+ extensions:
+ - ".jsonld"
+ tm_scope: source.js
+ language_id: 176
+JSONiq:
+ color: "#40d47e"
+ type: programming
+ ace_mode: jsoniq
+ codemirror_mode: javascript
+ codemirror_mime_type: application/json
+ extensions:
+ - ".jq"
+ tm_scope: source.jq
+ language_id: 177
+JSX:
+ type: programming
+ group: JavaScript
+ extensions:
+ - ".jsx"
+ tm_scope: source.js.jsx
+ ace_mode: javascript
+ codemirror_mode: jsx
+ codemirror_mime_type: text/jsx
+ language_id: 178
+Jasmin:
+ type: programming
+ ace_mode: java
+ extensions:
+ - ".j"
+ tm_scope: source.jasmin
+ language_id: 180
+Java:
+ type: programming
+ ace_mode: java
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-java
+ color: "#b07219"
+ extensions:
+ - ".java"
+ language_id: 181
+Java Server Pages:
+ type: programming
+ group: Java
+ aliases:
+ - jsp
+ extensions:
+ - ".jsp"
+ tm_scope: text.html.jsp
+ ace_mode: jsp
+ codemirror_mode: htmlembedded
+ codemirror_mime_type: application/x-jsp
+ language_id: 182
+JavaScript:
+ type: programming
+ tm_scope: source.js
+ ace_mode: javascript
+ codemirror_mode: javascript
+ codemirror_mime_type: text/javascript
+ color: "#f1e05a"
+ aliases:
+ - js
+ - node
+ extensions:
+ - ".js"
+ - "._js"
+ - ".bones"
+ - ".es"
+ - ".es6"
+ - ".frag"
+ - ".gs"
+ - ".jake"
+ - ".jsb"
+ - ".jscad"
+ - ".jsfl"
+ - ".jsm"
+ - ".jss"
+ - ".mjs"
+ - ".njs"
+ - ".pac"
+ - ".sjs"
+ - ".ssjs"
+ - ".xsjs"
+ - ".xsjslib"
+ filenames:
+ - Jakefile
+ interpreters:
+ - node
+ language_id: 183
+Jison:
+ type: programming
+ group: Yacc
+ extensions:
+ - ".jison"
+ tm_scope: source.jison
+ ace_mode: text
+ language_id: 284531423
+Jison Lex:
+ type: programming
+ group: Lex
+ extensions:
+ - ".jisonlex"
+ tm_scope: source.jisonlex
+ ace_mode: text
+ language_id: 406395330
+Jolie:
+ type: programming
+ extensions:
+ - ".ol"
+ - ".iol"
+ interpreters:
+ - jolie
+ color: "#843179"
+ ace_mode: text
+ tm_scope: source.jolie
+ language_id: 998078858
+Julia:
+ type: programming
+ extensions:
+ - ".jl"
+ interpreters:
+ - julia
+ color: "#a270ba"
+ ace_mode: julia
+ codemirror_mode: julia
+ codemirror_mime_type: text/x-julia
+ language_id: 184
+Jupyter Notebook:
+ type: markup
+ ace_mode: json
+ codemirror_mode: javascript
+ codemirror_mime_type: application/json
+ tm_scope: source.json
+ color: "#DA5B0B"
+ extensions:
+ - ".ipynb"
+ filenames:
+ - Notebook
+ aliases:
+ - IPython Notebook
+ language_id: 185
+KRL:
+ type: programming
+ color: "#28430A"
+ extensions:
+ - ".krl"
+ tm_scope: none
+ ace_mode: text
+ language_id: 186
+KiCad Layout:
+ type: data
+ aliases:
+ - pcbnew
+ extensions:
+ - ".kicad_pcb"
+ - ".kicad_mod"
+ - ".kicad_wks"
+ filenames:
+ - fp-lib-table
+ tm_scope: source.pcb.sexp
+ ace_mode: lisp
+ codemirror_mode: commonlisp
+ codemirror_mime_type: text/x-common-lisp
+ language_id: 187
+KiCad Legacy Layout:
+ type: data
+ extensions:
+ - ".brd"
+ tm_scope: source.pcb.board
+ ace_mode: text
+ language_id: 140848857
+KiCad Schematic:
+ type: data
+ aliases:
+ - eeschema schematic
+ extensions:
+ - ".sch"
+ tm_scope: source.pcb.schematic
+ ace_mode: text
+ language_id: 622447435
+Kit:
+ type: markup
+ ace_mode: html
+ codemirror_mode: htmlmixed
+ codemirror_mime_type: text/html
+ extensions:
+ - ".kit"
+ tm_scope: text.html.basic
+ language_id: 188
+Kotlin:
+ type: programming
+ color: "#F18E33"
+ extensions:
+ - ".kt"
+ - ".ktm"
+ - ".kts"
+ tm_scope: source.kotlin
+ ace_mode: text
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-kotlin
+ language_id: 189
+LFE:
+ type: programming
+ color: "#4C3023"
+ extensions:
+ - ".lfe"
+ tm_scope: source.lisp
+ ace_mode: lisp
+ codemirror_mode: commonlisp
+ codemirror_mime_type: text/x-common-lisp
+ language_id: 190
+LLVM:
+ type: programming
+ extensions:
+ - ".ll"
+ ace_mode: text
+ color: "#185619"
+ language_id: 191
+LOLCODE:
+ type: programming
+ extensions:
+ - ".lol"
+ color: "#cc9900"
+ tm_scope: none
+ ace_mode: text
+ language_id: 192
+LSL:
+ type: programming
+ ace_mode: lsl
+ extensions:
+ - ".lsl"
+ - ".lslp"
+ interpreters:
+ - lsl
+ color: "#3d9970"
+ language_id: 193
+LabVIEW:
+ type: programming
+ extensions:
+ - ".lvproj"
+ tm_scope: text.xml
+ ace_mode: xml
+ codemirror_mode: xml
+ codemirror_mime_type: text/xml
+ language_id: 194
+Lasso:
+ type: programming
+ color: "#999999"
+ extensions:
+ - ".lasso"
+ - ".las"
+ - ".lasso8"
+ - ".lasso9"
+ - ".ldml"
+ tm_scope: file.lasso
+ aliases:
+ - lassoscript
+ ace_mode: text
+ language_id: 195
+Latte:
+ type: markup
+ group: HTML
+ extensions:
+ - ".latte"
+ tm_scope: text.html.smarty
+ ace_mode: smarty
+ codemirror_mode: smarty
+ codemirror_mime_type: text/x-smarty
+ language_id: 196
+Lean:
+ type: programming
+ extensions:
+ - ".lean"
+ - ".hlean"
+ ace_mode: text
+ language_id: 197
+Less:
+ type: markup
+ group: CSS
+ extensions:
+ - ".less"
+ tm_scope: source.css.less
+ ace_mode: less
+ codemirror_mode: css
+ codemirror_mime_type: text/css
+ language_id: 198
+Lex:
+ type: programming
+ color: "#DBCA00"
+ aliases:
+ - flex
+ extensions:
+ - ".l"
+ - ".lex"
+ tm_scope: none
+ ace_mode: text
+ language_id: 199
+LilyPond:
+ type: programming
+ extensions:
+ - ".ly"
+ - ".ily"
+ ace_mode: text
+ language_id: 200
+Limbo:
+ type: programming
+ extensions:
+ - ".b"
+ - ".m"
+ tm_scope: none
+ ace_mode: text
+ language_id: 201
+Linker Script:
+ type: data
+ extensions:
+ - ".ld"
+ - ".lds"
+ - ".x"
+ filenames:
+ - ld.script
+ tm_scope: none
+ ace_mode: text
+ language_id: 202
+Linux Kernel Module:
+ type: data
+ extensions:
+ - ".mod"
+ tm_scope: none
+ ace_mode: text
+ language_id: 203
+Liquid:
+ type: markup
+ extensions:
+ - ".liquid"
+ tm_scope: text.html.liquid
+ ace_mode: liquid
+ language_id: 204
+Literate Agda:
+ type: programming
+ group: Agda
+ extensions:
+ - ".lagda"
+ tm_scope: none
+ ace_mode: text
+ language_id: 205
+Literate CoffeeScript:
+ type: programming
+ tm_scope: source.litcoffee
+ group: CoffeeScript
+ ace_mode: text
+ wrap: true
+ aliases:
+ - litcoffee
+ extensions:
+ - ".litcoffee"
+ language_id: 206
+Literate Haskell:
+ type: programming
+ group: Haskell
+ aliases:
+ - lhaskell
+ - lhs
+ extensions:
+ - ".lhs"
+ tm_scope: text.tex.latex.haskell
+ ace_mode: text
+ codemirror_mode: haskell-literate
+ codemirror_mime_type: text/x-literate-haskell
+ language_id: 207
+LiveScript:
+ type: programming
+ color: "#499886"
+ aliases:
+ - live-script
+ - ls
+ extensions:
+ - ".ls"
+ - "._ls"
+ filenames:
+ - Slakefile
+ ace_mode: livescript
+ codemirror_mode: livescript
+ codemirror_mime_type: text/x-livescript
+ language_id: 208
+Logos:
+ type: programming
+ extensions:
+ - ".xm"
+ - ".x"
+ - ".xi"
+ ace_mode: text
+ tm_scope: source.logos
+ language_id: 209
+Logtalk:
+ type: programming
+ extensions:
+ - ".lgt"
+ - ".logtalk"
+ ace_mode: text
+ language_id: 210
+LookML:
+ type: programming
+ ace_mode: yaml
+ codemirror_mode: yaml
+ codemirror_mime_type: text/x-yaml
+ color: "#652B81"
+ extensions:
+ - ".lookml"
+ - ".model.lkml"
+ - ".view.lkml"
+ tm_scope: source.yaml
+ language_id: 211
+LoomScript:
+ type: programming
+ extensions:
+ - ".ls"
+ tm_scope: source.loomscript
+ ace_mode: text
+ language_id: 212
+Lua:
+ type: programming
+ ace_mode: lua
+ codemirror_mode: lua
+ codemirror_mime_type: text/x-lua
+ color: "#000080"
+ extensions:
+ - ".lua"
+ - ".fcgi"
+ - ".nse"
+ - ".p8"
+ - ".pd_lua"
+ - ".rbxs"
+ - ".wlua"
+ interpreters:
+ - lua
+ language_id: 213
+M:
+ type: programming
+ aliases:
+ - mumps
+ extensions:
+ - ".mumps"
+ - ".m"
+ ace_mode: text
+ codemirror_mode: mumps
+ codemirror_mime_type: text/x-mumps
+ language_id: 214
+ tm_scope: none
+M4:
+ type: programming
+ extensions:
+ - ".m4"
+ tm_scope: none
+ ace_mode: text
+ language_id: 215
+M4Sugar:
+ type: programming
+ group: M4
+ aliases:
+ - autoconf
+ extensions:
+ - ".m4"
+ filenames:
+ - configure.ac
+ tm_scope: none
+ ace_mode: text
+ language_id: 216
+MAXScript:
+ type: programming
+ color: "#00a6a6"
+ extensions:
+ - ".ms"
+ - ".mcr"
+ tm_scope: source.maxscript
+ ace_mode: text
+ language_id: 217
+MQL4:
+ type: programming
+ color: "#62A8D6"
+ extensions:
+ - ".mq4"
+ - ".mqh"
+ tm_scope: source.mql5
+ ace_mode: c_cpp
+ language_id: 426
+MQL5:
+ type: programming
+ color: "#4A76B8"
+ extensions:
+ - ".mq5"
+ - ".mqh"
+ tm_scope: source.mql5
+ ace_mode: c_cpp
+ language_id: 427
+MTML:
+ type: markup
+ color: "#b7e1f4"
+ extensions:
+ - ".mtml"
+ tm_scope: text.html.basic
+ ace_mode: html
+ codemirror_mode: htmlmixed
+ codemirror_mime_type: text/html
+ language_id: 218
+MUF:
+ type: programming
+ group: Forth
+ extensions:
+ - ".muf"
+ - ".m"
+ tm_scope: none
+ ace_mode: forth
+ codemirror_mode: forth
+ codemirror_mime_type: text/x-forth
+ language_id: 219
+Makefile:
+ type: programming
+ color: "#427819"
+ aliases:
+ - bsdmake
+ - make
+ - mf
+ extensions:
+ - ".mak"
+ - ".d"
+ - ".make"
+ - ".mk"
+ - ".mkfile"
+ filenames:
+ - BSDmakefile
+ - GNUmakefile
+ - Kbuild
+ - Makefile
+ - Makefile.am
+ - Makefile.boot
+ - Makefile.frag
+ - Makefile.in
+ - Makefile.inc
+ - Makefile.wat
+ - makefile
+ - makefile.sco
+ - mkfile
+ interpreters:
+ - make
+ ace_mode: makefile
+ codemirror_mode: cmake
+ codemirror_mime_type: text/x-cmake
+ language_id: 220
+Mako:
+ type: programming
+ extensions:
+ - ".mako"
+ - ".mao"
+ tm_scope: text.html.mako
+ ace_mode: text
+ language_id: 221
+Markdown:
+ type: prose
+ aliases:
+ - pandoc
+ ace_mode: markdown
+ codemirror_mode: gfm
+ codemirror_mime_type: text/x-gfm
+ wrap: true
+ extensions:
+ - ".md"
+ - ".markdown"
+ - ".mdown"
+ - ".mdwn"
+ - ".mkd"
+ - ".mkdn"
+ - ".mkdown"
+ - ".ronn"
+ - ".workbook"
+ tm_scope: source.gfm
+ language_id: 222
+Marko:
+ group: HTML
+ type: markup
+ tm_scope: text.marko
+ extensions:
+ - ".marko"
+ aliases:
+ - markojs
+ ace_mode: text
+ codemirror_mode: htmlmixed
+ codemirror_mime_type: text/html
+ language_id: 932782397
+Mask:
+ type: markup
+ color: "#f97732"
+ ace_mode: mask
+ extensions:
+ - ".mask"
+ tm_scope: source.mask
+ language_id: 223
+Mathematica:
+ type: programming
+ extensions:
+ - ".mathematica"
+ - ".cdf"
+ - ".m"
+ - ".ma"
+ - ".mt"
+ - ".nb"
+ - ".nbp"
+ - ".wl"
+ - ".wlt"
+ aliases:
+ - mma
+ ace_mode: text
+ codemirror_mode: mathematica
+ codemirror_mime_type: text/x-mathematica
+ language_id: 224
+Matlab:
+ type: programming
+ color: "#e16737"
+ aliases:
+ - octave
+ extensions:
+ - ".matlab"
+ - ".m"
+ ace_mode: matlab
+ codemirror_mode: octave
+ codemirror_mime_type: text/x-octave
+ language_id: 225
+Maven POM:
+ type: data
+ tm_scope: text.xml.pom
+ filenames:
+ - pom.xml
+ ace_mode: xml
+ codemirror_mode: xml
+ codemirror_mime_type: text/xml
+ language_id: 226
+Max:
+ type: programming
+ color: "#c4a79c"
+ aliases:
+ - max/msp
+ - maxmsp
+ extensions:
+ - ".maxpat"
+ - ".maxhelp"
+ - ".maxproj"
+ - ".mxt"
+ - ".pat"
+ tm_scope: source.json
+ ace_mode: json
+ codemirror_mode: javascript
+ codemirror_mime_type: application/json
+ language_id: 227
+MediaWiki:
+ type: prose
+ wrap: true
+ extensions:
+ - ".mediawiki"
+ - ".wiki"
+ tm_scope: text.html.mediawiki
+ ace_mode: text
+ language_id: 228
+Mercury:
+ type: programming
+ color: "#ff2b2b"
+ ace_mode: prolog
+ interpreters:
+ - mmi
+ extensions:
+ - ".m"
+ - ".moo"
+ tm_scope: source.mercury
+ language_id: 229
+Meson:
+ type: programming
+ color: "#007800"
+ filenames:
+ - meson.build
+ - meson_options.txt
+ tm_scope: source.meson
+ ace_mode: text
+ language_id: 799141244
+Metal:
+ type: programming
+ color: "#8f14e9"
+ extensions:
+ - ".metal"
+ tm_scope: source.c++
+ ace_mode: c_cpp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-c++src
+ language_id: 230
+MiniD:
+ type: programming
+ searchable: false
+ extensions:
+ - ".minid"
+ tm_scope: none
+ ace_mode: text
+ language_id: 231
+Mirah:
+ type: programming
+ color: "#c7a938"
+ extensions:
+ - ".druby"
+ - ".duby"
+ - ".mirah"
+ tm_scope: source.ruby
+ ace_mode: ruby
+ codemirror_mode: ruby
+ codemirror_mime_type: text/x-ruby
+ language_id: 232
+Modelica:
+ type: programming
+ extensions:
+ - ".mo"
+ tm_scope: source.modelica
+ ace_mode: text
+ codemirror_mode: modelica
+ codemirror_mime_type: text/x-modelica
+ language_id: 233
+Modula-2:
+ type: programming
+ extensions:
+ - ".mod"
+ tm_scope: source.modula2
+ ace_mode: text
+ language_id: 234
+Modula-3:
+ type: programming
+ extensions:
+ - ".i3"
+ - ".ig"
+ - ".m3"
+ - ".mg"
+ color: "#223388"
+ ace_mode: text
+ tm_scope: source.modula-3
+ language_id: 564743864
+Module Management System:
+ type: programming
+ extensions:
+ - ".mms"
+ - ".mmk"
+ filenames:
+ - descrip.mmk
+ - descrip.mms
+ tm_scope: none
+ ace_mode: text
+ language_id: 235
+Monkey:
+ type: programming
+ extensions:
+ - ".monkey"
+ - ".monkey2"
+ ace_mode: text
+ tm_scope: source.monkey
+ language_id: 236
+Moocode:
+ type: programming
+ extensions:
+ - ".moo"
+ tm_scope: none
+ ace_mode: text
+ language_id: 237
+MoonScript:
+ type: programming
+ extensions:
+ - ".moon"
+ interpreters:
+ - moon
+ ace_mode: text
+ language_id: 238
+Myghty:
+ type: programming
+ extensions:
+ - ".myt"
+ tm_scope: none
+ ace_mode: text
+ language_id: 239
+NCL:
+ type: programming
+ color: "#28431f"
+ extensions:
+ - ".ncl"
+ tm_scope: source.ncl
+ ace_mode: text
+ language_id: 240
+NL:
+ type: data
+ extensions:
+ - ".nl"
+ tm_scope: none
+ ace_mode: text
+ language_id: 241
+NSIS:
+ type: programming
+ extensions:
+ - ".nsi"
+ - ".nsh"
+ ace_mode: text
+ codemirror_mode: nsis
+ codemirror_mime_type: text/x-nsis
+ language_id: 242
+Nearley:
+ type: programming
+ ace_mode: text
+ color: "#990000"
+ extensions:
+ - ".ne"
+ - ".nearley"
+ tm_scope: source.ne
+ language_id: 521429430
+Nemerle:
+ type: programming
+ color: "#3d3c6e"
+ extensions:
+ - ".n"
+ ace_mode: text
+ language_id: 243
+NetLinx:
+ type: programming
+ color: "#0aa0ff"
+ extensions:
+ - ".axs"
+ - ".axi"
+ tm_scope: source.netlinx
+ ace_mode: text
+ language_id: 244
+NetLinx+ERB:
+ type: programming
+ color: "#747faa"
+ extensions:
+ - ".axs.erb"
+ - ".axi.erb"
+ tm_scope: source.netlinx.erb
+ ace_mode: text
+ language_id: 245
+NetLogo:
+ type: programming
+ color: "#ff6375"
+ extensions:
+ - ".nlogo"
+ tm_scope: source.lisp
+ ace_mode: lisp
+ codemirror_mode: commonlisp
+ codemirror_mime_type: text/x-common-lisp
+ language_id: 246
+NewLisp:
+ type: programming
+ color: "#87AED7"
+ extensions:
+ - ".nl"
+ - ".lisp"
+ - ".lsp"
+ interpreters:
+ - newlisp
+ tm_scope: source.lisp
+ ace_mode: lisp
+ codemirror_mode: commonlisp
+ codemirror_mime_type: text/x-common-lisp
+ language_id: 247
+Nextflow:
+ type: programming
+ ace_mode: groovy
+ tm_scope: source.nextflow
+ color: "#3ac486"
+ extensions:
+ - ".nf"
+ filenames:
+ - nextflow.config
+ interpreters:
+ - nextflow
+ language_id: 506780613
+Nginx:
+ type: data
+ extensions:
+ - ".nginxconf"
+ - ".vhost"
+ filenames:
+ - nginx.conf
+ tm_scope: source.nginx
+ aliases:
+ - nginx configuration file
+ ace_mode: text
+ codemirror_mode: nginx
+ codemirror_mime_type: text/x-nginx-conf
+ language_id: 248
+Nim:
+ type: programming
+ color: "#37775b"
+ extensions:
+ - ".nim"
+ - ".nimrod"
+ ace_mode: text
+ tm_scope: source.nim
+ language_id: 249
+Ninja:
+ type: data
+ tm_scope: source.ninja
+ extensions:
+ - ".ninja"
+ ace_mode: text
+ language_id: 250
+Nit:
+ type: programming
+ color: "#009917"
+ extensions:
+ - ".nit"
+ tm_scope: source.nit
+ ace_mode: text
+ language_id: 251
+Nix:
+ type: programming
+ color: "#7e7eff"
+ extensions:
+ - ".nix"
+ aliases:
+ - nixos
+ tm_scope: source.nix
+ ace_mode: nix
+ language_id: 252
+Nu:
+ type: programming
+ color: "#c9df40"
+ aliases:
+ - nush
+ extensions:
+ - ".nu"
+ filenames:
+ - Nukefile
+ tm_scope: source.nu
+ ace_mode: scheme
+ codemirror_mode: scheme
+ codemirror_mime_type: text/x-scheme
+ interpreters:
+ - nush
+ language_id: 253
+NumPy:
+ type: programming
+ group: Python
+ extensions:
+ - ".numpy"
+ - ".numpyw"
+ - ".numsc"
+ tm_scope: none
+ ace_mode: text
+ codemirror_mode: python
+ codemirror_mime_type: text/x-python
+ language_id: 254
+OCaml:
+ type: programming
+ ace_mode: ocaml
+ codemirror_mode: mllike
+ codemirror_mime_type: text/x-ocaml
+ color: "#3be133"
+ extensions:
+ - ".ml"
+ - ".eliom"
+ - ".eliomi"
+ - ".ml4"
+ - ".mli"
+ - ".mll"
+ - ".mly"
+ interpreters:
+ - ocaml
+ - ocamlrun
+ - ocamlscript
+ tm_scope: source.ocaml
+ language_id: 255
+ObjDump:
+ type: data
+ extensions:
+ - ".objdump"
+ tm_scope: objdump.x86asm
+ ace_mode: assembly_x86
+ language_id: 256
+Objective-C:
+ type: programming
+ tm_scope: source.objc
+ color: "#438eff"
+ aliases:
+ - obj-c
+ - objc
+ - objectivec
+ extensions:
+ - ".m"
+ - ".h"
+ ace_mode: objectivec
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-objectivec
+ language_id: 257
+Objective-C++:
+ type: programming
+ tm_scope: source.objc++
+ color: "#6866fb"
+ aliases:
+ - obj-c++
+ - objc++
+ - objectivec++
+ extensions:
+ - ".mm"
+ ace_mode: objectivec
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-objectivec
+ language_id: 258
+Objective-J:
+ type: programming
+ color: "#ff0c5a"
+ aliases:
+ - obj-j
+ - objectivej
+ - objj
+ extensions:
+ - ".j"
+ - ".sj"
+ tm_scope: source.js.objj
+ ace_mode: text
+ language_id: 259
+Omgrofl:
+ type: programming
+ extensions:
+ - ".omgrofl"
+ color: "#cabbff"
+ tm_scope: none
+ ace_mode: text
+ language_id: 260
+Opa:
+ type: programming
+ extensions:
+ - ".opa"
+ ace_mode: text
+ language_id: 261
+Opal:
+ type: programming
+ color: "#f7ede0"
+ extensions:
+ - ".opal"
+ tm_scope: source.opal
+ ace_mode: text
+ language_id: 262
+OpenCL:
+ type: programming
+ group: C
+ extensions:
+ - ".cl"
+ - ".opencl"
+ tm_scope: source.c
+ ace_mode: c_cpp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-csrc
+ language_id: 263
+OpenEdge ABL:
+ type: programming
+ aliases:
+ - progress
+ - openedge
+ - abl
+ extensions:
+ - ".p"
+ - ".cls"
+ - ".w"
+ tm_scope: source.abl
+ ace_mode: text
+ language_id: 264
+OpenRC runscript:
+ type: programming
+ group: Shell
+ aliases:
+ - openrc
+ interpreters:
+ - openrc-run
+ tm_scope: source.shell
+ ace_mode: sh
+ codemirror_mode: shell
+ codemirror_mime_type: text/x-sh
+ language_id: 265
+OpenSCAD:
+ type: programming
+ extensions:
+ - ".scad"
+ tm_scope: source.scad
+ ace_mode: scad
+ language_id: 266
+OpenType Feature File:
+ type: data
+ aliases:
+ - AFDKO
+ extensions:
+ - ".fea"
+ tm_scope: source.opentype
+ ace_mode: text
+ language_id: 374317347
+Org:
+ type: prose
+ wrap: true
+ extensions:
+ - ".org"
+ tm_scope: none
+ ace_mode: text
+ language_id: 267
+Ox:
+ type: programming
+ extensions:
+ - ".ox"
+ - ".oxh"
+ - ".oxo"
+ tm_scope: source.ox
+ ace_mode: text
+ language_id: 268
+Oxygene:
+ type: programming
+ color: "#cdd0e3"
+ extensions:
+ - ".oxygene"
+ tm_scope: none
+ ace_mode: text
+ language_id: 269
+Oz:
+ type: programming
+ color: "#fab738"
+ extensions:
+ - ".oz"
+ tm_scope: source.oz
+ ace_mode: text
+ codemirror_mode: oz
+ codemirror_mime_type: text/x-oz
+ language_id: 270
+P4:
+ type: programming
+ color: "#7055b5"
+ extensions:
+ - ".p4"
+ tm_scope: source.p4
+ ace_mode: text
+ language_id: 348895984
+PAWN:
+ type: programming
+ color: "#dbb284"
+ extensions:
+ - ".pwn"
+ - ".inc"
+ tm_scope: source.pawn
+ ace_mode: text
+ language_id: 271
+PHP:
+ type: programming
+ tm_scope: text.html.php
+ ace_mode: php
+ codemirror_mode: php
+ codemirror_mime_type: application/x-httpd-php
+ color: "#4F5D95"
+ extensions:
+ - ".php"
+ - ".aw"
+ - ".ctp"
+ - ".fcgi"
+ - ".inc"
+ - ".php3"
+ - ".php4"
+ - ".php5"
+ - ".phps"
+ - ".phpt"
+ filenames:
+ - ".php"
+ - ".php_cs"
+ - ".php_cs.dist"
+ - Phakefile
+ interpreters:
+ - php
+ aliases:
+ - inc
+ language_id: 272
+PLSQL:
+ type: programming
+ ace_mode: sql
+ codemirror_mode: sql
+ codemirror_mime_type: text/x-plsql
+ tm_scope: none
+ color: "#dad8d8"
+ extensions:
+ - ".pls"
+ - ".bdy"
+ - ".ddl"
+ - ".fnc"
+ - ".pck"
+ - ".pkb"
+ - ".pks"
+ - ".plb"
+ - ".plsql"
+ - ".prc"
+ - ".spc"
+ - ".sql"
+ - ".tpb"
+ - ".tps"
+ - ".trg"
+ - ".vw"
+ language_id: 273
+PLpgSQL:
+ type: programming
+ ace_mode: pgsql
+ codemirror_mode: sql
+ codemirror_mime_type: text/x-sql
+ tm_scope: source.sql
+ extensions:
+ - ".sql"
+ language_id: 274
+POV-Ray SDL:
+ type: programming
+ aliases:
+ - pov-ray
+ - povray
+ extensions:
+ - ".pov"
+ - ".inc"
+ ace_mode: text
+ language_id: 275
+Pan:
+ type: programming
+ color: "#cc0000"
+ extensions:
+ - ".pan"
+ tm_scope: source.pan
+ ace_mode: text
+ language_id: 276
+Papyrus:
+ type: programming
+ color: "#6600cc"
+ extensions:
+ - ".psc"
+ tm_scope: source.papyrus.skyrim
+ ace_mode: text
+ language_id: 277
+Parrot:
+ type: programming
+ color: "#f3ca0a"
+ extensions:
+ - ".parrot"
+ tm_scope: none
+ ace_mode: text
+ language_id: 278
+Parrot Assembly:
+ group: Parrot
+ type: programming
+ aliases:
+ - pasm
+ extensions:
+ - ".pasm"
+ interpreters:
+ - parrot
+ tm_scope: none
+ ace_mode: text
+ language_id: 279
+Parrot Internal Representation:
+ group: Parrot
+ tm_scope: source.parrot.pir
+ type: programming
+ aliases:
+ - pir
+ extensions:
+ - ".pir"
+ interpreters:
+ - parrot
+ ace_mode: text
+ language_id: 280
+Pascal:
+ type: programming
+ color: "#E3F171"
+ extensions:
+ - ".pas"
+ - ".dfm"
+ - ".dpr"
+ - ".inc"
+ - ".lpr"
+ - ".pascal"
+ - ".pp"
+ interpreters:
+ - instantfpc
+ ace_mode: pascal
+ codemirror_mode: pascal
+ codemirror_mime_type: text/x-pascal
+ language_id: 281
+Pep8:
+ type: programming
+ color: "#C76F5B"
+ extensions:
+ - ".pep"
+ ace_mode: text
+ tm_scope: source.pep8
+ language_id: 840372442
+Perl:
+ type: programming
+ tm_scope: source.perl
+ ace_mode: perl
+ codemirror_mode: perl
+ codemirror_mime_type: text/x-perl
+ color: "#0298c3"
+ extensions:
+ - ".pl"
+ - ".al"
+ - ".cgi"
+ - ".fcgi"
+ - ".perl"
+ - ".ph"
+ - ".plx"
+ - ".pm"
+ - ".psgi"
+ - ".t"
+ filenames:
+ - Makefile.PL
+ - Rexfile
+ - ack
+ - cpanfile
+ interpreters:
+ - cperl
+ - perl
+ aliases:
+ - cperl
+ language_id: 282
+Perl 6:
+ type: programming
+ color: "#0000fb"
+ extensions:
+ - ".6pl"
+ - ".6pm"
+ - ".nqp"
+ - ".p6"
+ - ".p6l"
+ - ".p6m"
+ - ".pl"
+ - ".pl6"
+ - ".pm"
+ - ".pm6"
+ - ".t"
+ interpreters:
+ - perl6
+ aliases:
+ - perl6
+ tm_scope: source.perl6fe
+ ace_mode: perl
+ codemirror_mode: perl
+ codemirror_mime_type: text/x-perl
+ language_id: 283
+Pic:
+ type: markup
+ group: Roff
+ tm_scope: source.pic
+ extensions:
+ - ".pic"
+ - ".chem"
+ ace_mode: text
+ codemirror_mode: troff
+ codemirror_mime_type: text/troff
+ language_id: 425
+Pickle:
+ type: data
+ extensions:
+ - ".pkl"
+ tm_scope: none
+ ace_mode: text
+ language_id: 284
+PicoLisp:
+ type: programming
+ extensions:
+ - ".l"
+ interpreters:
+ - picolisp
+ - pil
+ tm_scope: source.lisp
+ ace_mode: lisp
+ language_id: 285
+PigLatin:
+ type: programming
+ color: "#fcd7de"
+ extensions:
+ - ".pig"
+ tm_scope: source.pig_latin
+ ace_mode: text
+ language_id: 286
+Pike:
+ type: programming
+ color: "#005390"
+ extensions:
+ - ".pike"
+ - ".pmod"
+ interpreters:
+ - pike
+ ace_mode: text
+ language_id: 287
+Pod:
+ type: prose
+ ace_mode: perl
+ codemirror_mode: perl
+ codemirror_mime_type: text/x-perl
+ wrap: true
+ extensions:
+ - ".pod"
+ interpreters:
+ - perl
+ tm_scope: none
+ language_id: 288
+PogoScript:
+ type: programming
+ color: "#d80074"
+ extensions:
+ - ".pogo"
+ tm_scope: source.pogoscript
+ ace_mode: text
+ language_id: 289
+Pony:
+ type: programming
+ extensions:
+ - ".pony"
+ tm_scope: source.pony
+ ace_mode: text
+ language_id: 290
+PostCSS:
+ type: markup
+ tm_scope: source.postcss
+ group: CSS
+ extensions:
+ - ".pcss"
+ ace_mode: text
+ language_id: 262764437
+PostScript:
+ type: markup
+ color: "#da291c"
+ extensions:
+ - ".ps"
+ - ".eps"
+ - ".pfa"
+ tm_scope: source.postscript
+ aliases:
+ - postscr
+ ace_mode: text
+ language_id: 291
+PowerBuilder:
+ type: programming
+ color: "#8f0f8d"
+ extensions:
+ - ".pbt"
+ - ".sra"
+ - ".sru"
+ - ".srw"
+ tm_scope: none
+ ace_mode: text
+ language_id: 292
+PowerShell:
+ type: programming
+ color: "#012456"
+ ace_mode: powershell
+ codemirror_mode: powershell
+ codemirror_mime_type: application/x-powershell
+ aliases:
+ - posh
+ - pwsh
+ extensions:
+ - ".ps1"
+ - ".psd1"
+ - ".psm1"
+ interpreters:
+ - pwsh
+ language_id: 293
+Processing:
+ type: programming
+ color: "#0096D8"
+ extensions:
+ - ".pde"
+ ace_mode: text
+ language_id: 294
+Prolog:
+ type: programming
+ color: "#74283c"
+ extensions:
+ - ".pl"
+ - ".pro"
+ - ".prolog"
+ - ".yap"
+ interpreters:
+ - swipl
+ - yap
+ tm_scope: source.prolog
+ ace_mode: prolog
+ language_id: 295
+Propeller Spin:
+ type: programming
+ color: "#7fa2a7"
+ extensions:
+ - ".spin"
+ tm_scope: source.spin
+ ace_mode: text
+ language_id: 296
+Protocol Buffer:
+ type: data
+ aliases:
+ - protobuf
+ - Protocol Buffers
+ extensions:
+ - ".proto"
+ tm_scope: source.protobuf
+ ace_mode: protobuf
+ codemirror_mode: protobuf
+ codemirror_mime_type: text/x-protobuf
+ language_id: 297
+Public Key:
+ type: data
+ extensions:
+ - ".asc"
+ - ".pub"
+ tm_scope: none
+ ace_mode: text
+ codemirror_mode: asciiarmor
+ codemirror_mime_type: application/pgp
+ language_id: 298
+Pug:
+ group: HTML
+ type: markup
+ extensions:
+ - ".jade"
+ - ".pug"
+ tm_scope: text.jade
+ ace_mode: jade
+ codemirror_mode: pug
+ codemirror_mime_type: text/x-pug
+ language_id: 179
+Puppet:
+ type: programming
+ color: "#302B6D"
+ extensions:
+ - ".pp"
+ filenames:
+ - Modulefile
+ ace_mode: text
+ codemirror_mode: puppet
+ codemirror_mime_type: text/x-puppet
+ tm_scope: source.puppet
+ language_id: 299
+Pure Data:
+ type: data
+ extensions:
+ - ".pd"
+ tm_scope: none
+ ace_mode: text
+ language_id: 300
+PureBasic:
+ type: programming
+ color: "#5a6986"
+ extensions:
+ - ".pb"
+ - ".pbi"
+ tm_scope: none
+ ace_mode: text
+ language_id: 301
+PureScript:
+ type: programming
+ color: "#1D222D"
+ extensions:
+ - ".purs"
+ tm_scope: source.purescript
+ ace_mode: haskell
+ codemirror_mode: haskell
+ codemirror_mime_type: text/x-haskell
+ language_id: 302
+Python:
+ type: programming
+ ace_mode: python
+ codemirror_mode: python
+ codemirror_mime_type: text/x-python
+ color: "#3572A5"
+ extensions:
+ - ".py"
+ - ".bzl"
+ - ".cgi"
+ - ".fcgi"
+ - ".gyp"
+ - ".gypi"
+ - ".lmi"
+ - ".py3"
+ - ".pyde"
+ - ".pyi"
+ - ".pyp"
+ - ".pyt"
+ - ".pyw"
+ - ".rpy"
+ - ".spec"
+ - ".tac"
+ - ".wsgi"
+ - ".xpy"
+ filenames:
+ - ".gclient"
+ - BUCK
+ - BUILD
+ - BUILD.bazel
+ - SConscript
+ - SConstruct
+ - Snakefile
+ - WORKSPACE
+ - wscript
+ interpreters:
+ - python
+ - python2
+ - python3
+ aliases:
+ - rusthon
+ - python3
+ language_id: 303
+Python console:
+ type: programming
+ group: Python
+ searchable: false
+ aliases:
+ - pycon
+ tm_scope: text.python.console
+ ace_mode: text
+ language_id: 428
+Python traceback:
+ type: data
+ group: Python
+ searchable: false
+ extensions:
+ - ".pytb"
+ tm_scope: text.python.traceback
+ ace_mode: text
+ language_id: 304
+QML:
+ type: programming
+ color: "#44a51c"
+ extensions:
+ - ".qml"
+ - ".qbs"
+ tm_scope: source.qml
+ ace_mode: text
+ language_id: 305
+QMake:
+ type: programming
+ extensions:
+ - ".pro"
+ - ".pri"
+ interpreters:
+ - qmake
+ ace_mode: text
+ language_id: 306
+Quake:
+ type: programming
+ filenames:
+ - m3makefile
+ - m3overrides
+ color: "#882233"
+ ace_mode: text
+ tm_scope: source.quake
+ language_id: 375265331
+R:
+ type: programming
+ color: "#198CE7"
+ aliases:
+ - R
+ - Rscript
+ - splus
+ extensions:
+ - ".r"
+ - ".rd"
+ - ".rsx"
+ filenames:
+ - ".Rprofile"
+ - expr-dist
+ interpreters:
+ - Rscript
+ ace_mode: r
+ codemirror_mode: r
+ codemirror_mime_type: text/x-rsrc
+ language_id: 307
+RAML:
+ type: markup
+ ace_mode: yaml
+ codemirror_mode: yaml
+ codemirror_mime_type: text/x-yaml
+ tm_scope: source.yaml
+ color: "#77d9fb"
+ extensions:
+ - ".raml"
+ language_id: 308
+RDoc:
+ type: prose
+ ace_mode: rdoc
+ wrap: true
+ extensions:
+ - ".rdoc"
+ tm_scope: text.rdoc
+ language_id: 309
+REALbasic:
+ type: programming
+ extensions:
+ - ".rbbas"
+ - ".rbfrm"
+ - ".rbmnu"
+ - ".rbres"
+ - ".rbtbar"
+ - ".rbuistate"
+ tm_scope: source.vbnet
+ ace_mode: text
+ language_id: 310
+REXX:
+ type: programming
+ aliases:
+ - arexx
+ extensions:
+ - ".rexx"
+ - ".pprx"
+ - ".rex"
+ interpreters:
+ - regina
+ - rexx
+ tm_scope: source.rexx
+ ace_mode: text
+ language_id: 311
+RHTML:
+ type: markup
+ group: HTML
+ extensions:
+ - ".rhtml"
+ tm_scope: text.html.erb
+ aliases:
+ - html+ruby
+ ace_mode: rhtml
+ codemirror_mode: htmlembedded
+ codemirror_mime_type: application/x-erb
+ language_id: 312
+RMarkdown:
+ type: prose
+ wrap: true
+ ace_mode: markdown
+ codemirror_mode: gfm
+ codemirror_mime_type: text/x-gfm
+ extensions:
+ - ".rmd"
+ tm_scope: source.gfm
+ language_id: 313
+RPC:
+ type: programming
+ aliases:
+ - rpcgen
+ - oncrpc
+ - xdr
+ ace_mode: c_cpp
+ extensions:
+ - ".x"
+ tm_scope: source.c
+ language_id: 1031374237
+RPM Spec:
+ type: data
+ tm_scope: source.rpm-spec
+ extensions:
+ - ".spec"
+ aliases:
+ - specfile
+ ace_mode: text
+ codemirror_mode: rpm
+ codemirror_mime_type: text/x-rpm-spec
+ language_id: 314
+RUNOFF:
+ type: markup
+ color: "#665a4e"
+ extensions:
+ - ".rnh"
+ - ".rno"
+ tm_scope: text.runoff
+ ace_mode: text
+ language_id: 315
+Racket:
+ type: programming
+ color: "#22228f"
+ extensions:
+ - ".rkt"
+ - ".rktd"
+ - ".rktl"
+ - ".scrbl"
+ interpreters:
+ - racket
+ tm_scope: source.racket
+ ace_mode: lisp
+ language_id: 316
+Ragel:
+ type: programming
+ color: "#9d5200"
+ extensions:
+ - ".rl"
+ aliases:
+ - ragel-rb
+ - ragel-ruby
+ tm_scope: none
+ ace_mode: text
+ language_id: 317
+Rascal:
+ type: programming
+ color: "#fffaa0"
+ extensions:
+ - ".rsc"
+ tm_scope: source.rascal
+ ace_mode: text
+ language_id: 173616037
+Raw token data:
+ type: data
+ aliases:
+ - raw
+ extensions:
+ - ".raw"
+ tm_scope: none
+ ace_mode: text
+ language_id: 318
+Reason:
+ type: programming
+ group: OCaml
+ ace_mode: rust
+ codemirror_mode: rust
+ codemirror_mime_type: text/x-rustsrc
+ extensions:
+ - ".re"
+ - ".rei"
+ interpreters:
+ - ocaml
+ tm_scope: source.reason
+ language_id: 869538413
+Rebol:
+ type: programming
+ color: "#358a5b"
+ extensions:
+ - ".reb"
+ - ".r"
+ - ".r2"
+ - ".r3"
+ - ".rebol"
+ ace_mode: text
+ tm_scope: source.rebol
+ language_id: 319
+Red:
+ type: programming
+ color: "#f50000"
+ extensions:
+ - ".red"
+ - ".reds"
+ aliases:
+ - red/system
+ tm_scope: source.red
+ ace_mode: text
+ language_id: 320
+Redcode:
+ type: programming
+ extensions:
+ - ".cw"
+ tm_scope: none
+ ace_mode: text
+ language_id: 321
+Regular Expression:
+ type: data
+ extensions:
+ - ".regexp"
+ - ".regex"
+ aliases:
+ - regexp
+ - regex
+ ace_mode: text
+ tm_scope: source.regexp
+ language_id: 363378884
+Ren'Py:
+ type: programming
+ aliases:
+ - renpy
+ color: "#ff7f7f"
+ extensions:
+ - ".rpy"
+ tm_scope: source.renpy
+ ace_mode: python
+ language_id: 322
+RenderScript:
+ type: programming
+ extensions:
+ - ".rs"
+ - ".rsh"
+ tm_scope: none
+ ace_mode: text
+ language_id: 323
+Ring:
+ type: programming
+ color: "#2D54CB"
+ extensions:
+ - ".ring"
+ tm_scope: source.ring
+ ace_mode: text
+ language_id: 431
+RobotFramework:
+ type: programming
+ extensions:
+ - ".robot"
+ tm_scope: text.robot
+ ace_mode: text
+ language_id: 324
+Roff:
+ type: markup
+ color: "#ecdebe"
+ extensions:
+ - ".man"
+ - ".1"
+ - ".1in"
+ - ".1m"
+ - ".1x"
+ - ".2"
+ - ".3"
+ - ".3in"
+ - ".3m"
+ - ".3qt"
+ - ".3x"
+ - ".4"
+ - ".5"
+ - ".6"
+ - ".7"
+ - ".8"
+ - ".9"
+ - ".l"
+ - ".me"
+ - ".ms"
+ - ".n"
+ - ".nr"
+ - ".rno"
+ - ".roff"
+ - ".tmac"
+ filenames:
+ - mmn
+ - mmt
+ tm_scope: text.roff
+ aliases:
+ - nroff
+ ace_mode: text
+ codemirror_mode: troff
+ codemirror_mime_type: text/troff
+ language_id: 141
+Rouge:
+ type: programming
+ ace_mode: clojure
+ codemirror_mode: clojure
+ codemirror_mime_type: text/x-clojure
+ color: "#cc0088"
+ extensions:
+ - ".rg"
+ tm_scope: source.clojure
+ language_id: 325
+Ruby:
+ type: programming
+ ace_mode: ruby
+ codemirror_mode: ruby
+ codemirror_mime_type: text/x-ruby
+ color: "#701516"
+ aliases:
+ - jruby
+ - macruby
+ - rake
+ - rb
+ - rbx
+ extensions:
+ - ".rb"
+ - ".builder"
+ - ".eye"
+ - ".fcgi"
+ - ".gemspec"
+ - ".god"
+ - ".jbuilder"
+ - ".mspec"
+ - ".pluginspec"
+ - ".podspec"
+ - ".rabl"
+ - ".rake"
+ - ".rbuild"
+ - ".rbw"
+ - ".rbx"
+ - ".ru"
+ - ".ruby"
+ - ".spec"
+ - ".thor"
+ - ".watchr"
+ interpreters:
+ - ruby
+ - macruby
+ - rake
+ - jruby
+ - rbx
+ filenames:
+ - ".irbrc"
+ - ".pryrc"
+ - Appraisals
+ - Berksfile
+ - Brewfile
+ - Buildfile
+ - Capfile
+ - Dangerfile
+ - Deliverfile
+ - Fastfile
+ - Gemfile
+ - Gemfile.lock
+ - Guardfile
+ - Jarfile
+ - Mavenfile
+ - Podfile
+ - Puppetfile
+ - Rakefile
+ - Snapfile
+ - Thorfile
+ - Vagrantfile
+ - buildfile
+ language_id: 326
+Rust:
+ type: programming
+ color: "#dea584"
+ extensions:
+ - ".rs"
+ - ".rs.in"
+ ace_mode: rust
+ codemirror_mode: rust
+ codemirror_mime_type: text/x-rustsrc
+ language_id: 327
+SAS:
+ type: programming
+ color: "#B34936"
+ extensions:
+ - ".sas"
+ tm_scope: source.sas
+ ace_mode: text
+ codemirror_mode: sas
+ codemirror_mime_type: text/x-sas
+ language_id: 328
+SCSS:
+ type: markup
+ tm_scope: source.scss
+ group: CSS
+ ace_mode: scss
+ codemirror_mode: css
+ codemirror_mime_type: text/x-scss
+ extensions:
+ - ".scss"
+ language_id: 329
+SMT:
+ type: programming
+ extensions:
+ - ".smt2"
+ - ".smt"
+ interpreters:
+ - boolector
+ - cvc4
+ - mathsat5
+ - opensmt
+ - smtinterpol
+ - smt-rat
+ - stp
+ - verit
+ - yices2
+ - z3
+ tm_scope: source.smt
+ ace_mode: text
+ language_id: 330
+SPARQL:
+ type: data
+ tm_scope: source.sparql
+ ace_mode: text
+ codemirror_mode: sparql
+ codemirror_mime_type: application/sparql-query
+ extensions:
+ - ".sparql"
+ - ".rq"
+ language_id: 331
+SQF:
+ type: programming
+ color: "#3F3F3F"
+ extensions:
+ - ".sqf"
+ - ".hqf"
+ tm_scope: source.sqf
+ ace_mode: text
+ language_id: 332
+SQL:
+ type: data
+ tm_scope: source.sql
+ ace_mode: sql
+ codemirror_mode: sql
+ codemirror_mime_type: text/x-sql
+ extensions:
+ - ".sql"
+ - ".cql"
+ - ".ddl"
+ - ".inc"
+ - ".mysql"
+ - ".prc"
+ - ".tab"
+ - ".udf"
+ - ".viw"
+ language_id: 333
+SQLPL:
+ type: programming
+ ace_mode: sql
+ codemirror_mode: sql
+ codemirror_mime_type: text/x-sql
+ tm_scope: source.sql
+ extensions:
+ - ".sql"
+ - ".db2"
+ language_id: 334
+SRecode Template:
+ type: markup
+ color: "#348a34"
+ tm_scope: source.lisp
+ ace_mode: lisp
+ codemirror_mode: commonlisp
+ codemirror_mime_type: text/x-common-lisp
+ extensions:
+ - ".srt"
+ language_id: 335
+STON:
+ type: data
+ group: Smalltalk
+ extensions:
+ - ".ston"
+ tm_scope: source.smalltalk
+ ace_mode: text
+ language_id: 336
+SVG:
+ type: data
+ extensions:
+ - ".svg"
+ tm_scope: text.xml
+ ace_mode: xml
+ codemirror_mode: xml
+ codemirror_mime_type: text/xml
+ language_id: 337
+Sage:
+ type: programming
+ group: Python
+ extensions:
+ - ".sage"
+ - ".sagews"
+ tm_scope: source.python
+ ace_mode: python
+ codemirror_mode: python
+ codemirror_mime_type: text/x-python
+ language_id: 338
+SaltStack:
+ type: programming
+ color: "#646464"
+ aliases:
+ - saltstate
+ - salt
+ extensions:
+ - ".sls"
+ tm_scope: source.yaml.salt
+ ace_mode: yaml
+ codemirror_mode: yaml
+ codemirror_mime_type: text/x-yaml
+ language_id: 339
+Sass:
+ type: markup
+ tm_scope: source.sass
+ group: CSS
+ extensions:
+ - ".sass"
+ ace_mode: sass
+ codemirror_mode: sass
+ codemirror_mime_type: text/x-sass
+ language_id: 340
+Scala:
+ type: programming
+ ace_mode: scala
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-scala
+ color: "#c22d40"
+ extensions:
+ - ".scala"
+ - ".kojo"
+ - ".sbt"
+ - ".sc"
+ interpreters:
+ - scala
+ language_id: 341
+Scaml:
+ group: HTML
+ type: markup
+ extensions:
+ - ".scaml"
+ tm_scope: source.scaml
+ ace_mode: text
+ language_id: 342
+Scheme:
+ type: programming
+ color: "#1e4aec"
+ extensions:
+ - ".scm"
+ - ".sch"
+ - ".sld"
+ - ".sls"
+ - ".sps"
+ - ".ss"
+ interpreters:
+ - guile
+ - bigloo
+ - chicken
+ - csi
+ - gosh
+ - r6rs
+ ace_mode: scheme
+ codemirror_mode: scheme
+ codemirror_mime_type: text/x-scheme
+ language_id: 343
+Scilab:
+ type: programming
+ extensions:
+ - ".sci"
+ - ".sce"
+ - ".tst"
+ ace_mode: text
+ language_id: 344
+Self:
+ type: programming
+ color: "#0579aa"
+ extensions:
+ - ".self"
+ tm_scope: none
+ ace_mode: text
+ language_id: 345
+ShaderLab:
+ type: programming
+ extensions:
+ - ".shader"
+ ace_mode: text
+ tm_scope: source.shaderlab
+ language_id: 664257356
+Shell:
+ type: programming
+ color: "#89e051"
+ aliases:
+ - sh
+ - shell-script
+ - bash
+ - zsh
+ extensions:
+ - ".sh"
+ - ".bash"
+ - ".bats"
+ - ".cgi"
+ - ".command"
+ - ".fcgi"
+ - ".ksh"
+ - ".sh.in"
+ - ".tmux"
+ - ".tool"
+ - ".zsh"
+ filenames:
+ - ".bash_history"
+ - ".bash_logout"
+ - ".bash_profile"
+ - ".bashrc"
+ - ".cshrc"
+ - ".login"
+ - ".profile"
+ - ".zlogin"
+ - ".zlogout"
+ - ".zprofile"
+ - ".zshenv"
+ - ".zshrc"
+ - 9fs
+ - PKGBUILD
+ - bash_logout
+ - bash_profile
+ - bashrc
+ - cshrc
+ - gradlew
+ - login
+ - man
+ - profile
+ - zlogin
+ - zlogout
+ - zprofile
+ - zshenv
+ - zshrc
+ interpreters:
+ - ash
+ - bash
+ - dash
+ - ksh
+ - mksh
+ - pdksh
+ - rc
+ - sh
+ - zsh
+ ace_mode: sh
+ codemirror_mode: shell
+ codemirror_mime_type: text/x-sh
+ language_id: 346
+ShellSession:
+ type: programming
+ extensions:
+ - ".sh-session"
+ aliases:
+ - bash session
+ - console
+ tm_scope: text.shell-session
+ ace_mode: sh
+ codemirror_mode: shell
+ codemirror_mime_type: text/x-sh
+ language_id: 347
+Shen:
+ type: programming
+ color: "#120F14"
+ extensions:
+ - ".shen"
+ tm_scope: source.shen
+ ace_mode: text
+ language_id: 348
+Slash:
+ type: programming
+ color: "#007eff"
+ extensions:
+ - ".sl"
+ tm_scope: text.html.slash
+ ace_mode: text
+ language_id: 349
+Slim:
+ group: HTML
+ type: markup
+ extensions:
+ - ".slim"
+ tm_scope: text.slim
+ ace_mode: text
+ codemirror_mode: slim
+ codemirror_mime_type: text/x-slim
+ language_id: 350
+Smali:
+ type: programming
+ extensions:
+ - ".smali"
+ ace_mode: text
+ tm_scope: source.smali
+ language_id: 351
+Smalltalk:
+ type: programming
+ color: "#596706"
+ extensions:
+ - ".st"
+ - ".cs"
+ aliases:
+ - squeak
+ ace_mode: text
+ codemirror_mode: smalltalk
+ codemirror_mime_type: text/x-stsrc
+ language_id: 352
+Smarty:
+ type: programming
+ extensions:
+ - ".tpl"
+ ace_mode: smarty
+ codemirror_mode: smarty
+ codemirror_mime_type: text/x-smarty
+ tm_scope: text.html.smarty
+ language_id: 353
+Solidity:
+ type: programming
+ color: "#AA6746"
+ ace_mode: text
+ tm_scope: source.solidity
+ language_id: 237469032
+SourcePawn:
+ type: programming
+ color: "#5c7611"
+ aliases:
+ - sourcemod
+ extensions:
+ - ".sp"
+ - ".inc"
+ - ".sma"
+ tm_scope: source.sp
+ ace_mode: text
+ language_id: 354
+Spline Font Database:
+ type: data
+ extensions:
+ - ".sfd"
+ tm_scope: text.sfd
+ ace_mode: yaml
+ language_id: 767169629
+Squirrel:
+ type: programming
+ color: "#800000"
+ extensions:
+ - ".nut"
+ tm_scope: source.c++
+ ace_mode: c_cpp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-c++src
+ language_id: 355
+Stan:
+ type: programming
+ color: "#b2011d"
+ extensions:
+ - ".stan"
+ ace_mode: text
+ tm_scope: source.stan
+ language_id: 356
+Standard ML:
+ type: programming
+ color: "#dc566d"
+ aliases:
+ - sml
+ extensions:
+ - ".ML"
+ - ".fun"
+ - ".sig"
+ - ".sml"
+ tm_scope: source.ml
+ ace_mode: text
+ codemirror_mode: mllike
+ codemirror_mime_type: text/x-ocaml
+ language_id: 357
+Stata:
+ type: programming
+ extensions:
+ - ".do"
+ - ".ado"
+ - ".doh"
+ - ".ihlp"
+ - ".mata"
+ - ".matah"
+ - ".sthlp"
+ ace_mode: text
+ language_id: 358
+Stylus:
+ type: markup
+ group: CSS
+ extensions:
+ - ".styl"
+ tm_scope: source.stylus
+ ace_mode: stylus
+ language_id: 359
+SubRip Text:
+ type: data
+ extensions:
+ - ".srt"
+ ace_mode: text
+ tm_scope: text.srt
+ language_id: 360
+SugarSS:
+ type: markup
+ tm_scope: source.css.postcss.sugarss
+ group: CSS
+ extensions:
+ - ".sss"
+ ace_mode: text
+ language_id: 826404698
+SuperCollider:
+ type: programming
+ color: "#46390b"
+ extensions:
+ - ".sc"
+ - ".scd"
+ interpreters:
+ - sclang
+ - scsynth
+ tm_scope: source.supercollider
+ ace_mode: text
+ language_id: 361
+Swift:
+ type: programming
+ color: "#ffac45"
+ extensions:
+ - ".swift"
+ ace_mode: text
+ codemirror_mode: swift
+ codemirror_mime_type: text/x-swift
+ language_id: 362
+SystemVerilog:
+ type: programming
+ color: "#DAE1C2"
+ extensions:
+ - ".sv"
+ - ".svh"
+ - ".vh"
+ ace_mode: verilog
+ codemirror_mode: verilog
+ codemirror_mime_type: text/x-systemverilog
+ language_id: 363
+TI Program:
+ type: programming
+ ace_mode: text
+ color: "#A0AA87"
+ extensions:
+ - ".8xp"
+ - ".8xk"
+ - ".8xk.txt"
+ - ".8xp.txt"
+ language_id: 422
+ tm_scope: none
+TLA:
+ type: programming
+ extensions:
+ - ".tla"
+ tm_scope: source.tla
+ ace_mode: text
+ language_id: 364
+TOML:
+ type: data
+ extensions:
+ - ".toml"
+ filenames:
+ - Cargo.lock
+ - Gopkg.lock
+ tm_scope: source.toml
+ ace_mode: toml
+ codemirror_mode: toml
+ codemirror_mime_type: text/x-toml
+ language_id: 365
+TXL:
+ type: programming
+ extensions:
+ - ".txl"
+ tm_scope: source.txl
+ ace_mode: text
+ language_id: 366
+Tcl:
+ type: programming
+ color: "#e4cc98"
+ extensions:
+ - ".tcl"
+ - ".adp"
+ - ".tm"
+ filenames:
+ - owh
+ - starfield
+ interpreters:
+ - tclsh
+ - wish
+ ace_mode: tcl
+ codemirror_mode: tcl
+ codemirror_mime_type: text/x-tcl
+ language_id: 367
+Tcsh:
+ type: programming
+ group: Shell
+ extensions:
+ - ".tcsh"
+ - ".csh"
+ tm_scope: source.shell
+ ace_mode: sh
+ codemirror_mode: shell
+ codemirror_mime_type: text/x-sh
+ language_id: 368
+TeX:
+ type: markup
+ color: "#3D6117"
+ ace_mode: tex
+ codemirror_mode: stex
+ codemirror_mime_type: text/x-stex
+ wrap: true
+ aliases:
+ - latex
+ extensions:
+ - ".tex"
+ - ".aux"
+ - ".bbx"
+ - ".bib"
+ - ".cbx"
+ - ".cls"
+ - ".dtx"
+ - ".ins"
+ - ".lbx"
+ - ".ltx"
+ - ".mkii"
+ - ".mkiv"
+ - ".mkvi"
+ - ".sty"
+ - ".toc"
+ language_id: 369
+Tea:
+ type: markup
+ extensions:
+ - ".tea"
+ tm_scope: source.tea
+ ace_mode: text
+ language_id: 370
+Terra:
+ type: programming
+ extensions:
+ - ".t"
+ color: "#00004c"
+ ace_mode: lua
+ codemirror_mode: lua
+ codemirror_mime_type: text/x-lua
+ interpreters:
+ - lua
+ language_id: 371
+Text:
+ type: prose
+ wrap: true
+ aliases:
+ - fundamental
+ extensions:
+ - ".txt"
+ - ".fr"
+ - ".nb"
+ - ".ncl"
+ - ".no"
+ filenames:
+ - COPYING
+ - COPYING.regex
+ - COPYRIGHT.regex
+ - FONTLOG
+ - INSTALL
+ - INSTALL.mysql
+ - LICENSE
+ - LICENSE.mysql
+ - NEWS
+ - README.1ST
+ - README.me
+ - README.mysql
+ - click.me
+ - delete.me
+ - keep.me
+ - read.me
+ - readme.1st
+ - test.me
+ tm_scope: none
+ ace_mode: text
+ language_id: 372
+Textile:
+ type: prose
+ ace_mode: textile
+ codemirror_mode: textile
+ codemirror_mime_type: text/x-textile
+ wrap: true
+ extensions:
+ - ".textile"
+ tm_scope: none
+ language_id: 373
+Thrift:
+ type: programming
+ tm_scope: source.thrift
+ extensions:
+ - ".thrift"
+ ace_mode: text
+ language_id: 374
+Turing:
+ type: programming
+ color: "#cf142b"
+ extensions:
+ - ".t"
+ - ".tu"
+ tm_scope: source.turing
+ ace_mode: text
+ language_id: 375
+Turtle:
+ type: data
+ extensions:
+ - ".ttl"
+ tm_scope: source.turtle
+ ace_mode: text
+ codemirror_mode: turtle
+ codemirror_mime_type: text/turtle
+ language_id: 376
+Twig:
+ type: markup
+ group: HTML
+ extensions:
+ - ".twig"
+ tm_scope: text.html.twig
+ ace_mode: twig
+ codemirror_mode: twig
+ codemirror_mime_type: text/x-twig
+ language_id: 377
+Type Language:
+ type: data
+ aliases:
+ - tl
+ extensions:
+ - ".tl"
+ tm_scope: source.tl
+ ace_mode: text
+ language_id: 632765617
+TypeScript:
+ type: programming
+ color: "#2b7489"
+ aliases:
+ - ts
+ extensions:
+ - ".ts"
+ - ".tsx"
+ tm_scope: source.ts
+ ace_mode: typescript
+ codemirror_mode: javascript
+ codemirror_mime_type: application/typescript
+ language_id: 378
+Unified Parallel C:
+ type: programming
+ group: C
+ ace_mode: c_cpp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-csrc
+ extensions:
+ - ".upc"
+ tm_scope: source.c
+ language_id: 379
+Unity3D Asset:
+ type: data
+ ace_mode: yaml
+ codemirror_mode: yaml
+ codemirror_mime_type: text/x-yaml
+ extensions:
+ - ".anim"
+ - ".asset"
+ - ".mat"
+ - ".meta"
+ - ".prefab"
+ - ".unity"
+ tm_scope: source.yaml
+ language_id: 380
+Unix Assembly:
+ type: programming
+ group: Assembly
+ extensions:
+ - ".s"
+ - ".ms"
+ tm_scope: source.x86
+ ace_mode: assembly_x86
+ language_id: 120
+Uno:
+ type: programming
+ extensions:
+ - ".uno"
+ ace_mode: csharp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-csharp
+ tm_scope: source.cs
+ language_id: 381
+UnrealScript:
+ type: programming
+ color: "#a54c4d"
+ extensions:
+ - ".uc"
+ tm_scope: source.java
+ ace_mode: java
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-java
+ language_id: 382
+UrWeb:
+ type: programming
+ aliases:
+ - Ur/Web
+ - Ur
+ extensions:
+ - ".ur"
+ - ".urs"
+ tm_scope: source.ur
+ ace_mode: text
+ language_id: 383
+VCL:
+ type: programming
+ color: "#148AA8"
+ extensions:
+ - ".vcl"
+ tm_scope: source.varnish.vcl
+ ace_mode: text
+ language_id: 384
+VHDL:
+ type: programming
+ color: "#adb2cb"
+ extensions:
+ - ".vhdl"
+ - ".vhd"
+ - ".vhf"
+ - ".vhi"
+ - ".vho"
+ - ".vhs"
+ - ".vht"
+ - ".vhw"
+ ace_mode: vhdl
+ codemirror_mode: vhdl
+ codemirror_mime_type: text/x-vhdl
+ language_id: 385
+Vala:
+ type: programming
+ color: "#fbe5cd"
+ extensions:
+ - ".vala"
+ - ".vapi"
+ ace_mode: vala
+ language_id: 386
+Verilog:
+ type: programming
+ color: "#b2b7f8"
+ extensions:
+ - ".v"
+ - ".veo"
+ ace_mode: verilog
+ codemirror_mode: verilog
+ codemirror_mime_type: text/x-verilog
+ language_id: 387
+Vim script:
+ type: programming
+ color: "#199f4b"
+ tm_scope: source.viml
+ aliases:
+ - vim
+ - viml
+ - nvim
+ extensions:
+ - ".vim"
+ filenames:
+ - ".gvimrc"
+ - ".nvimrc"
+ - ".vimrc"
+ - _vimrc
+ - gvimrc
+ - nvimrc
+ - vimrc
+ ace_mode: text
+ language_id: 388
+Visual Basic:
+ type: programming
+ color: "#945db7"
+ extensions:
+ - ".vb"
+ - ".bas"
+ - ".cls"
+ - ".frm"
+ - ".frx"
+ - ".vba"
+ - ".vbhtml"
+ - ".vbs"
+ tm_scope: source.vbnet
+ aliases:
+ - vb.net
+ - vbnet
+ ace_mode: text
+ codemirror_mode: vb
+ codemirror_mime_type: text/x-vb
+ language_id: 389
+Volt:
+ type: programming
+ color: "#1F1F1F"
+ extensions:
+ - ".volt"
+ tm_scope: source.d
+ ace_mode: d
+ codemirror_mode: d
+ codemirror_mime_type: text/x-d
+ language_id: 390
+Vue:
+ type: markup
+ color: "#2c3e50"
+ extensions:
+ - ".vue"
+ tm_scope: text.html.vue
+ ace_mode: html
+ language_id: 391
+Wavefront Material:
+ type: data
+ extensions:
+ - ".mtl"
+ tm_scope: source.wavefront.mtl
+ ace_mode: text
+ language_id: 392
+Wavefront Object:
+ type: data
+ extensions:
+ - ".obj"
+ tm_scope: source.wavefront.obj
+ ace_mode: text
+ language_id: 393
+Web Ontology Language:
+ type: data
+ extensions:
+ - ".owl"
+ tm_scope: text.xml
+ ace_mode: xml
+ language_id: 394
+WebAssembly:
+ type: programming
+ color: "#04133b"
+ extensions:
+ - ".wast"
+ - ".wat"
+ aliases:
+ - wast
+ - wasm
+ tm_scope: source.webassembly
+ ace_mode: lisp
+ codemirror_mode: commonlisp
+ codemirror_mime_type: text/x-common-lisp
+ language_id: 956556503
+WebIDL:
+ type: programming
+ extensions:
+ - ".webidl"
+ tm_scope: source.webidl
+ ace_mode: text
+ codemirror_mode: webidl
+ codemirror_mime_type: text/x-webidl
+ language_id: 395
+World of Warcraft Addon Data:
+ type: data
+ extensions:
+ - ".toc"
+ tm_scope: source.toc
+ ace_mode: text
+ language_id: 396
+X BitMap:
+ type: data
+ group: C
+ aliases:
+ - xbm
+ extensions:
+ - ".xbm"
+ ace_mode: c_cpp
+ tm_scope: source.c
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-csrc
+ language_id: 782911107
+X PixMap:
+ type: data
+ group: C
+ aliases:
+ - xpm
+ extensions:
+ - ".xpm"
+ - ".pm"
+ ace_mode: c_cpp
+ tm_scope: source.c
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-csrc
+ language_id: 781846279
+X10:
+ type: programming
+ aliases:
+ - xten
+ ace_mode: text
+ extensions:
+ - ".x10"
+ color: "#4B6BEF"
+ tm_scope: source.x10
+ language_id: 397
+XC:
+ type: programming
+ color: "#99DA07"
+ extensions:
+ - ".xc"
+ tm_scope: source.xc
+ ace_mode: c_cpp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-csrc
+ language_id: 398
+XCompose:
+ type: data
+ filenames:
+ - ".XCompose"
+ - XCompose
+ - xcompose
+ tm_scope: config.xcompose
+ ace_mode: text
+ language_id: 225167241
+XML:
+ type: data
+ ace_mode: xml
+ codemirror_mode: xml
+ codemirror_mime_type: text/xml
+ aliases:
+ - rss
+ - xsd
+ - wsdl
+ extensions:
+ - ".xml"
+ - ".adml"
+ - ".admx"
+ - ".ant"
+ - ".axml"
+ - ".builds"
+ - ".ccproj"
+ - ".ccxml"
+ - ".clixml"
+ - ".cproject"
+ - ".cscfg"
+ - ".csdef"
+ - ".csl"
+ - ".csproj"
+ - ".ct"
+ - ".depproj"
+ - ".dita"
+ - ".ditamap"
+ - ".ditaval"
+ - ".dll.config"
+ - ".dotsettings"
+ - ".filters"
+ - ".fsproj"
+ - ".fxml"
+ - ".glade"
+ - ".gml"
+ - ".grxml"
+ - ".iml"
+ - ".ivy"
+ - ".jelly"
+ - ".jsproj"
+ - ".kml"
+ - ".launch"
+ - ".mdpolicy"
+ - ".mjml"
+ - ".mm"
+ - ".mod"
+ - ".mxml"
+ - ".natvis"
+ - ".ncl"
+ - ".ndproj"
+ - ".nproj"
+ - ".nuspec"
+ - ".odd"
+ - ".osm"
+ - ".pkgproj"
+ - ".plist"
+ - ".pluginspec"
+ - ".proj"
+ - ".props"
+ - ".ps1xml"
+ - ".psc1"
+ - ".pt"
+ - ".rdf"
+ - ".resx"
+ - ".rss"
+ - ".sch"
+ - ".scxml"
+ - ".sfproj"
+ - ".shproj"
+ - ".srdf"
+ - ".storyboard"
+ - ".stTheme"
+ - ".sublime-snippet"
+ - ".targets"
+ - ".tmCommand"
+ - ".tml"
+ - ".tmLanguage"
+ - ".tmPreferences"
+ - ".tmSnippet"
+ - ".tmTheme"
+ - ".ts"
+ - ".tsx"
+ - ".ui"
+ - ".urdf"
+ - ".ux"
+ - ".vbproj"
+ - ".vcxproj"
+ - ".vsixmanifest"
+ - ".vssettings"
+ - ".vstemplate"
+ - ".vxml"
+ - ".wixproj"
+ - ".wsdl"
+ - ".wsf"
+ - ".wxi"
+ - ".wxl"
+ - ".wxs"
+ - ".x3d"
+ - ".xacro"
+ - ".xaml"
+ - ".xib"
+ - ".xlf"
+ - ".xliff"
+ - ".xmi"
+ - ".xml.dist"
+ - ".xproj"
+ - ".xsd"
+ - ".xspec"
+ - ".xul"
+ - ".zcml"
+ filenames:
+ - ".classpath"
+ - ".cproject"
+ - ".project"
+ - App.config
+ - NuGet.config
+ - Settings.StyleCop
+ - Web.Debug.config
+ - Web.Release.config
+ - Web.config
+ - packages.config
+ language_id: 399
+XPages:
+ type: data
+ extensions:
+ - ".xsp-config"
+ - ".xsp.metadata"
+ tm_scope: text.xml
+ ace_mode: xml
+ codemirror_mode: xml
+ codemirror_mime_type: text/xml
+ language_id: 400
+XProc:
+ type: programming
+ extensions:
+ - ".xpl"
+ - ".xproc"
+ tm_scope: text.xml
+ ace_mode: xml
+ codemirror_mode: xml
+ codemirror_mime_type: text/xml
+ language_id: 401
+XQuery:
+ type: programming
+ color: "#5232e7"
+ extensions:
+ - ".xquery"
+ - ".xq"
+ - ".xql"
+ - ".xqm"
+ - ".xqy"
+ ace_mode: xquery
+ codemirror_mode: xquery
+ codemirror_mime_type: application/xquery
+ tm_scope: source.xq
+ language_id: 402
+XS:
+ type: programming
+ extensions:
+ - ".xs"
+ tm_scope: source.c
+ ace_mode: c_cpp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-csrc
+ language_id: 403
+XSLT:
+ type: programming
+ aliases:
+ - xsl
+ extensions:
+ - ".xslt"
+ - ".xsl"
+ tm_scope: text.xml.xsl
+ ace_mode: xml
+ codemirror_mode: xml
+ codemirror_mime_type: text/xml
+ color: "#EB8CEB"
+ language_id: 404
+Xojo:
+ type: programming
+ extensions:
+ - ".xojo_code"
+ - ".xojo_menu"
+ - ".xojo_report"
+ - ".xojo_script"
+ - ".xojo_toolbar"
+ - ".xojo_window"
+ tm_scope: source.vbnet
+ ace_mode: text
+ language_id: 405
+Xtend:
+ type: programming
+ extensions:
+ - ".xtend"
+ ace_mode: text
+ language_id: 406
+YAML:
+ type: data
+ tm_scope: source.yaml
+ aliases:
+ - yml
+ extensions:
+ - ".yml"
+ - ".mir"
+ - ".reek"
+ - ".rviz"
+ - ".sublime-syntax"
+ - ".syntax"
+ - ".yaml"
+ - ".yaml-tmlanguage"
+ - ".yml.mysql"
+ filenames:
+ - ".clang-format"
+ - ".clang-tidy"
+ - ".gemrc"
+ - glide.lock
+ ace_mode: yaml
+ codemirror_mode: yaml
+ codemirror_mime_type: text/x-yaml
+ language_id: 407
+YANG:
+ type: data
+ extensions:
+ - ".yang"
+ tm_scope: source.yang
+ ace_mode: text
+ language_id: 408
+YARA:
+ type: data
+ ace_mode: text
+ extensions:
+ - ".yar"
+ - ".yara"
+ tm_scope: source.yara
+ language_id: 805122868
+Yacc:
+ type: programming
+ extensions:
+ - ".y"
+ - ".yacc"
+ - ".yy"
+ tm_scope: source.bison
+ ace_mode: text
+ color: "#4B6C4B"
+ language_id: 409
+Zephir:
+ type: programming
+ color: "#118f9e"
+ extensions:
+ - ".zep"
+ tm_scope: source.php.zephir
+ ace_mode: php
+ language_id: 410
+Zimpl:
+ type: programming
+ extensions:
+ - ".zimpl"
+ - ".zmpl"
+ - ".zpl"
+ tm_scope: none
+ ace_mode: text
+ language_id: 411
+desktop:
+ type: data
+ extensions:
+ - ".desktop"
+ - ".desktop.in"
+ tm_scope: source.desktop
+ ace_mode: text
+ language_id: 412
+eC:
+ type: programming
+ color: "#913960"
+ extensions:
+ - ".ec"
+ - ".eh"
+ tm_scope: source.c.ec
+ ace_mode: text
+ language_id: 413
+edn:
+ type: data
+ ace_mode: clojure
+ codemirror_mode: clojure
+ codemirror_mime_type: text/x-clojure
+ extensions:
+ - ".edn"
+ tm_scope: source.clojure
+ language_id: 414
+fish:
+ type: programming
+ group: Shell
+ interpreters:
+ - fish
+ extensions:
+ - ".fish"
+ tm_scope: source.fish
+ ace_mode: text
+ language_id: 415
+mupad:
+ type: programming
+ extensions:
+ - ".mu"
+ ace_mode: text
+ language_id: 416
+nesC:
+ type: programming
+ color: "#94B0C7"
+ extensions:
+ - ".nc"
+ ace_mode: text
+ tm_scope: source.nesc
+ language_id: 417
+ooc:
+ type: programming
+ color: "#b0b77e"
+ extensions:
+ - ".ooc"
+ ace_mode: text
+ language_id: 418
+q:
+ type: programming
+ extensions:
+ - ".q"
+ tm_scope: source.q
+ ace_mode: text
+ color: "#0040cd"
+ language_id: 970539067
+reStructuredText:
+ type: prose
+ wrap: true
+ aliases:
+ - rst
+ extensions:
+ - ".rst"
+ - ".rest"
+ - ".rest.txt"
+ - ".rst.txt"
+ ace_mode: text
+ codemirror_mode: rst
+ codemirror_mime_type: text/x-rst
+ language_id: 419
+sed:
+ type: programming
+ color: "#64b970"
+ extensions:
+ - ".sed"
+ interpreters:
+ - gsed
+ - minised
+ - sed
+ - ssed
+ ace_mode: text
+ tm_scope: source.sed
+ language_id: 847830017
+wdl:
+ type: programming
+ color: "#42f1f4"
+ extensions:
+ - ".wdl"
+ tm_scope: source.wdl
+ ace_mode: text
+ language_id: 374521672
+wisp:
+ type: programming
+ ace_mode: clojure
+ codemirror_mode: clojure
+ codemirror_mime_type: text/x-clojure
+ color: "#7582D1"
+ extensions:
+ - ".wisp"
+ tm_scope: source.clojure
+ language_id: 420
+xBase:
+ type: programming
+ color: "#403a40"
+ aliases:
+ - advpl
+ - clipper
+ - foxpro
+ extensions:
+ - ".prg"
+ - ".ch"
+ - ".prw"
+ tm_scope: source.harbour
+ ace_mode: text
+ language_id: 421
diff --git a/yarn.lock b/yarn.lock
index 25ea8d7557c..5879ccb9267 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -616,10 +616,10 @@
lodash "^4.17.10"
to-fast-properties "^2.0.0"
-"@gitlab-org/gitlab-svgs@^1.23.0", "@gitlab-org/gitlab-svgs@^1.29.0":
- version "1.31.0"
- resolved "https://registry.yarnpkg.com/@gitlab-org/gitlab-svgs/-/gitlab-svgs-1.31.0.tgz#495b074669f93af40e34f9978ce887773dea470a"
- integrity sha512-tJbf99XX/ddFkXCXxQr9a0GJD9rPVoW3qMbU14dkxwG4WBmPEoVg+e7sLvm9OWTD1uUqiVW3qWKp++SGhhcRlw==
+"@gitlab-org/gitlab-svgs@^1.23.0", "@gitlab-org/gitlab-svgs@^1.32.0":
+ version "1.32.0"
+ resolved "https://registry.yarnpkg.com/@gitlab-org/gitlab-svgs/-/gitlab-svgs-1.32.0.tgz#a65ab7724fa7d55be8e5cc9b2dbe3f0757432fd3"
+ integrity sha512-L3o8dFUd2nSkVZBwh2hCJWzNzADJ3dTBZxamND8NLosZK9/ohNhccmsQOZGyMCUHaOzm4vifaaXkAXh04UtMKA==
"@gitlab-org/gitlab-ui@^1.8.0":
version "1.8.0"