diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-08-04 00:08:59 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-08-04 00:08:59 +0300 |
commit | e643b1a37690e16a3683aea0a3369e9723e17a35 (patch) | |
tree | 8f5d606291b2827eafac76b3413fe2793860317e | |
parent | b9b477a3f1e64590e087cfe2cc21c9d5bd448756 (diff) |
Add latest changes from gitlab-org/gitlab@master
33 files changed, 636 insertions, 906 deletions
diff --git a/.rubocop_todo/layout/space_inside_block_braces.yml b/.rubocop_todo/layout/space_inside_block_braces.yml index 7911a99169f..38ee4c862ca 100644 --- a/.rubocop_todo/layout/space_inside_block_braces.yml +++ b/.rubocop_todo/layout/space_inside_block_braces.yml @@ -51,52 +51,6 @@ Layout/SpaceInsideBlockBraces: - 'ee/lib/elastic/latest/git_class_proxy.rb' - 'ee/lib/gitlab/auth/smartcard/san_extension.rb' - 'ee/lib/world.rb' - - 'ee/spec/controllers/autocomplete_controller_spec.rb' - - 'ee/spec/controllers/countries_controller_spec.rb' - - 'ee/spec/controllers/groups/epics_controller_spec.rb' - - 'ee/spec/controllers/projects/issues_controller_spec.rb' - - 'ee/spec/controllers/projects/pipelines_controller_spec.rb' - - 'ee/spec/controllers/subscriptions_controller_spec.rb' - - 'ee/spec/elastic_integration/global_search_spec.rb' - - 'ee/spec/factories/dast/profiles_pipelines.rb' - - 'ee/spec/factories/licenses.rb' - - 'ee/spec/finders/billed_users_finder_spec.rb' - - 'ee/spec/finders/clusters/environments_finder_spec.rb' - - 'ee/spec/finders/dast/profiles_finder_spec.rb' - - 'ee/spec/finders/ee/namespaces/projects_finder_spec.rb' - - 'ee/spec/finders/security/pipeline_vulnerabilities_finder_spec.rb' - - 'ee/spec/finders/security/training_providers/kontra_url_finder_spec.rb' - - 'ee/spec/finders/security/vulnerabilities_finder_spec.rb' - - 'ee/spec/finders/security/vulnerability_reads_finder_spec.rb' - - 'ee/spec/finders/status_page/incidents_finder_spec.rb' - - 'ee/spec/frontend/fixtures/epic.rb' - - 'ee/spec/frontend/fixtures/projects.rb' - - 'ee/spec/helpers/ee/projects/pipeline_helper_spec.rb' - - 'ee/spec/helpers/ee/projects/security/dast_configuration_helper_spec.rb' - - 'ee/spec/helpers/ee/registrations_helper_spec.rb' - - 'ee/spec/helpers/ee/trial_helper_spec.rb' - - 'ee/spec/helpers/projects/on_demand_scans_helper_spec.rb' - - 'ee/spec/mailers/credentials_inventory_mailer_spec.rb' - - 'ee/spec/migrations/geo/migrate_job_artifact_registry_spec.rb' - - 'ee/spec/presenters/epic_issue_presenter_spec.rb' - - 'ee/spec/serializers/member_user_entity_spec.rb' - - 'ee/spec/serializers/merge_request_poll_widget_entity_spec.rb' - - 'ee/spec/serializers/vulnerabilities/finding_reports_comparer_entity_spec.rb' - - 'ee/spec/support/shared_examples/features/ultimate_trial_callout_shared_examples.rb' - - 'ee/spec/support/shared_examples/requests/api/project_approval_rules_api_shared_examples.rb' - - 'ee/spec/support/shared_examples/services/base_sync_service_shared_examples.rb' - - 'ee/spec/support/shared_examples/services/boards/base_service_shared_examples.rb' - - 'ee/spec/support/shared_examples/services/search_notes_shared_examples.rb' - - 'ee/spec/tasks/gitlab/elastic_rake_spec.rb' - - 'ee/spec/views/registrations/groups_projects/new.html.haml_spec.rb' - - 'ee/spec/views/shared/billings/_eoa_bronze_plan_banner.html.haml_spec.rb' - - 'ee/spec/views/shared/credentials_inventory/_expiry_date.html.haml_spec.rb' - - 'ee/spec/views/shared/credentials_inventory/personal_access_tokens/_personal_access_token.html.haml_spec.rb' - - 'ee/spec/views/shared/credentials_inventory/ssh_keys/_ssh_key.html.haml_spec.rb' - - 'ee/spec/workers/adjourned_project_deletion_worker_spec.rb' - - 'ee/spec/workers/adjourned_projects_deletion_cron_worker_spec.rb' - - 'ee/spec/workers/security/create_orchestration_policy_worker_spec.rb' - - 'ee/spec/workers/security/orchestration_policy_rule_schedule_worker_spec.rb' - 'lib/api/commits.rb' - 'lib/api/helpers/merge_requests_helpers.rb' - 'lib/backup/manager.rb' diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 858b41711a5..df7c71c4341 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -30c010ce568c2e387728658b752fd65ee4f2a926 +8f39a5a9cdf3b8d544153e8297bcf639e5c626e7 diff --git a/GITLAB_METRICS_EXPORTER_VERSION b/GITLAB_METRICS_EXPORTER_VERSION index ba2906d0666..f3e956091b9 100644 --- a/GITLAB_METRICS_EXPORTER_VERSION +++ b/GITLAB_METRICS_EXPORTER_VERSION @@ -1 +1 @@ -main +2c781b65ccfd6d016c7bfab1982ecb234c4e2cd0 diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue index f2c30870a68..68c2db5fde8 100644 --- a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue +++ b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue @@ -318,13 +318,6 @@ export default { packageRegistryAccessLevelEnabled() { return this.glFeatures.packageRegistryAccessLevel; }, - showAdditonalSettings() { - if (this.glFeatures.enforceAuthChecksOnUploads) { - return true; - } - - return this.visibilityLevel !== this.visibilityOptions.PRIVATE; - }, }, watch: { @@ -545,7 +538,7 @@ export default { </template> </gl-sprintf> </span> - <div v-if="showAdditonalSettings" class="gl-mt-4"> + <div class="gl-mt-4"> <strong class="gl-display-block">{{ s__('ProjectSettings|Additional options') }}</strong> <label v-if="visibilityLevel !== visibilityOptions.PRIVATE" @@ -560,9 +553,7 @@ export default { {{ s__('ProjectSettings|Users can request access') }} </label> <label - v-if=" - visibilityLevel !== visibilityOptions.PUBLIC && glFeatures.enforceAuthChecksOnUploads - " + v-if="visibilityLevel !== visibilityOptions.PUBLIC" class="gl-line-height-28 gl-font-weight-normal gl-display-block gl-mb-0" > <input diff --git a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue index 3c22844434d..5576c6e2c62 100644 --- a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue +++ b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue @@ -9,6 +9,7 @@ import { GlFormGroup, GlFormInput, GlFormSelect, + GlSegmentedControl, } from '@gitlab/ui'; import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue'; import axios from '~/lib/utils/axios_utils'; @@ -81,9 +82,11 @@ export default { newPage: s__('WikiPage|Create page'), }, cancel: s__('WikiPage|Cancel'), - editSourceButtonText: s__('WikiPage|Edit source'), - editRichTextButtonText: s__('WikiPage|Edit rich text'), }, + switchEditingControlOptions: [ + { text: s__('Wiki Page|Source'), value: 'source' }, + { text: s__('Wiki Page|Rich text'), value: 'richText' }, + ], components: { GlAlert, GlIcon, @@ -94,6 +97,7 @@ export default { GlSprintf, GlLink, GlButton, + GlSegmentedControl, MarkdownField, LocalStorageSync, ContentEditor: () => @@ -105,10 +109,10 @@ export default { inject: ['formatOptions', 'pageInfo'], data() { return { + editingMode: 'source', title: this.pageInfo.title?.trim() || '', format: this.pageInfo.format || 'markdown', content: this.pageInfo.content || '', - useContentEditor: false, commitMessage: '', isDirty: false, contentEditorRenderFailed: false, @@ -177,6 +181,9 @@ export default { isContentEditorActive() { return this.isMarkdownFormat && this.useContentEditor; }, + useContentEditor() { + return this.editingMode === 'richText'; + }, }, mounted() { this.updateCommitMessage(); @@ -193,16 +200,15 @@ export default { .then(({ data }) => data.body); }, - toggleEditingMode() { - if (this.useContentEditor) { + toggleEditingMode(editingMode) { + this.editingMode = editingMode; + if (!this.useContentEditor && this.contentEditor) { this.content = this.contentEditor.getSerializedContent(); } - - this.useContentEditor = !this.useContentEditor; }, - setUseContentEditor(value) { - this.useContentEditor = value; + setEditingMode(value) { + this.editingMode = value; }, async handleFormSubmit(e) { @@ -372,20 +378,20 @@ export default { <div class="row" data-testid="wiki-form-content-fieldset"> <div class="col-sm-12 row-sm-5"> <gl-form-group> - <div v-if="isMarkdownFormat" class="gl-display-flex gl-justify-content-end gl-mb-3"> - <gl-button + <div v-if="isMarkdownFormat" class="gl-display-flex gl-justify-content-start gl-mb-3"> + <gl-segmented-control data-testid="toggle-editing-mode-button" data-qa-selector="editing_mode_button" - :data-qa-mode="toggleEditingModeButtonText" - variant="link" - @click="toggleEditingMode" - >{{ toggleEditingModeButtonText }}</gl-button - > + :checked="editingMode" + class="gl-display-flex" + :options="$options.switchEditingControlOptions" + @input="toggleEditingMode" + /> </div> <local-storage-sync storage-key="gl-wiki-content-editor-enabled" - :value="useContentEditor" - @input="setUseContentEditor" + :value="editingMode" + @input="setEditingMode" /> <markdown-field v-if="!isContentEditorActive" diff --git a/app/controllers/concerns/uploads_actions.rb b/app/controllers/concerns/uploads_actions.rb index f914e804e18..e98d36854f1 100644 --- a/app/controllers/concerns/uploads_actions.rb +++ b/app/controllers/concerns/uploads_actions.rb @@ -143,10 +143,8 @@ module UploadsActions end def bypass_auth_checks_on_uploads? - if ::Feature.enabled?(:enforce_auth_checks_on_uploads, target_project) - if target_project && !target_project.public? && target_project.enforce_auth_checks_on_uploads? - return false - end + if target_project && !target_project.public? && target_project.enforce_auth_checks_on_uploads? + return false end action_name == 'show' && embeddable? diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 4de46c9579e..bd766be0eec 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -46,10 +46,6 @@ class ProjectsController < Projects::ApplicationController push_frontend_feature_flag(:work_items_hierarchy, @project) end - before_action only: :edit do - push_frontend_feature_flag(:enforce_auth_checks_on_uploads, @project) - end - layout :determine_layout feature_category :projects, [ diff --git a/config/feature_flags/development/enforce_auth_checks_on_uploads.yml b/config/feature_flags/development/enforce_auth_checks_on_uploads.yml deleted file mode 100644 index d0cbe123a8f..00000000000 --- a/config/feature_flags/development/enforce_auth_checks_on_uploads.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: enforce_auth_checks_on_uploads -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80117 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/352291 -milestone: '14.8' -type: development -group: group::code review -default_enabled: false diff --git a/doc/administration/index.md b/doc/administration/index.md index d5f59692173..3f2ae3170ab 100644 --- a/doc/administration/index.md +++ b/doc/administration/index.md @@ -209,7 +209,6 @@ Learn how to install, configure, update, and maintain your GitLab instance. - [Log system](logs/index.md): Where to look for logs. - [Sidekiq Troubleshooting](troubleshooting/sidekiq.md): Debug when Sidekiq appears hung and is not processing jobs. -- [Troubleshooting Elasticsearch](troubleshooting/elasticsearch.md) - [Navigating GitLab via Rails console](operations/rails_console.md) - [GitLab application limits](instance_limits.md) - [Responding to security incidents](../security/responding_to_security_incidents.md) diff --git a/doc/administration/troubleshooting/elasticsearch.md b/doc/administration/troubleshooting/elasticsearch.md index 85a0de506bf..7390f4bc816 100644 --- a/doc/administration/troubleshooting/elasticsearch.md +++ b/doc/administration/troubleshooting/elasticsearch.md @@ -1,390 +1,11 @@ --- -stage: Data Stores -group: Global Search -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +redirect_to: '../../integration/advanced_search/elasticsearch_troubleshooting.md' +remove_date: '2022-11-02' --- -# Troubleshooting Elasticsearch **(PREMIUM SELF)** +This document was moved to [another location](../../integration/advanced_search/elasticsearch_troubleshooting.md). -To install and configure Elasticsearch, -visit the [administrator documentation](../../integration/advanced_search/elasticsearch.md). - -For troubleshooting, visit the -[administrator troubleshooting documentation](../../integration/advanced_search/elasticsearch_troubleshooting.md). - -Troubleshooting Elasticsearch requires: - -- Knowledge of common terms. -- Establishing within which category the problem fits. - -## Troubleshooting workflows - -The type of problem will determine what steps to take. The possible troubleshooting workflows are for: - -- Search results. -- Indexing. -- Integration. -- Performance. -- Advanced Search Migrations. - -### Search Results workflow - -The following workflow is for Elasticsearch search results issues: - -```mermaid -graph TD; - B --> |No| B1 - B --> |Yes| B4 - B1 --> B2 - B2 --> B3 - B4 --> B5 - B5 --> |Yes| B6 - B5 --> |No| B7 - B7 --> B8 - B{Is GitLab using<br>Elasticsearch for<br>searching?} - B1[From the Admin Area, select<br>Integrations from the left<br>sidebar to ensure the settings<br>are correct.] - B2[Perform a search via<br>the rails console] - B3[If all settings are correct<br>and it still doesn't show Elasticsearch<br>doing the searches, escalate<br>to GitLab support.] - B4[Perform<br>the same search via the<br>Elasticsearch API] - B5{Are the results<br>the same?} - B6[This means it is working as intended.<br>Speak with GitLab support<br>to confirm if the issue lies with<br>the filters.] - B7[Check the index status of the project<br>containing the missing search<br>results.] - B8(Indexing Troubleshooting) -``` - -### Indexing workflow - -The following workflow is for Elasticsearch indexing issues: - -```mermaid -graph TD; - C --> |Yes| C1 - C1 --> |Yes| C2 - C1 --> |No| C3 - C3 --> |Yes| C4 - C3 --> |No| C5 - C --> |No| C6 - C6 --> |No| C10 - C7 --> |GitLab| C8 - C7 --> |Elasticsearch| C9 - C6 --> |Yes| C7 - C10 --> |No| C12 - C10 --> |Yes| C11 - C12 --> |Yes| C13 - C12 --> |No| C14 - C14 --> |Yes| C15 - C14 --> |No| C16 - C{Is the problem with<br>creating an empty<br>index?} - C1{Does the gitlab-production<br>index exist on the<br>Elasticsearch instance?} - C2(Try to manually<br>delete the index on the<br>Elasticsearch instance and<br>retry creating an empty index.) - C3{Can indices be made<br>manually on the Elasticsearch<br>instance?} - C4(Retry the creation of an empty index) - C5(It is best to speak with an<br>Elasticsearch admin concerning the<br>instance's inability to create indices.) - C6{Is the indexer presenting<br>errors during indexing?} - C7{Is the error a GitLab<br>error or an Elasticsearch<br>error?} - C8[Escalate to<br>GitLab support] - C9[You will want<br>to speak with an<br>Elasticsearch admin.] - C10{Does the index status<br>show 100%?} - C11[Escalate to<br>GitLab support] - C12{Does re-indexing the project<br> present any GitLab errors?} - C13[Rectify the GitLab errors and<br>restart troubleshooting, or<br>escalate to GitLab support.] - C14{Does re-indexing the project<br>present errors on the <br>Elasticsearch instance?} - C15[It would be best<br>to speak with an<br>Elasticsearch admin.] - C16[This is likely a bug/issue<br>in GitLab and will require<br>deeper investigation. Escalate<br>to GitLab support.] -``` - -### Integration workflow - -The following workflow is for Elasticsearch integration issues: - -```mermaid -graph TD; - D --> |No| D1 - D --> |Yes| D2 - D2 --> |No| D3 - D2 --> |Yes| D4 - D4 --> |No| D5 - D4 --> |Yes| D6 - D{Is the error concerning<br>the Go indexer?} - D1[It would be best<br>to speak with an<br>Elasticsearch admin.] - D2{Is the ICU development<br>package installed?} - D3>This package is required.<br>Install the package<br>and retry.] - D4{Is the error stemming<br>from the indexer?} - D5[This would indicate an OS level<br> issue. It would be best to<br>contact your sysadmin.] - D6[This is likely a bug/issue<br>in GitLab and will require<br>deeper investigation. Escalate<br>to GitLab support.] -``` - -### Performance workflow - -The following workflow is for Elasticsearch performance issues: - -```mermaid -graph TD; - F --> |Yes| F1 - F --> |No| F2 - F2 --> |No| F3 - F2 --> |Yes| F4 - F4 --> F5 - F5 --> |No| F6 - F5 --> |Yes| F7 - F{Is the Elasticsearch instance<br>running on the same server<br>as the GitLab instance?} - F1(This is not advised and will cause issues.<br>We recommend moving the Elasticsearch<br>instance to a different server.) - F2{Does the Elasticsearch<br>server have at least 8<br>GB of RAM and 2 CPU<br>cores?} - F3(According to Elasticsearch, a non-prod<br>server needs these as a base requirement.<br>Production often requires more. We recommend<br>you increase the server specifications.) - F4(Obtain the <br>cluster health information) - F5(Does it show the<br>status as green?) - F6(We recommend you speak with<br>an Elasticsearch admin<br>about implementing sharding.) - F7(Escalate to<br>GitLab support.) -``` - -### Advanced Search Migrations workflow - -```mermaid -graph TD; - D --> |No| D1 - D --> |Yes| D2 - D2 --> |No| D3 - D2 --> |Yes| D4 - D4 --> |No| D5 - D4 --> |Yes| D6 - D6 --> |No| D8 - D6 --> |Yes| D7 - - D{Is there a halted migration?} - D1[Migrations run in the<br>background and will<br>stop when completed.] - D2{Does the elasticsearch.log<br>file contain errors?} - D3[This is likely a bug/issue<br>in GitLab and will require<br>deeper investigation. Escalate<br>to GitLab support.] - D4{Have the errors<br>been addressed?} - D5[Have an Elasticsearch admin<br>review and address<br>the errors.] - D6{Has the migration<br>been retried?} - D7[This is likely a bug/issue<br>in GitLab and will require<br>deeper investigation. Escalate<br>to GitLab support.] - D8[Retry the migration from<br>the Admin > Settings ><br>Advanced Search UI.] -``` - -## Troubleshooting walkthrough - -Most Elasticsearch troubleshooting can be broken down into 4 categories: - -- [Troubleshooting search results](#troubleshooting-search-results) -- [Troubleshooting indexing](#troubleshooting-indexing) -- [Troubleshooting integration](#troubleshooting-integration) -- [Troubleshooting performance](#troubleshooting-performance) -- [Troubleshooting Advanced Search migrations](#troubleshooting-advanced-search-migrations) - -Generally speaking, if it does not fall into those four categories, it is either: - -- Something GitLab support needs to look into. -- Not a true Elasticsearch issue. - -Exercise caution. Issues that appear to be Elasticsearch problems can be OS-level issues. - -### Troubleshooting search results - -Troubleshooting search result issues is rather straight forward on Elasticsearch. - -The first step is to confirm GitLab is using Elasticsearch for the search function. -To do this: - -1. On the top bar, select **Menu > Admin**. -1. On the left sidebar, select **Settings > General**, and then confirm the - integration is enabled. -1. Confirm searches use Elasticsearch by accessing the rails console - (`sudo gitlab-rails console`) and running the following commands: - - ```rails - u = User.find_by_email('email_of_user_doing_search') - s = SearchService.new(u, {:search => 'search_term'}) - pp s.search_objects.class - ``` - -The output from the last command is the key here. If it shows: - -- `ActiveRecord::Relation`, **it is not** using Elasticsearch. -- `Kaminari::PaginatableArray`, **it is** using Elasticsearch. - -| Not using Elasticsearch | Using Elasticsearch | -|--------------------------|------------------------------| -| `ActiveRecord::Relation` | `Kaminari::PaginatableArray` | - -If all the settings look correct and it is still not using Elasticsearch for the search function, it is best to escalate to GitLab support. This could be a bug/issue. - -Moving past that, it is best to attempt the same [search via the Rails console](../../integration/advanced_search/elasticsearch_troubleshooting.md#i-indexed-all-the-repositories-but-i-cant-get-any-hits-for-my-search-term-in-the-ui) -or the [Elasticsearch Search API](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html), -and compare the results from what you see in GitLab. - -If the results: - -- Sync up, then there is not a technical "issue." Instead, it might be a problem - with the Elasticsearch filters we are using. This can be complicated, so it is best to - escalate to GitLab support to check these and guide you on the potential on whether or - not a feature request is needed. -- Do not match up, this indicates a problem with the documents generated from the - project. It is best to re-index that project and proceed with - [Troubleshooting indexing](#troubleshooting-indexing). - -### Troubleshooting indexing - -Troubleshooting indexing issues can be tricky. It can pretty quickly go to either GitLab -support or your Elasticsearch administrator. - -The best place to start is to determine if the issue is with creating an empty index. -If it is, check on the Elasticsearch side to determine if the `gitlab-production` (the -name for the GitLab index) exists. If it exists, manually delete it on the Elasticsearch -side and attempt to recreate it from the -[`recreate_index`](../../integration/advanced_search/elasticsearch.md#gitlab-advanced-search-rake-tasks) -Rake task. - -If you still encounter issues, try creating an index manually on the Elasticsearch -instance. The details of the index aren't important here, as we want to test if indices -can be made. If the indices: - -- Cannot be made, speak with your Elasticsearch administrator. -- Can be made, Escalate this to GitLab support. - -If the issue is not with creating an empty index, the next step is to check for errors -during the indexing of projects. If errors do occur, they stem from either the indexing: - -- On the GitLab side. You need to rectify those. If they are not - something you are familiar with, contact GitLab support for guidance. -- Within the Elasticsearch instance itself. See if the error is [documented and has a fix](../../integration/advanced_search/elasticsearch_troubleshooting.md). If not, speak with your Elasticsearch administrator. - -If the indexing process does not present errors, check the status of the indexed projects. You can do this via the following Rake tasks: - -- [`sudo gitlab-rake gitlab:elastic:index_projects_status`](../../integration/advanced_search/elasticsearch.md#gitlab-advanced-search-rake-tasks) (shows the overall status) -- [`sudo gitlab-rake gitlab:elastic:projects_not_indexed`](../../integration/advanced_search/elasticsearch.md#gitlab-advanced-search-rake-tasks) (shows specific projects that are not indexed) - -If: - -- Everything is showing at 100%, escalate to GitLab support. This could be a potential - bug/issue. -- You do see something not at 100%, attempt to reindex that project. To do this, - run `sudo gitlab-rake gitlab:elastic:index_projects ID_FROM=<project ID> ID_TO=<project ID>`. - -If reindexing the project shows: - -- Errors on the GitLab side, escalate those to GitLab support. -- Elasticsearch errors or doesn't present any errors at all, reach out to your - Elasticsearch administrator to check the instance. - -### Troubleshooting integration - -Troubleshooting integration tends to be pretty straight forward, as there really isn't -much to "integrate" here. - -If the issue is: - -- With the Go indexer, check if the ICU development package is installed. - This is a required package so make sure you install it. - Go indexer was a beta indexer which can be optionally turned on/off, but in 12.3 it reached stable status and is now the default. -- Not concerning the Go indexer, it is almost always an - Elasticsearch-side issue. This means you should reach out to your Elasticsearch administrator - regarding the errors you are seeing. If you are unsure here, it never hurts to reach - out to GitLab support. - -Beyond that, review the error. If it is: - -- Specifically from the indexer, this could be a bug/issue and should be escalated to - GitLab support. -- An OS issue, you should reach out to your systems administrator. -- A `Faraday::TimeoutError (execution expired)` error **and** you're using a proxy, - [set a custom `gitlab_rails['env']` environment variable, called `no_proxy`](https://docs.gitlab.com/omnibus/settings/environment-variables.html) - with the IP address of your Elasticsearch host. - -### Troubleshooting performance - -Troubleshooting performance can be difficult on Elasticsearch. There is a ton of tuning -that *can* be done, but the majority of this falls on shoulders of a skilled -Elasticsearch administrator. - -Generally speaking, ensure: - -- The Elasticsearch server **is not** running on the same node as GitLab. -- The Elasticsearch server have enough RAM and CPU cores. -- That sharding **is** being used. - -Going into some more detail here, if Elasticsearch is running on the same server as GitLab, resource contention is **very** likely to occur. Ideally, Elasticsearch, which requires ample resources, should be running on its own server (maybe coupled with Logstash and Kibana). - -When it comes to Elasticsearch, RAM is the key resource. Elasticsearch themselves recommend: - -- **At least** 8 GB of RAM for a non-production instance. -- **At least** 16 GB of RAM for a production instance. -- Ideally, 64 GB of RAM. - -For CPU, Elasticsearch recommends at least 2 CPU cores, but Elasticsearch states common -setups use up to 8 cores. For more details on server specs, check out -[Elasticsearch's hardware guide](https://www.elastic.co/guide/en/elasticsearch/guide/current/hardware.html). - -Beyond the obvious, sharding comes into play. Sharding is a core part of Elasticsearch. -It allows for horizontal scaling of indices, which is helpful when you are dealing with -a large amount of data. - -With the way GitLab does indexing, there is a **huge** amount of documents being -indexed. By utilizing sharding, you can speed up Elasticsearch's ability to locate -data, since each shard is a Lucene index. - -If you are not using sharding, you are likely to hit issues when you start using -Elasticsearch in a production environment. - -Keep in mind that an index with only one shard has **no scale factor** and will -likely encounter issues when called upon with some frequency. - -If you need to know how many shards, read -[Elasticsearch's documentation on capacity planning](https://www.elastic.co/guide/en/elasticsearch/guide/2.x/capacity-planning.html), -as the answer is not straight forward. - -The easiest way to determine if sharding is in use is to check the output of the -[Elasticsearch Health API](https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-health.html): - -- Red means the cluster is down. -- Yellow means it is up with no sharding/replication. -- Green means it is healthy (up, sharding, replicating). - -For production use, it should always be green. - -Beyond these steps, you get into some of the more complicated things to check, -such as merges and caching. These can get complicated and it takes some time to -learn them, so it is best to escalate/pair with an Elasticsearch expert if you need to -dig further into these. - -Feel free to reach out to GitLab support, but this is likely to be something a skilled -Elasticsearch administrator has more experience with. - -### Troubleshooting Advanced Search migrations - -Troubleshooting Advanced Search migration failures can be difficult and may -require contacting an Elasticsearch administrator or GitLab Support. - -The best place to start while debugging issues with an Advanced Search -migration is the [`elasticsearch.log` file](../logs/index.md#elasticsearchlog). -Migrations log information while a migration is in progress and any -errors encountered. Apply fixes for any errors found in the log and retry -the migration. - -If you still encounter issues after retrying the migration, reach out to GitLab support. - -## Common issues - -All common issues [should be documented](../../integration/advanced_search/elasticsearch_troubleshooting.md). If not, -feel free to update that page with issues you encounter and solutions. - -## Replication - -Setting up Elasticsearch isn't too bad, but it can be a bit finicky and time consuming. - -The easiest method is to spin up a Docker container with the required version and -bind ports 9200/9300 so it can be used. - -The following is an example of running a Docker container of Elasticsearch v7.2.0: - -```shell -docker pull docker.elastic.co/elasticsearch/elasticsearch:7.2.0 -docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.2.0 -``` - -From here, you can: - -- Grab the IP of the Docker container (use `docker inspect <container_id>`) -- Use `<IP.add.re.ss:9200>` to communicate with it. - -This is a quick method to test out Elasticsearch, but by no means is this a -production solution. +<!-- This redirect file can be deleted after <2022-11-02>. --> +<!-- Redirects that point to other docs in the same project expire in three months. --> +<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html --> diff --git a/doc/administration/troubleshooting/index.md b/doc/administration/troubleshooting/index.md index 9c5e09b1d65..7408ada0e8d 100644 --- a/doc/administration/troubleshooting/index.md +++ b/doc/administration/troubleshooting/index.md @@ -13,7 +13,6 @@ installation. - [SSL](ssl.md) - [Geo](../geo/replication/troubleshooting.md) -- [Elasticsearch](elasticsearch.md) - [Sidekiq](sidekiq.md) - [GitLab Rails console cheat sheet](gitlab_rails_cheat_sheet.md) - [Example group SAML and SCIM configurations](../../user/group/saml_sso/example_saml_config.md) diff --git a/doc/integration/advanced_search/elasticsearch_troubleshooting.md b/doc/integration/advanced_search/elasticsearch_troubleshooting.md index a07c0aef189..6d9cb539cbd 100644 --- a/doc/integration/advanced_search/elasticsearch_troubleshooting.md +++ b/doc/integration/advanced_search/elasticsearch_troubleshooting.md @@ -58,6 +58,20 @@ There are a couple of ways to achieve that: ::Gitlab::CurrentSettings.elasticsearch_limit_indexing? # Whether or not Elasticsearch is limited only to certain projects/namespaces ``` +- Confirm searches use Elasticsearch by accessing the [rails console] + (../../administration/operations/rails_console.md) and running the following commands: + + ```rails + u = User.find_by_email('email_of_user_doing_search') + s = SearchService.new(u, {:search => 'search_term'}) + pp s.search_objects.class + ``` + + The output from the last command is the key here. If it shows: + + - `ActiveRecord::Relation`, **it is not** using Elasticsearch. + - `Kaminari::PaginatableArray`, **it is** using Elasticsearch. + - If Elasticsearch is limited to specific namespaces and you need to know if Elasticsearch is being used for a specific project or namespace, you can use the Rails console: @@ -67,13 +81,57 @@ There are a couple of ways to achieve that: ::Gitlab::CurrentSettings.search_using_elasticsearch?(scope: Project.find_by_full_path("/my-namespace/my-project")) ``` -## I updated GitLab and now I can't find anything +## Troubleshooting indexing + +Troubleshooting indexing issues can be tricky. It can pretty quickly go to either GitLab +support or your Elasticsearch administrator. + +The best place to start is to determine if the issue is with creating an empty index. +If it is, check on the Elasticsearch side to determine if the `gitlab-production` (the +name for the GitLab index) exists. If it exists, manually delete it on the Elasticsearch +side and attempt to recreate it from the +[`recreate_index`](../../integration/advanced_search/elasticsearch.md#gitlab-advanced-search-rake-tasks) +Rake task. + +If you still encounter issues, try creating an index manually on the Elasticsearch +instance. The details of the index aren't important here, as we want to test if indices +can be made. If the indices: + +- Cannot be made, speak with your Elasticsearch administrator. +- Can be made, Escalate this to GitLab support. + +If the issue is not with creating an empty index, the next step is to check for errors +during the indexing of projects. If errors do occur, they stem from either the indexing: + +- On the GitLab side. You need to rectify those. If they are not + something you are familiar with, contact GitLab support for guidance. +- Within the Elasticsearch instance itself. See if the error is [documented and has a fix](../../integration/advanced_search/elasticsearch_troubleshooting.md). If not, speak with your Elasticsearch administrator. + +If the indexing process does not present errors, check the status of the indexed projects. You can do this via the following Rake tasks: + +- [`sudo gitlab-rake gitlab:elastic:index_projects_status`](../../integration/advanced_search/elasticsearch.md#gitlab-advanced-search-rake-tasks) (shows the overall status) +- [`sudo gitlab-rake gitlab:elastic:projects_not_indexed`](../../integration/advanced_search/elasticsearch.md#gitlab-advanced-search-rake-tasks) (shows specific projects that are not indexed) + +If: + +- Everything is showing at 100%, escalate to GitLab support. This could be a potential + bug/issue. +- You do see something not at 100%, attempt to reindex that project. To do this, + run `sudo gitlab-rake gitlab:elastic:index_projects ID_FROM=<project ID> ID_TO=<project ID>`. + +If reindexing the project shows: + +- Errors on the GitLab side, escalate those to GitLab support. +- Elasticsearch errors or doesn't present any errors at all, reach out to your + Elasticsearch administrator to check the instance. + +### I updated GitLab and now I can't find anything We continuously make updates to our indexing strategies and aim to support newer versions of Elasticsearch. When indexing changes are made, it may be necessary for you to [reindex](elasticsearch.md#zero-downtime-reindexing) after updating GitLab. -## I indexed all the repositories but I can't get any hits for my search term in the UI +### I indexed all the repositories but I can't get any hits for my search term in the UI Make sure you [indexed all the database data](elasticsearch.md#enable-advanced-search). @@ -93,7 +151,10 @@ curl --request GET <elasticsearch_server_ip>:9200/gitlab-production/_search?q=<s More [complex Elasticsearch API calls](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-filter-context.html) are also possible. -It is important to understand at which level the problem is manifesting (UI, Rails code, Elasticsearch side) to be able to [troubleshoot further](../../administration/troubleshooting/elasticsearch.md#search-results-workflow). +If the results: + +- Sync up, please check that you are using [supported syntax](../../user/search/global_search/advanced_search_syntax.md). Note that Advanced Search does not support [exact substring matching](https://gitlab.com/gitlab-org/gitlab/-/issues/325234). +- Do not match up, this indicates a problem with the documents generated from the project. It is best to [re-index that project](../advanced_search/elasticsearch.md#indexing-a-range-of-projects-or-a-specific-project) NOTE: The above instructions are not to be used for scenarios that only index a [subset of namespaces](elasticsearch.md#limit-the-number-of-namespaces-and-projects-that-can-be-indexed). @@ -104,15 +165,15 @@ See [Elasticsearch Index Scopes](elasticsearch.md#advanced-search-index-scopes) You must re-run all the Rake tasks to reindex the database, repositories, and wikis. -## The indexing process is taking a very long time +### The indexing process is taking a very long time The more data present in your GitLab instance, the longer the indexing process takes. -## There are some projects that weren't indexed, but I don't know which ones +### There are some projects that weren't indexed, but I don't know which ones You can run `sudo gitlab-rake gitlab:elastic:projects_not_indexed` to display projects that aren't indexed. -## No new data is added to the Elasticsearch index when I push code +### No new data is added to the Elasticsearch index when I push code NOTE: This was [fixed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35936) in GitLab 13.2 and the Rake task is not available for versions greater than that. @@ -123,6 +184,116 @@ When performing the initial indexing of blobs, we lock all projects until the pr sudo gitlab-rake gitlab:elastic:clear_locked_projects ``` +### Indexing fails with `error: elastic: Error 429 (Too Many Requests)` + +If `ElasticCommitIndexerWorker` Sidekiq workers are failing with this error during indexing, it usually means that Elasticsearch is unable to keep up with the concurrency of indexing request. To address change the following settings: + +- To decrease the indexing throughput you can decrease `Bulk request concurrency` (see [Advanced Search settings](elasticsearch.md#advanced-search-configuration)). This is set to `10` by default, but you change it to as low as 1 to reduce the number of concurrent indexing operations. +- If changing `Bulk request concurrency` didn't help, you can use the [queue selector](../../administration/operations/extra_sidekiq_processes.md#queue-selector) option to [limit indexing jobs only to specific Sidekiq nodes](elasticsearch.md#index-large-instances-with-dedicated-sidekiq-nodes-or-processes), which should reduce the number of indexing requests. + +### Indexing is very slow or fails with `rejected execution of coordinating operation` messages + +Bulk requests getting rejected by the Elasticsearch nodes are likely due to load and lack of available memory. +Ensure that your Elasticsearch cluster meets the [system requirements](elasticsearch.md#system-requirements) and has enough resources +to perform bulk operations. See also the error ["429 (Too Many Requests)"](#indexing-fails-with-error-elastic-error-429-too-many-requests). + +### Last resort to recreate an index + +There may be cases where somehow data never got indexed and it's not in the +queue, or the index is somehow in a state where migrations just cannot +proceed. It is always best to try to troubleshoot the root cause of the problem +by [viewing the logs](#view-logs). + +If there are no other options, then you always have the option of recreating the +entire index from scratch. If you have a small GitLab installation, this can +sometimes be a quick way to resolve a problem, but if you have a large GitLab +installation, then this might take a very long time to complete. Until the +index is fully recreated, your index does not serve correct search results, +so you may want to disable **Search with Elasticsearch** while it is running. + +If you are sure you've read the above caveats and want to proceed, then you +should run the following Rake task to recreate the entire index from scratch: + +**For Omnibus installations** + +```shell +# WARNING: DO NOT RUN THIS UNTIL YOU READ THE DESCRIPTION ABOVE +sudo gitlab-rake gitlab:elastic:index +``` + +**For installations from source** + +```shell +# WARNING: DO NOT RUN THIS UNTIL YOU READ THE DESCRIPTION ABOVE +cd /home/git/gitlab +sudo -u git -H bundle exec rake gitlab:elastic:index +``` + +### Troubleshooting performance + +Troubleshooting performance can be difficult on Elasticsearch. There is a ton of tuning +that *can* be done, but the majority of this falls on shoulders of a skilled +Elasticsearch administrator. + +Generally speaking, ensure: + +- The Elasticsearch server **is not** running on the same node as GitLab. +- The Elasticsearch server have enough RAM and CPU cores. +- That sharding **is** being used. + +Going into some more detail here, if Elasticsearch is running on the same server as GitLab, resource contention is **very** likely to occur. Ideally, Elasticsearch, which requires ample resources, should be running on its own server (maybe coupled with Logstash and Kibana). + +When it comes to Elasticsearch, RAM is the key resource. Elasticsearch themselves recommend: + +- **At least** 8 GB of RAM for a non-production instance. +- **At least** 16 GB of RAM for a production instance. +- Ideally, 64 GB of RAM. + +For CPU, Elasticsearch recommends at least 2 CPU cores, but Elasticsearch states common +setups use up to 8 cores. For more details on server specs, check out +[Elasticsearch's hardware guide](https://www.elastic.co/guide/en/elasticsearch/guide/current/hardware.html). + +Beyond the obvious, sharding comes into play. Sharding is a core part of Elasticsearch. +It allows for horizontal scaling of indices, which is helpful when you are dealing with +a large amount of data. + +With the way GitLab does indexing, there is a **huge** amount of documents being +indexed. By utilizing sharding, you can speed up Elasticsearch's ability to locate +data, since each shard is a Lucene index. + +If you are not using sharding, you are likely to hit issues when you start using +Elasticsearch in a production environment. + +Keep in mind that an index with only one shard has **no scale factor** and will +likely encounter issues when called upon with some frequency. + +If you need to know how many shards, read +[Elasticsearch's documentation on capacity planning](https://www.elastic.co/guide/en/elasticsearch/guide/2.x/capacity-planning.html), +as the answer is not straight forward. + +The easiest way to determine if sharding is in use is to check the output of the +[Elasticsearch Health API](https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-health.html): + +- Red means the cluster is down. +- Yellow means it is up with no sharding/replication. +- Green means it is healthy (up, sharding, replicating). + +For production use, it should always be green. + +Beyond these steps, you get into some of the more complicated things to check, +such as merges and caching. These can get complicated and it takes some time to +learn them, so it is best to escalate/pair with an Elasticsearch expert if you need to +dig further into these. + +Feel free to reach out to GitLab support, but this is likely to be something a skilled +Elasticsearch administrator has more experience with. + +## Issues with migrations + +Please ensure you've read about [Elasticsearch Migrations](../advanced_search/elasticsearch.md#advanced-search-migrations). + +If there is a halted migration and your [`elasticsearch.log`](../../administration/logs/index.md#elasticsearchlog) file contain errors, this could potentially be a bug/issue. Escalate to GitLab support if retrying migrations does not succeed. + ## `Can't specify parent if no parent field has been configured` error If you enabled Elasticsearch before GitLab 8.12 and have not rebuilt indices, you get @@ -160,6 +331,10 @@ This exception is seen when your Elasticsearch cluster is configured to reject r AWS has [fixed limits](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/limits.html#network-limits) for this setting ("Maximum size of HTTP request payloads"), based on the size of the underlying instance. +## `Faraday::TimeoutError (execution expired)` error when using a proxy + +Set a custom `gitlab_rails['env']` environment variable, called [`no_proxy`](https://docs.gitlab.com/omnibus/settings/environment-variables.html) with the IP address of your Elasticsearch host. + ## My single node Elasticsearch cluster status never goes from `yellow` to `green` even though everything seems to be running properly **For a single node Elasticsearch cluster the functional cluster health status is yellow** (never green) because the primary shard is allocated but replicas cannot be as there is no other node to which Elasticsearch can assign a replica. This also applies if you are using the [Amazon OpenSearch](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/aes-handling-errors.html#aes-handling-errors-yellow-cluster-status) service. @@ -196,10 +371,6 @@ reason may be incompatible with our integration. You should try disabling plugins so you can rule out the possibility that the plugin is causing the problem. -## Low-level troubleshooting - -There is a [more structured, lower-level troubleshooting document](../../administration/troubleshooting/elasticsearch.md) for when you experience other issues, including poor performance. - ## Elasticsearch `code_analyzer` doesn't account for all code cases The `code_analyzer` pattern and filter configuration is being evaluated for improvement. We have fixed [most edge cases](https://gitlab.com/groups/gitlab-org/-/epics/3621#note_363429094) that were not returning expected search results due to our pattern and filter configuration. @@ -210,38 +381,6 @@ Improvements to the `code_analyzer` pattern and filters are being discussed in [ In GitLab 13.9, a change was made where [binary file names are being indexed](https://gitlab.com/gitlab-org/gitlab/-/issues/301083). However, without indexing all projects' data from scratch, only binary files that are added or updated after the GitLab 13.9 release are searchable. -## Last resort to recreate an index - -There may be cases where somehow data never got indexed and it's not in the -queue, or the index is somehow in a state where migrations just cannot -proceed. It is always best to try to troubleshoot the root cause of the problem -by [viewing the logs](#view-logs). - -If there are no other options, then you always have the option of recreating the -entire index from scratch. If you have a small GitLab installation, this can -sometimes be a quick way to resolve a problem, but if you have a large GitLab -installation, then this might take a very long time to complete. Until the -index is fully recreated, your index does not serve correct search results, -so you may want to disable **Search with Elasticsearch** while it is running. - -If you are sure you've read the above caveats and want to proceed, then you -should run the following Rake task to recreate the entire index from scratch: - -**For Omnibus installations** - -```shell -# WARNING: DO NOT RUN THIS UNTIL YOU READ THE DESCRIPTION ABOVE -sudo gitlab-rake gitlab:elastic:index -``` - -**For installations from source** - -```shell -# WARNING: DO NOT RUN THIS UNTIL YOU READ THE DESCRIPTION ABOVE -cd /home/git/gitlab -sudo -u git -H bundle exec rake gitlab:elastic:index -``` - ## How does Advanced Search handle private projects? Advanced Search stores all the projects in the same Elasticsearch indices, @@ -249,19 +388,6 @@ however, searches only surface results that can be viewed by the user. Advanced Search honors all permission checks in the application by filtering out projects that a user does not have access to at search time. -## Indexing fails with `error: elastic: Error 429 (Too Many Requests)` - -If `ElasticCommitIndexerWorker` Sidekiq workers are failing with this error during indexing, it usually means that Elasticsearch is unable to keep up with the concurrency of indexing request. To address change the following settings: - -- To decrease the indexing throughput you can decrease `Bulk request concurrency` (see [Advanced Search settings](elasticsearch.md#advanced-search-configuration)). This is set to `10` by default, but you change it to as low as 1 to reduce the number of concurrent indexing operations. -- If changing `Bulk request concurrency` didn't help, you can use the [queue selector](../../administration/operations/extra_sidekiq_processes.md#queue-selector) option to [limit indexing jobs only to specific Sidekiq nodes](elasticsearch.md#index-large-instances-with-dedicated-sidekiq-nodes-or-processes), which should reduce the number of indexing requests. - -## Indexing is very slow or fails with `rejected execution of coordinating operation` messages - -Bulk requests getting rejected by the Elasticsearch nodes are likely due to load and lack of available memory. -Ensure that your Elasticsearch cluster meets the [system requirements](elasticsearch.md#system-requirements) and has enough resources -to perform bulk operations. See also the error ["429 (Too Many Requests)"](#indexing-fails-with-error-elastic-error-429-too-many-requests). - ## Access requirements for the self-managed AWS OpenSearch Service To use the self-managed AWS OpenSearch Service with GitLab, configure your instance's domain access policies diff --git a/doc/integration/mattermost/index.md b/doc/integration/mattermost/index.md index 1a60ca3a5fe..99678c9a1d3 100644 --- a/doc/integration/mattermost/index.md +++ b/doc/integration/mattermost/index.md @@ -229,53 +229,60 @@ sudo gitlab-ctl start mattermost ### Mattermost Command Line Tools (CLI) -NOTE: -This CLI will be replaced in a future release with the new [`mmctl` Command Line Tool](https://docs.mattermost.com/manage/mmctl-command-line-tool.html). +[`mmctl`](https://docs.mattermost.com/manage/mmctl-command-line-tool.html) is a CLI tool for the Mattermost server which is installed locally and uses the Mattermost API, but may also be used remotely. You must configure Mattermost either for local connections or authenticate as an administrator with local login credentials (not through GitLab SSO). The executable is located at `/opt/gitlab/embedded/bin/mmctl`. -To use the [Mattermost Command Line Tools (CLI)](https://docs.mattermost.com/administration/command-line-tools.html), ensure that you are in the `/opt/gitlab/embedded/service/mattermost` directory when you run the CLI commands and that you specify the location of the configuration file. The executable is `/opt/gitlab/embedded/bin/mattermost`. +#### Use `mmctl` through a local connection -```shell -cd /opt/gitlab/embedded/service/mattermost +For local connections, the `mmctl` binary and Mattermost must be run from the same server. To enable the local socket: -sudo /opt/gitlab/embedded/bin/chpst -e /opt/gitlab/etc/mattermost/env -P -U mattermost:mattermost -u mattermost:mattermost /opt/gitlab/embedded/bin/mattermost --config=/var/opt/gitlab/mattermost/config.json version -``` +1. Edit `/var/opt/gitlab/mattermost/config.json`, and add the following lines: + + ```json + { + "ServiceSettings": { + ... + "EnableLocalMode": true, + "LocalModeSocketLocation": "/var/tmp/mattermost_local.socket", + ... + } + } + ``` + +1. Restart Mattermost: + + ```shell + sudo gitlab-ctl restart mattermost + ``` -Until [#4745](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4745) has been implemented, the command requires quite of bit typing and is hard to remember, so let's make a bash or Zsh alias to make it a bit easier to remember. Add the following to your `~/.bashrc` or `~/.zshrc` file: +You can then use `/opt/gitlab/embedded/bin/mmctl --local` to run `mmctl` commands +on your Mattermost instance. + +For example, to show the list of users: ```shell -alias mattermost-cli="cd /opt/gitlab/embedded/service/mattermost && sudo /opt/gitlab/embedded/bin/chpst -e /opt/gitlab/etc/mattermost/env -P -U mattermost:mattermost -u mattermost:mattermost /opt/gitlab/embedded/bin/mattermost --config=/var/opt/gitlab/mattermost/config.json $1" +$ /opt/gitlab/embedded/bin/mmctl --local user list + +13dzo5bmg7fu8rdox347hbfxde: appsbot (appsbot@localhost) +tbnkwjdug3dejcoddboo4yuomr: boards (boards@localhost) +wd3g5zpepjgbfjgpdjaas7yj6a: feedbackbot (feedbackbot@localhost) +8d3zzgpurp85zgf1q88pef73eo: playbooks (playbooks@localhost) +There are 4 users on local instance ``` -Then source `~/.zshrc` or `~/.bashrc` with `source ~/.zshrc` or `source ~/.bashrc`. +#### Use `mmctl` through a remote connection -If successful, you can now run any Mattermost CLI command with your new shell alias `mattermost-cli`: +For remote connections or local connections where the socket cannot be used, +create a non SSO user and give that user admin privileges. Those credentials +can then be used to authenticate `mmctl`: ```shell -$ mattermost-cli version - -[sudo] password for username: -{"level":"info","ts":1569614421.9058893,"caller":"utils/i18n.go:83","msg":"Loaded system translations for 'en' from '/opt/gitlab/embedded/service/mattermost/i18n/en.json'"} -{"level":"info","ts":1569614421.9062793,"caller":"app/server_app_adapters.go:58","msg":"Server is initializing..."} -{"level":"info","ts":1569614421.90976,"caller":"sqlstore/supplier.go:223","msg":"Pinging SQL master database"} -{"level":"info","ts":1569614422.0515099,"caller":"mlog/log.go:165","msg":"Starting up plugins"} -{"level":"info","ts":1569614422.0515954,"caller":"app/plugin.go:193","msg":"Syncing plugins from the file store"} -{"level":"info","ts":1569614422.086005,"caller":"app/plugin.go:228","msg":"Found no files in plugins file store"} -{"level":"info","ts":1569614423.9337213,"caller":"sqlstore/post_store.go:1301","msg":"Post.Message supports at most 16383 characters (65535 bytes)"} -{"level":"error","ts":1569614425.6317747,"caller":"go-plugin/stream.go:15","msg":" call to OnConfigurationChange failed, error: Must have a GitLab oauth client id","plugin_id":"com.github.manland.mattermost-plugin-gitlab","source":"plugin_stderr"} -{"level":"info","ts":1569614425.6875598,"caller":"mlog/sugar.go:19","msg":"Ensuring Surveybot exists","plugin_id":"com.mattermost.nps"} -{"level":"info","ts":1569614425.6953356,"caller":"app/server.go:216","msg":"Current version is 5.14.0 (5.14.2/Fri Aug 30 20:20:48 UTC 2019/817ee89711bf26d33f840ce7f59fba14da1ed168/none)"} -{"level":"info","ts":1569614425.6953766,"caller":"app/server.go:217","msg":"Enterprise Enabled: false"} -{"level":"info","ts":1569614425.6954057,"caller":"app/server.go:219","msg":"Current working directory is /opt/gitlab/embedded/service/mattermost/i18n"} -{"level":"info","ts":1569614425.6954265,"caller":"app/server.go:220","msg":"Loaded config","source":"file:///var/opt/gitlab/mattermost/config.json"} -Version: 5.14.0 -Build Number: 5.14.2 -Build Date: Fri Aug 30 20:20:48 UTC 2019 -Build Hash: 817ee89711bf26d33f840ce7f59fba14da1ed168 -Build Enterprise Ready: false -DB Version: 5.14.0 -``` +$ /opt/gitlab/embedded/bin/mmctl auth login http://mattermost.example.com -For more details see [Mattermost Command Line Tools (CLI)](https://docs.mattermost.com/administration/command-line-tools.html) and the [Troubleshooting Mattermost CLI](#troubleshooting-the-mattermost-cli) below. +Connection name: test +Username: local-user +Password: + credentials for "test": "local-user@http://mattermost.example.com" stored +``` ## Configuring GitLab and Mattermost integrations @@ -512,14 +519,6 @@ sequenceDiagram Mattermost->>User: Mattermost/GitLab user ready ``` -## Troubleshooting the Mattermost CLI - -### Failed to ping DB retrying in 10 seconds err=dial tcp: lookup dockerhost: no such host - -As of version 11.0, majority of the Mattermost settings are now configured via environmental variables. The error is mainly due to the database connection string being commented out in `gitlab.rb` and the database connection settings being set in environmental variables. Additionally, the connection string in the `gitlab.rb` is for MySQL which is no longer supported as of 12.1. - -You can fix this by setting up a `mattermost-cli` [shell alias](#mattermost-command-line-tools-cli). - ## Community support resources For help and support around your GitLab Mattermost deployment please see: diff --git a/doc/security/user_file_uploads.md b/doc/security/user_file_uploads.md index 2e2dbdaa765..7c11d01396d 100644 --- a/doc/security/user_file_uploads.md +++ b/doc/security/user_file_uploads.md @@ -8,13 +8,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w # User file uploads **(FREE)** > - Enforced authorization checks [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80117) in GitLab 14.8 [with a flag](../administration/feature_flags.md) named `enforce_auth_checks_on_uploads`. Disabled by default. +> - Enforced authorization checks became [generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/352291) in GitLab 15.3. Feature flag `enforce_auth_checks_on_uploads` removed. > - Project settings in the user interface [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/88567) in GitLab 15.3. -FLAG: -On self-managed GitLab, by default this feature is unavailable. To make it available per project or for your entire instance, -ask an administrator to [enable the feature flag](../administration/feature_flags.md) named `enforce_auth_checks_on_uploads`. -On GitLab.com, this feature is not available. - In private or internal projects, GitLab restricts access to uploaded files (such as PDFs) to authenticated users only. By default, image files are not subject to the same restriction, and unauthenticated users can use the URL to view the diff --git a/lib/tasks/contracts/pipelines.rake b/lib/tasks/contracts/pipelines.rake index ad1936055d8..522e1f0399e 100644 --- a/lib/tasks/contracts/pipelines.rake +++ b/lib/tasks/contracts/pipelines.rake @@ -10,6 +10,13 @@ provider = File.expand_path('provider', contracts) # rubocop:disable Rails/RakeEnvironment namespace :contracts do namespace :pipelines do + Pact::VerificationTask.new(:create_a_new_pipeline) do |pact| + pact.uri( + "#{contracts}/contracts/project/pipeline/new/pipelines#new-post_create_a_new_pipeline.json", + pact_helper: "#{provider}/pact_helpers/project/pipeline/create_a_new_pipeline_helper.rb" + ) + end + Pact::VerificationTask.new(:get_list_project_pipelines) do |pact| pact.uri( "#{contracts}/contracts/project/pipeline/index/pipelines#index-get_list_project_pipelines.json", @@ -34,6 +41,7 @@ namespace :contracts do desc 'Run all pipeline contract tests' task 'test:pipelines', :contract_mr do |_t, arg| errors = %w[ + create_a_new_pipeline get_list_project_pipelines get_pipeline_header_data delete_pipeline diff --git a/lib/unnested_in_filters/rewriter.rb b/lib/unnested_in_filters/rewriter.rb index cba002a5632..bf7be177a0d 100644 --- a/lib/unnested_in_filters/rewriter.rb +++ b/lib/unnested_in_filters/rewriter.rb @@ -25,7 +25,7 @@ module UnnestedInFilters attr_reader :model, :attribute, :values delegate :connection, :columns, :attribute_types, to: :model, private: true - delegate :quote, :quote_table_name, :quote_column_name, to: :connection + delegate :quote, :quote_table_name, :quote_column_name, :visitor, to: :connection def table_name quote_table_name(attribute.pluralize) @@ -36,8 +36,17 @@ module UnnestedInFilters end def serialized_values - array_type.serialize(values) - .then { |array| quote(array) } + values.is_a?(Arel::Nodes::SelectStatement) ? "ARRAY(#{serialized_arel_value})" : serialized_array_values + end + + def serialized_arel_value + visitor.compile(values, unprepared_statement_collector) + end + + def serialized_array_values + values.map(&:value) + .then { array_type.serialize(_1) } + .then { |array| quote(array) } end def array_type @@ -51,6 +60,13 @@ module UnnestedInFilters def column columns.find { _1.name == attribute } end + + def unprepared_statement_collector + Arel::Collectors::SubstituteBinds.new( + connection, + Arel::Collectors::SQLString.new + ) + end end def initialize(relation) @@ -125,7 +141,7 @@ module UnnestedInFilters attr_reader :relation - delegate :model, :order_values, :limit_value, :where_values_hash, to: :relation, private: true + delegate :model, :order_values, :limit_value, :where_values_hash, :where_clause, to: :relation, private: true def log_rewrite ::Gitlab::AppLogger.info(message: 'Query is being rewritten by `UnnestedInFilters`', model: model.name) @@ -150,7 +166,28 @@ module UnnestedInFilters end def in_filters - @in_filters ||= where_values_hash.select { _2.is_a?(Array) } + @in_filters ||= arel_in_nodes.each_with_object({}) { |node, memo| memo[node.left.name] = node.right } + end + + def arel_in_nodes + where_clause_arel_nodes.select(&method(:in_predicate?)) + end + + # `ActiveRecord::WhereClause#ast` is returning a single node when there is only one + # predicate but returning an `Arel::Nodes::And` node if there are more than one predicates. + # This is why we are checking the returned object responds to `children` or not. + def where_clause_arel_nodes + return [where_clause_ast] unless where_clause_ast.respond_to?(:children) + + where_clause_ast.children + end + + def where_clause_ast + @where_clause_ast ||= where_clause.ast + end + + def in_predicate?(arel_node) + arel_node.is_a?(Arel::Nodes::HomogeneousIn) || arel_node.is_a?(Arel::Nodes::In) end def has_index_coverage? diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 22f3ff9f1b5..7c2fde49498 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -43928,6 +43928,12 @@ msgstr "" msgid "Wiki" msgstr "" +msgid "Wiki Page|Rich text" +msgstr "" + +msgid "Wiki Page|Source" +msgstr "" + msgid "Wiki page" msgstr "" @@ -44054,12 +44060,6 @@ msgstr "" msgid "WikiPage|Create page" msgstr "" -msgid "WikiPage|Edit rich text" -msgstr "" - -msgid "WikiPage|Edit source" -msgstr "" - msgid "WikiPage|Format" msgstr "" diff --git a/qa/qa/page/component/wiki_page_form.rb b/qa/qa/page/component/wiki_page_form.rb index 74b6c6b2d5e..22b9a4c8b0d 100644 --- a/qa/qa/page/component/wiki_page_form.rb +++ b/qa/qa/page/component/wiki_page_form.rb @@ -48,7 +48,9 @@ module QA end def use_new_editor - click_element(:editing_mode_button, mode: 'Edit rich text') + within_element(:editing_mode_button) do + find('label', text: 'Rich text').click + end wait_until(reload: false) do has_element?(:content_editor_container) diff --git a/spec/contracts/consumer/fixtures/project/pipeline/create_a_new_pipeline.fixture.js b/spec/contracts/consumer/fixtures/project/pipeline/create_a_new_pipeline.fixture.js new file mode 100644 index 00000000000..a732189e6fb --- /dev/null +++ b/spec/contracts/consumer/fixtures/project/pipeline/create_a_new_pipeline.fixture.js @@ -0,0 +1,43 @@ +/* eslint-disable @gitlab/require-i18n-strings */ + +import { Matchers } from '@pact-foundation/pact'; +import { REDIRECT_HTML } from '../../../helpers/common_regex_patterns'; + +const body = Matchers.term({ + matcher: REDIRECT_HTML, + generate: + '<html><body>You are being <a href="http://example.org/gitlab-org/gitlab-qa/-/pipelines/5">redirected</a>.</body></html>', +}); + +const NewProjectPipeline = { + success: { + status: 302, + headers: { + 'Content-Type': 'text/html; charset=utf-8', + }, + body, + }, + + scenario: { + state: 'a project with a valid .gitlab-ci.yml configuration exists', + uponReceiving: 'a request to create a new pipeline', + }, + + request: { + withRequest: { + method: 'POST', + path: '/gitlab-org/gitlab-qa/-/pipelines', + headers: { + Accept: '*/*', + 'Content-Type': 'application/json; charset=utf-8', + }, + body: { + ref: 'master', + }, + }, + }, +}; + +export { NewProjectPipeline }; + +/* eslint-enable @gitlab/require-i18n-strings */ diff --git a/spec/contracts/consumer/helpers/common_regex_patterns.js b/spec/contracts/consumer/helpers/common_regex_patterns.js index 664a71ab8a9..2fbb4ea49f8 100644 --- a/spec/contracts/consumer/helpers/common_regex_patterns.js +++ b/spec/contracts/consumer/helpers/common_regex_patterns.js @@ -3,6 +3,7 @@ */ export const URL = '^(http|https)://[a-z0-9]+([-.]{1}[a-z0-9]+)*.[a-z]{2,5}(:[0-9]{1,5})?(/.*)?$'; export const URL_PATH = '^/[a-zA-Z0-9#-=?_]+$'; +export const REDIRECT_HTML = 'You are being <a href=\\"(.)+/pipelines/[0-9]+\\">redirected</a>.'; // Pipelines export const PIPELINE_GROUPS = diff --git a/spec/contracts/consumer/resources/api/project/pipelines.js b/spec/contracts/consumer/resources/api/project/pipelines.js new file mode 100644 index 00000000000..f58a7a5fb0f --- /dev/null +++ b/spec/contracts/consumer/resources/api/project/pipelines.js @@ -0,0 +1,19 @@ +import axios from 'axios'; + +export async function postProjectPipelines(endpoint) { + const { url } = endpoint; + + return axios({ + method: 'POST', + baseURL: url, + url: '/gitlab-org/gitlab-qa/-/pipelines', + headers: { + Accept: '*/*', + 'Content-Type': 'application/json; charset=utf-8', + }, + data: { ref: 'master' }, + validateStatus: (status) => { + return status === 302; + }, + }); +} diff --git a/spec/contracts/consumer/resources/graphql/pipelines.js b/spec/contracts/consumer/resources/graphql/pipelines.js index b076006af17..48724e15eb8 100644 --- a/spec/contracts/consumer/resources/graphql/pipelines.js +++ b/spec/contracts/consumer/resources/graphql/pipelines.js @@ -16,9 +16,9 @@ export async function getPipelineHeaderDataRequest(endpoint) { }; return axios({ + method: 'POST', baseURL: url, url: '/api/graphql', - method: 'POST', headers: { Accept: '*/*' }, data: graphqlQuery, }); diff --git a/spec/contracts/consumer/specs/project/pipeline/new.spec.js b/spec/contracts/consumer/specs/project/pipeline/new.spec.js new file mode 100644 index 00000000000..621b31af52d --- /dev/null +++ b/spec/contracts/consumer/specs/project/pipeline/new.spec.js @@ -0,0 +1,45 @@ +/* eslint-disable @gitlab/require-i18n-strings */ + +import { pactWith } from 'jest-pact'; + +import { NewProjectPipeline } from '../../../fixtures/project/pipeline/create_a_new_pipeline.fixture'; +import { postProjectPipelines } from '../../../resources/api/project/pipelines'; + +const CONSUMER_NAME = 'Pipelines#new'; +const CONSUMER_LOG = '../logs/consumer.log'; +const CONTRACT_DIR = '../contracts/project/pipeline/new'; +const PROVIDER_NAME = 'POST Create a new pipeline'; + +// API endpoint: /pipelines.json +pactWith( + { + consumer: CONSUMER_NAME, + provider: PROVIDER_NAME, + log: CONSUMER_LOG, + dir: CONTRACT_DIR, + }, + + (provider) => { + describe(PROVIDER_NAME, () => { + beforeEach(async () => { + const interaction = { + ...NewProjectPipeline.scenario, + ...NewProjectPipeline.request, + willRespondWith: NewProjectPipeline.success, + }; + + provider.addInteraction(interaction); + }); + + it('returns a successful body', async () => { + const newPipeline = await postProjectPipelines({ + url: provider.mockService.baseUrl, + }); + + expect(newPipeline.status).toEqual(NewProjectPipeline.success.status); + }); + }); + }, +); + +/* eslint-enable @gitlab/require-i18n-strings */ diff --git a/spec/contracts/contracts/project/pipeline/new/pipelines#new-post_create_a_new_pipeline.json b/spec/contracts/contracts/project/pipeline/new/pipelines#new-post_create_a_new_pipeline.json new file mode 100644 index 00000000000..4627f0cb0bf --- /dev/null +++ b/spec/contracts/contracts/project/pipeline/new/pipelines#new-post_create_a_new_pipeline.json @@ -0,0 +1,43 @@ +{ + "consumer": { + "name": "Pipelines#new" + }, + "provider": { + "name": "POST Create a new pipeline" + }, + "interactions": [ + { + "description": "a request to create a new pipeline", + "providerState": "a project with a valid .gitlab-ci.yml configuration exists", + "request": { + "method": "POST", + "path": "/gitlab-org/gitlab-qa/-/pipelines", + "headers": { + "Accept": "*/*", + "Content-Type": "application/json; charset=utf-8" + }, + "body": { + "ref": "master" + } + }, + "response": { + "status": 302, + "headers": { + "Content-Type": "text/html; charset=utf-8" + }, + "body": "<html><body>You are being <a href=\"http://example.org/gitlab-org/gitlab-qa/-/pipelines/5\">redirected</a>.</body></html>", + "matchingRules": { + "$.body": { + "match": "regex", + "regex": "You are being <a href=\\\"(.)+\\/pipelines\\/[0-9]+\\\">redirected<\\/a>." + } + } + } + } + ], + "metadata": { + "pactSpecification": { + "version": "2.0.0" + } + } +}
\ No newline at end of file diff --git a/spec/contracts/provider/pact_helpers/project/pipeline/create_a_new_pipeline_helper.rb b/spec/contracts/provider/pact_helpers/project/pipeline/create_a_new_pipeline_helper.rb new file mode 100644 index 00000000000..e7d9b1452d3 --- /dev/null +++ b/spec/contracts/provider/pact_helpers/project/pipeline/create_a_new_pipeline_helper.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +require_relative '../../../spec_helper' +require_relative '../../../states/project/pipeline/new_state' + +module Provider + module CreateNewPipelineHelper + Pact.service_provider "POST Create a new pipeline" do + app { Environments::Test.app } + + honours_pact_with 'Pipelines#new' do + pact_uri '../contracts/project/pipeline/new/pipelines#new-post_create_a_new_pipeline.json' + end + end + end +end diff --git a/spec/contracts/provider/states/project/pipeline/new_state.rb b/spec/contracts/provider/states/project/pipeline/new_state.rb new file mode 100644 index 00000000000..95914180bec --- /dev/null +++ b/spec/contracts/provider/states/project/pipeline/new_state.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +Pact.provider_states_for "Pipelines#new" do + provider_state "a project with a valid .gitlab-ci.yml configuration exists" do + set_up do + user = User.find_by(name: Provider::UsersHelper::CONTRACT_USER_NAME) + namespace = create(:namespace, name: 'gitlab-org') + project = create( + :project, + :custom_repo, + name: 'gitlab-qa', + namespace: namespace, + creator: user, + files: { + '.gitlab-ci.yml' => <<~YAML + test-success: + script: echo 'OK' + YAML + }) + + project.add_maintainer(user) + end + end +end diff --git a/spec/controllers/groups/uploads_controller_spec.rb b/spec/controllers/groups/uploads_controller_spec.rb index 8fcc3a7fccf..645360289d1 100644 --- a/spec/controllers/groups/uploads_controller_spec.rb +++ b/spec/controllers/groups/uploads_controller_spec.rb @@ -67,30 +67,10 @@ RSpec.describe Groups::UploadsController do end context "when not signed in" do - context "enforce_auth_checks_on_uploads feature flag" do - context "with flag enabled" do - before do - stub_feature_flags(enforce_auth_checks_on_uploads: true) - end + it "responds with appropriate status" do + show_upload - it "responds with appropriate status" do - show_upload - - expect(response).to have_gitlab_http_status(:ok) - end - end - - context "with flag disabled" do - before do - stub_feature_flags(enforce_auth_checks_on_uploads: false) - end - - it "responds with status 200" do - show_upload - - expect(response).to have_gitlab_http_status(:ok) - end - end + expect(response).to have_gitlab_http_status(:ok) end end @@ -100,30 +80,10 @@ RSpec.describe Groups::UploadsController do end context "when the user doesn't have access to the model" do - context "enforce_auth_checks_on_uploads feature flag" do - context "with flag enabled" do - before do - stub_feature_flags(enforce_auth_checks_on_uploads: true) - end - - it "responds with status 200" do - show_upload - - expect(response).to have_gitlab_http_status(:ok) - end - end - end - - context "with flag disabled" do - before do - stub_feature_flags(enforce_auth_checks_on_uploads: false) - end - - it "responds with status 200" do - show_upload + it "responds with status 200" do + show_upload - expect(response).to have_gitlab_http_status(:ok) - end + expect(response).to have_gitlab_http_status(:ok) end end end @@ -135,30 +95,10 @@ RSpec.describe Groups::UploadsController do end context "when not signed in" do - context "enforce_auth_checks_on_uploads feature flag" do - context "with flag enabled" do - before do - stub_feature_flags(enforce_auth_checks_on_uploads: true) - end + it "responds with appropriate status" do + show_upload - it "responds with appropriate status" do - show_upload - - expect(response).to have_gitlab_http_status(:ok) - end - end - - context "with flag disabled" do - before do - stub_feature_flags(enforce_auth_checks_on_uploads: false) - end - - it "responds with status 200" do - show_upload - - expect(response).to have_gitlab_http_status(:ok) - end - end + expect(response).to have_gitlab_http_status(:ok) end end @@ -168,30 +108,10 @@ RSpec.describe Groups::UploadsController do end context "when the user doesn't have access to the model" do - context "enforce_auth_checks_on_uploads feature flag" do - context "with flag enabled" do - before do - stub_feature_flags(enforce_auth_checks_on_uploads: true) - end - - it "responds with status 200" do - show_upload - - expect(response).to have_gitlab_http_status(:ok) - end - end - end - - context "with flag disabled" do - before do - stub_feature_flags(enforce_auth_checks_on_uploads: false) - end - - it "responds with status 200" do - show_upload + it "responds with status 200" do + show_upload - expect(response).to have_gitlab_http_status(:ok) - end + expect(response).to have_gitlab_http_status(:ok) end end end diff --git a/spec/controllers/projects/uploads_controller_spec.rb b/spec/controllers/projects/uploads_controller_spec.rb index 6d2db25ade2..01635f2e158 100644 --- a/spec/controllers/projects/uploads_controller_spec.rb +++ b/spec/controllers/projects/uploads_controller_spec.rb @@ -86,47 +86,27 @@ RSpec.describe Projects::UploadsController do end context "when not signed in" do - context "enforce_auth_checks_on_uploads feature flag" do - context "with flag enabled" do - before do - stub_feature_flags(enforce_auth_checks_on_uploads: true) - end - - context 'when the project has setting enforce_auth_checks_on_uploads true' do - before do - model.update!(enforce_auth_checks_on_uploads: true) - end - - it "responds with status 302" do - show_upload - - expect(response).to have_gitlab_http_status(:redirect) - end - end - - context 'when the project has setting enforce_auth_checks_on_uploads false' do - before do - model.update!(enforce_auth_checks_on_uploads: false) - end + context 'when the project has setting enforce_auth_checks_on_uploads true' do + before do + model.update!(enforce_auth_checks_on_uploads: true) + end - it "responds with status 200" do - show_upload + it "responds with status 302" do + show_upload - expect(response).to have_gitlab_http_status(:ok) - end - end + expect(response).to have_gitlab_http_status(:redirect) end + end - context "with flag disabled" do - before do - stub_feature_flags(enforce_auth_checks_on_uploads: false) - end + context 'when the project has setting enforce_auth_checks_on_uploads false' do + before do + model.update!(enforce_auth_checks_on_uploads: false) + end - it "responds with status 200" do - show_upload + it "responds with status 200" do + show_upload - expect(response).to have_gitlab_http_status(:ok) - end + expect(response).to have_gitlab_http_status(:ok) end end end @@ -137,41 +117,21 @@ RSpec.describe Projects::UploadsController do end context "when the user doesn't have access to the model" do - context "enforce_auth_checks_on_uploads feature flag" do - context "with flag enabled" do - before do - stub_feature_flags(enforce_auth_checks_on_uploads: true) - end - - context 'when the project has setting enforce_auth_checks_on_uploads true' do - before do - model.update!(enforce_auth_checks_on_uploads: true) - end - - it "responds with status 404" do - show_upload - - expect(response).to have_gitlab_http_status(:not_found) - end - end - - context 'when the project has setting enforce_auth_checks_on_uploads false' do - before do - model.update!(enforce_auth_checks_on_uploads: false) - end - - it "responds with status 200" do - show_upload - - expect(response).to have_gitlab_http_status(:ok) - end - end + context 'when the project has setting enforce_auth_checks_on_uploads true' do + before do + model.update!(enforce_auth_checks_on_uploads: true) + end + + it "responds with status 404" do + show_upload + + expect(response).to have_gitlab_http_status(:not_found) end end - context "with flag disabled" do + context 'when the project has setting enforce_auth_checks_on_uploads false' do before do - stub_feature_flags(enforce_auth_checks_on_uploads: false) + model.update!(enforce_auth_checks_on_uploads: false) end it "responds with status 200" do @@ -190,47 +150,27 @@ RSpec.describe Projects::UploadsController do end context "when not signed in" do - context "enforce_auth_checks_on_uploads feature flag" do - context "with flag enabled" do - before do - stub_feature_flags(enforce_auth_checks_on_uploads: true) - end - - context 'when the project has setting enforce_auth_checks_on_uploads true' do - before do - model.update!(enforce_auth_checks_on_uploads: true) - end - - it "responds with status 200" do - show_upload - - expect(response).to have_gitlab_http_status(:ok) - end - end + context 'when the project has setting enforce_auth_checks_on_uploads true' do + before do + model.update!(enforce_auth_checks_on_uploads: true) + end - context 'when the project has setting enforce_auth_checks_on_uploads false' do - before do - model.update!(enforce_auth_checks_on_uploads: false) - end + it "responds with status 200" do + show_upload - it "responds with status 200" do - show_upload + expect(response).to have_gitlab_http_status(:ok) + end + end - expect(response).to have_gitlab_http_status(:ok) - end - end + context 'when the project has setting enforce_auth_checks_on_uploads false' do + before do + model.update!(enforce_auth_checks_on_uploads: false) end - context "with flag disabled" do - before do - stub_feature_flags(enforce_auth_checks_on_uploads: false) - end + it "responds with status 200" do + show_upload - it "responds with status 200" do - show_upload - - expect(response).to have_gitlab_http_status(:ok) - end + expect(response).to have_gitlab_http_status(:ok) end end end @@ -241,41 +181,21 @@ RSpec.describe Projects::UploadsController do end context "when the user doesn't have access to the model" do - context "enforce_auth_checks_on_uploads feature flag" do - context "with flag enabled" do - before do - stub_feature_flags(enforce_auth_checks_on_uploads: true) - end - - context 'when the project has setting enforce_auth_checks_on_uploads true' do - before do - model.update!(enforce_auth_checks_on_uploads: true) - end - - it "responds with status 200" do - show_upload - - expect(response).to have_gitlab_http_status(:ok) - end - end - - context 'when the project has setting enforce_auth_checks_on_uploads false' do - before do - model.update!(enforce_auth_checks_on_uploads: false) - end - - it "responds with status 200" do - show_upload - - expect(response).to have_gitlab_http_status(:ok) - end - end + context 'when the project has setting enforce_auth_checks_on_uploads true' do + before do + model.update!(enforce_auth_checks_on_uploads: true) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) end end - context "with flag disabled" do + context 'when the project has setting enforce_auth_checks_on_uploads false' do before do - stub_feature_flags(enforce_auth_checks_on_uploads: false) + model.update!(enforce_auth_checks_on_uploads: false) end it "responds with status 200" do diff --git a/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js b/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js index a5db10d106d..160e0832d35 100644 --- a/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js +++ b/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js @@ -1,5 +1,5 @@ import { nextTick } from 'vue'; -import { GlAlert, GlButton, GlFormInput, GlFormGroup } from '@gitlab/ui'; +import { GlAlert, GlButton, GlFormInput, GlFormGroup, GlSegmentedControl } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; @@ -106,6 +106,7 @@ describe('WikiForm', () => { MarkdownField, GlAlert, GlButton, + GlSegmentedControl, LocalStorageSync: stubComponent(LocalStorageSync), GlFormInput, GlFormGroup, @@ -317,20 +318,20 @@ describe('WikiForm', () => { }); describe('when content editor is not active', () => { - it('displays "Edit rich text" label in the toggle editing mode button', () => { - expect(findToggleEditingModeButton().text()).toBe('Edit rich text'); + it('displays "Source" label in the toggle editing mode button', () => { + expect(findToggleEditingModeButton().props().checked).toBe('source'); }); describe('when clicking the toggle editing mode button', () => { beforeEach(async () => { - await findToggleEditingModeButton().trigger('click'); + await findToggleEditingModeButton().vm.$emit('input', 'richText'); }); it('hides the classic editor', () => { expect(findClassicEditor().exists()).toBe(false); }); - it('hides the content editor', () => { + it('shows the content editor', () => { expect(findContentEditor().exists()).toBe(true); }); }); @@ -342,7 +343,7 @@ describe('WikiForm', () => { expect(findContentEditor().exists()).toBe(false); // enable content editor - await findLocalStorageSync().vm.$emit('input', true); + await findLocalStorageSync().vm.$emit('input', 'richText'); expect(findContentEditor().exists()).toBe(true); expect(findClassicEditor().exists()).toBe(false); @@ -352,17 +353,18 @@ describe('WikiForm', () => { describe('when content editor is active', () => { let mockContentEditor; - beforeEach(async () => { + beforeEach(() => { + createWrapper(); mockContentEditor = { getSerializedContent: jest.fn(), setSerializedContent: jest.fn(), }; - await findToggleEditingModeButton().trigger('click'); + findToggleEditingModeButton().vm.$emit('input', 'richText'); }); - it('displays "Edit source" label in the toggle editing mode button', () => { - expect(findToggleEditingModeButton().text()).toBe('Edit source'); + it('displays "Edit Rich" label in the toggle editing mode button', () => { + expect(findToggleEditingModeButton().props().checked).toBe('richText'); }); describe('when clicking the toggle editing mode button', () => { @@ -374,7 +376,8 @@ describe('WikiForm', () => { ); findContentEditor().vm.$emit('initialized', mockContentEditor); - await findToggleEditingModeButton().trigger('click'); + await findToggleEditingModeButton().vm.$emit('input', 'source'); + await nextTick(); }); it('hides the content editor', () => { @@ -398,7 +401,7 @@ describe('WikiForm', () => { createWrapper({ mountFn: mount }); mock.onPost(/preview-markdown/).reply(400); - await findToggleEditingModeButton().trigger('click'); + await findToggleEditingModeButton().vm.$emit('input', 'richText'); // try waiting for content editor to load (but it will never actually load) await waitForPromises(); @@ -410,7 +413,7 @@ describe('WikiForm', () => { describe('toggling editing modes to the classic editor', () => { beforeEach(() => { - return findToggleEditingModeButton().trigger('click'); + return findToggleEditingModeButton().vm.$emit('input', 'source'); }); it('switches to classic editor', () => { @@ -426,7 +429,7 @@ describe('WikiForm', () => { mock.onPost(/preview-markdown/).reply(200, { body: '<p>hello <strong>world</strong></p>' }); - await findToggleEditingModeButton().trigger('click'); + await findToggleEditingModeButton().vm.$emit('input', 'richText'); await waitForPromises(); }); @@ -463,7 +466,6 @@ describe('WikiForm', () => { it('triggers tracking events on form submit', async () => { await triggerFormSubmit(); - expect(trackingSpy).toHaveBeenCalledWith(undefined, SAVED_USING_CONTENT_EDITOR_ACTION, { label: WIKI_CONTENT_EDITOR_TRACKING_LABEL, }); diff --git a/spec/lib/tasks/gitlab/metrics_exporter_task_spec.rb b/spec/lib/tasks/gitlab/metrics_exporter_task_spec.rb index dfb3c511470..4e17e91f019 100644 --- a/spec/lib/tasks/gitlab/metrics_exporter_task_spec.rb +++ b/spec/lib/tasks/gitlab/metrics_exporter_task_spec.rb @@ -26,7 +26,7 @@ RSpec.describe 'gitlab:metrics_exporter:install' do let(:expected_clone_params) do { repo: 'https://gitlab.com/gitlab-org/gitlab-metrics-exporter.git', - version: 'main', + version: an_instance_of(String), target_dir: 'path/to/exporter' } end diff --git a/spec/lib/unnested_in_filters/rewriter_spec.rb b/spec/lib/unnested_in_filters/rewriter_spec.rb index e2ccbd92504..a808aec7728 100644 --- a/spec/lib/unnested_in_filters/rewriter_spec.rb +++ b/spec/lib/unnested_in_filters/rewriter_spec.rb @@ -88,6 +88,35 @@ RSpec.describe UnnestedInFilters::Rewriter do expect(issued_query.gsub(/\s/, '')).to start_with(expected_query.gsub(/\s/, '')) end + context 'when the relation has a subquery' do + let(:relation) { User.where(state: User.select(:state), user_type: %i(support_bot alert_bot)).limit(1) } + + let(:expected_query) do + <<~SQL + SELECT + "users".* + FROM + unnest(ARRAY(SELECT "users"."state" FROM "users")::character varying[]) AS "states"("state"), + unnest('{1,2}'::smallint[]) AS "user_types"("user_type"), + LATERAL ( + SELECT + "users".* + FROM + "users" + WHERE + (users."state" = "states"."state") AND + (users."user_type" = "user_types"."user_type") + LIMIT 1 + ) AS users + LIMIT 1 + SQL + end + + it 'changes the query' do + expect(issued_query.gsub(/\s/, '')).to start_with(expected_query.gsub(/\s/, '')) + end + end + context 'when there is an order' do let(:relation) { User.where(state: %w(active blocked banned)).order(order).limit(2) } let(:expected_query) do diff --git a/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb b/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb index 6dca94ecf0a..0792ac14e47 100644 --- a/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb +++ b/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb @@ -205,41 +205,13 @@ RSpec.shared_examples 'handle uploads' do allow_any_instance_of(FileUploader).to receive(:image?).and_return(true) end - context "enforce_auth_checks_on_uploads feature flag" do - context "with flag enabled" do - before do - stub_feature_flags(enforce_auth_checks_on_uploads: true) - end + it "responds with the appropriate status code" do + show_upload - it "responds with appropriate status" do - show_upload - - # We're switching here based on the class due to the feature - # flag :enforce_auth_checks_on_uploads switching on project. - # When it is enabled fully, we will apply the code it guards - # to both Projects::UploadsController as well as - # Groups::UploadsController. - # - # https://gitlab.com/gitlab-org/gitlab/-/issues/352291 - # - if model.instance_of?(Group) - expect(response).to have_gitlab_http_status(:ok) - else - expect(response).to have_gitlab_http_status(:redirect) - end - end - end - - context "with flag disabled" do - before do - stub_feature_flags(enforce_auth_checks_on_uploads: false) - end - - it "responds with status 200" do - show_upload - - expect(response).to have_gitlab_http_status(:ok) - end + if model.instance_of?(Group) + expect(response).to have_gitlab_http_status(:ok) + else + expect(response).to have_gitlab_http_status(:redirect) end end end @@ -308,41 +280,13 @@ RSpec.shared_examples 'handle uploads' do allow_any_instance_of(FileUploader).to receive(:image?).and_return(true) end - context "enforce_auth_checks_on_uploads feature flag" do - context "with flag enabled" do - before do - stub_feature_flags(enforce_auth_checks_on_uploads: true) - end - - it "responds with status 404" do - show_upload - - # We're switching here based on the class due to the feature - # flag :enforce_auth_checks_on_uploads switching on - # project. When it is enabled fully, we will apply the - # code it guards to both Projects::UploadsController as - # well as Groups::UploadsController. - # - # https://gitlab.com/gitlab-org/gitlab/-/issues/352291 - # - if model.instance_of?(Group) - expect(response).to have_gitlab_http_status(:ok) - else - expect(response).to have_gitlab_http_status(:not_found) - end - end - end - - context "with flag disabled" do - before do - stub_feature_flags(enforce_auth_checks_on_uploads: false) - end - - it "responds with status 200" do - show_upload + it "responds with the appropriate status code" do + show_upload - expect(response).to have_gitlab_http_status(:ok) - end + if model.instance_of?(Group) + expect(response).to have_gitlab_http_status(:ok) + else + expect(response).to have_gitlab_http_status(:not_found) end end end diff --git a/spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb index 79c7c1891ac..87067336a36 100644 --- a/spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb +++ b/spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb @@ -140,7 +140,7 @@ RSpec.shared_examples 'User updates wiki page' do context 'when using the content editor' do context 'with feature flag on' do before do - click_button 'Edit rich text' + find('[data-testid="toggle-editing-mode-button"] label', text: 'Rich text').click end it_behaves_like 'edits content using the content editor' |