diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 405346d68da..314f99c5f41 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -80,6 +80,7 @@ variables: CACHE_CLASSES: "true" CHECK_PRECOMPILED_ASSETS: "true" FF_USE_FASTZIP: "true" + SKIP_FLAKY_TESTS_AUTOMATICALLY: "true" DOCS_REVIEW_APPS_DOMAIN: "178.62.207.141.nip.io" DOCS_GITLAB_REPO_SUFFIX: "ee" diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index e6b80f90dca..46738651960 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -6,6 +6,9 @@ class ProfilesController < Profiles::ApplicationController before_action :user before_action :authorize_change_username!, only: :update_username + before_action only: :update_username do + check_rate_limit!(:profile_update_username, scope: current_user) if Feature.enabled?(:rate_limit_profile_update_username, default_enabled: :yaml) + end skip_before_action :require_email, only: [:show, :update] before_action do push_frontend_feature_flag(:webauthn, default_enabled: :yaml) diff --git a/config/feature_flags/development/rate_limit_profile_update_username.yml b/config/feature_flags/development/rate_limit_profile_update_username.yml new file mode 100644 index 00000000000..e72e3d605e3 --- /dev/null +++ b/config/feature_flags/development/rate_limit_profile_update_username.yml @@ -0,0 +1,8 @@ +--- +name: rate_limit_profile_update_username +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77221 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/349132 +milestone: '14.7' +type: development +group: group::optimize +default_enabled: false diff --git a/config/routes.rb b/config/routes.rb index b02c1380c7e..a77edbe0b21 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -145,9 +145,6 @@ Rails.application.routes.draw do get 'acme-challenge/' => 'acme_challenges#show' - # UserCallouts - resources :user_callouts, controller: 'users/callouts', only: [:create] # remove after 14.6 2021-12-22 to handle mixed deployments - scope :ide, as: :ide, format: false do get '/', to: 'ide#index' get '/project', to: 'ide#index' diff --git a/doc/.vale/gitlab/ReadingLevel.yml b/doc/.vale/gitlab/ReadingLevel.yml index 2e78c3ef36c..cd7597ee8dc 100644 --- a/doc/.vale/gitlab/ReadingLevel.yml +++ b/doc/.vale/gitlab/ReadingLevel.yml @@ -3,11 +3,11 @@ # # Checks the Flesch-Kincaid reading level. # -# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles -extends: readability -message: "Grade level (%s) is high. To lower the score, use shorter sentences and words." +# https://docs.errata.ai/vale/styles#metric +extends: metric +message: "The grade level - %s - refers to how hard the content is to understand. Aim for 8th grade or lower by using shorter sentences and words." link: https://docs.gitlab.com/ee/development/documentation/testing.html#vale-readability-score level: suggestion -grade: 8 -metrics: - - Flesch-Kincaid +formula: | + (0.39 * (words / sentences)) + (11.8 * (syllables / words)) - 15.59 +condition: "> 1" diff --git a/doc/administration/merge_request_diffs.md b/doc/administration/merge_request_diffs.md index f45df3e620b..01576eb4abf 100644 --- a/doc/administration/merge_request_diffs.md +++ b/doc/administration/merge_request_diffs.md @@ -14,7 +14,8 @@ By default, merge request diffs are stored in the database, in a table named `merge_request_diff_files`. Larger installations may find this table grows too large, in which case, switching to external storage is recommended. -Merge request diffs can be stored on disk, or in object storage. In general, it +Merge request diffs can be stored [on disk](#using-external-storage), or in +[object storage](#using-object-storage). In general, it is better to store the diffs in the database than on disk. A compromise is available that only [stores outdated diffs](#alternative-in-database-storage) outside of database. @@ -38,6 +39,7 @@ that only [stores outdated diffs](#alternative-in-database-storage) outside of d ``` 1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. + GitLab then migrates your existing merge request diffs to external storage. **In installations from source:** @@ -61,6 +63,7 @@ that only [stores outdated diffs](#alternative-in-database-storage) outside of d ``` 1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect. + GitLab then migrates your existing merge request diffs to external storage. ## Using object storage @@ -81,6 +84,7 @@ be configured already. 1. Set [object storage settings](#object-storage-settings). 1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. + GitLab then migrates your existing merge request diffs to external storage. **In installations from source:** @@ -94,6 +98,7 @@ be configured already. 1. Set [object storage settings](#object-storage-settings). 1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect. + GitLab then migrates your existing merge request diffs to external storage. [Read more about using object storage with GitLab](object_storage.md). diff --git a/doc/administration/object_storage.md b/doc/administration/object_storage.md index e9e43cf2309..0976fc3684e 100644 --- a/doc/administration/object_storage.md +++ b/doc/administration/object_storage.md @@ -48,6 +48,9 @@ There are two ways of specifying object storage configuration in GitLab: For more information on the differences and to transition from one form to another, see [Transition to consolidated form](#transition-to-consolidated-form). +If you are currently storing data locally, see +[Migrate to object storage](#migrate-to-object-storage) for migration details. + ### Consolidated object storage configuration > [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4368) in GitLab 13.2. @@ -485,9 +488,9 @@ This is the list of valid `objects` that can be used: | `uploads` | [User uploads](uploads.md) | | `lfs` | [Git Large File Storage objects](lfs/index.md) | | `packages` | [Project packages (for example, PyPI, Maven, or NuGet)](packages/index.md) | -| `dependency_proxy` | [GitLab Dependency Proxy](packages/dependency_proxy.md) | +| `dependency_proxy` | [Dependency Proxy](packages/dependency_proxy.md) | | `terraform_state` | [Terraform state files](terraform_state.md) | -| `pages` | [GitLab Pages](pages/index.md) | +| `pages` | [Pages](pages/index.md) | Within each object type, three parameters can be defined: @@ -514,6 +517,19 @@ no bucket is needed if CI artifacts are disabled with this setting: gitlab_rails['artifacts_enabled'] = false ``` +### Migrate to object storage + +To migrate existing local data to object storage see the following guides: + +- [Job artifacts](job_artifacts.md#migrating-to-object-storage) including archived job logs +- [LFS objects](lfs/index.md#migrating-to-object-storage) +- [Uploads](raketasks/uploads/migrate.md#migrate-to-object-storage) +- [Merge request diffs](merge_request_diffs.md#using-object-storage) +- [Packages](packages/index.md#migrating-local-packages-to-object-storage) (optional feature) +- Dependency Proxy - [migration not yet supported](https://gitlab.com/gitlab-org/gitlab/-/issues/343064) +- [Terraform state files](terraform_state.md#migrate-to-object-storage) +- [Pages content](pages/index.md#migrate-pages-deployments-to-object-storage) + ### Transition to consolidated form Prior to GitLab 13.2: @@ -565,11 +581,11 @@ supported by consolidated configuration form, refer to the following guides: | [Merge request diffs](merge_request_diffs.md#using-object-storage) | **{check-circle}** Yes | | [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)| **{dotted-circle}** No | | [Packages](packages/index.md#using-object-storage) (optional feature) | **{check-circle}** Yes | -| [Dependency Proxy](packages/dependency_proxy.md#using-object-storage) (optional feature) **(PREMIUM SELF)** | **{check-circle}** Yes | +| [Dependency Proxy](packages/dependency_proxy.md#using-object-storage) (optional feature) | **{check-circle}** Yes | | [Pseudonymizer](pseudonymizer.md) (optional feature) | **{dotted-circle}** No | | [Autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional for improved performance) | **{dotted-circle}** No | | [Terraform state files](terraform_state.md#using-object-storage) | **{check-circle}** Yes | -| [GitLab Pages content](pages/index.md#using-object-storage) | **{check-circle}** Yes | +| [Pages content](pages/index.md#using-object-storage) | **{check-circle}** Yes | ### Other alternatives to file system storage diff --git a/doc/api/packages.md b/doc/api/packages.md index a75b2e376fa..9eb732cd5d6 100644 --- a/doc/api/packages.md +++ b/doc/api/packages.md @@ -26,7 +26,7 @@ GET /projects/:id/packages | `id` | integer/string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) | | `order_by`| string | no | The field to use as order. One of `created_at` (default), `name`, `version`, or `type`. | | `sort` | string | no | The direction of the order, either `asc` (default) for ascending order or `desc` for descending order. | -| `package_type` | string | no | Filter the returned packages by type. One of `conan`, `maven`, `npm`, `pypi`, `composer`, `nuget`, `helm`, or `golang`. (_Introduced in GitLab 12.9_) +| `package_type` | string | no | Filter the returned packages by type. One of `conan`, `maven`, `npm`, `pypi`, `composer`, `nuget`, `helm`, `terraform_module`, or `golang`. (_Introduced in GitLab 12.9_) | `package_name` | string | no | Filter the project packages with a fuzzy search by name. (_Introduced in GitLab 12.9_) | `include_versionless` | boolean | no | When set to true, versionless packages are included in the response. (_Introduced in GitLab 13.8_) | `status` | string | no | Filter the returned packages by status. One of `default` (default), `hidden`, or `processing`. (_Introduced in GitLab 13.9_) diff --git a/doc/development/documentation/testing.md b/doc/development/documentation/testing.md index 13648a7c710..134183a0e75 100644 --- a/doc/development/documentation/testing.md +++ b/doc/development/documentation/testing.md @@ -234,15 +234,8 @@ As a general guideline, the lower the score, the more readable the documentation For example, a page that scores `12` before a set of changes, and `9` after, indicates an iterative improvement to readability. The score is not an exact science, but is meant to help indicate the general complexity level of the page. -The readability score is calculated by using the following formula: - -```plaintext -(.39 x ASL) + (11.8 x ASW) – 15.59 -``` - -- `ASL` is average sentence length (the number of words divided by the number of sentences). -- `ASW` is the average number of syllables per word (the number of syllables divided by the number of words). -- The score excludes headings, code blocks, and lists. +The readability score is calculated based on the number of words per sentence, and the number +of syllables per word. For more information, see [the Vale documentation](https://docs.errata.ai/vale/styles#metric). ### Install linters diff --git a/doc/development/pipelines.md b/doc/development/pipelines.md index cde44a8eb01..a9c68905095 100644 --- a/doc/development/pipelines.md +++ b/doc/development/pipelines.md @@ -170,10 +170,9 @@ After that, the next pipeline uses the up-to-date `knapsack/report-master.json` ### Flaky tests -Tests that are [known to be flaky](testing_guide/flaky_tests.md#automatic-retries-and-flaky-tests-detection) are: - -- skipped if the `$SKIP_FLAKY_TESTS_AUTOMATICALLY` variable is set to `true` (`false` by default) -- run if `$SKIP_FLAKY_TESTS_AUTOMATICALLY` variable is not set to `true` or if the `~"pipeline:run-flaky-tests"` label is set on the MR +Tests that are [known to be flaky](testing_guide/flaky_tests.md#automatic-retries-and-flaky-tests-detection) are +skipped unless the `$SKIP_FLAKY_TESTS_AUTOMATICALLY` variable is set to `false` or if the `~"pipeline:run-flaky-tests"` +label is set on the MR. ### Monitoring diff --git a/doc/install/next_steps.md b/doc/install/next_steps.md index b5cfbfc9bbb..1db2bf9b7b6 100644 --- a/doc/install/next_steps.md +++ b/doc/install/next_steps.md @@ -20,9 +20,11 @@ installation. Runners, the agents that are responsible for all of the GitLab CI/CD features. - [GitLab Pages](../administration/pages/index.md): Configure GitLab Pages to allow hosting of static sites. -- [GitLab Registry](../administration/packages/container_registry.md): With the - GitLab Container Registry, every project can have its own space to store Docker +- [GitLab Registry](../administration/packages/container_registry.md): Set up the + GitLab Container Registry so every project can have its own space to store Docker images. +- [GitLab Dependency Proxy](../administration/packages/dependency_proxy.md): Set up the dependency + proxy so you can cache container images from Docker Hub for faster, more reliable builds. ## Security diff --git a/lib/gitlab/application_rate_limiter.rb b/lib/gitlab/application_rate_limiter.rb index d02582d0362..a1310ef89e3 100644 --- a/lib/gitlab/application_rate_limiter.rb +++ b/lib/gitlab/application_rate_limiter.rb @@ -51,6 +51,7 @@ module Gitlab web_hook_calls: { interval: 1.minute }, users_get_by_id: { threshold: 10, interval: 1.minute }, profile_resend_email_confirmation: { threshold: 5, interval: 1.minute }, + profile_update_username: { threshold: 10, interval: 1.minute }, update_environment_canary_ingress: { threshold: 1, interval: 1.minute }, auto_rollback_deployment: { threshold: 1, interval: 3.minutes }, user_email_lookup: { threshold: -> { application_settings.user_email_lookup_limit }, interval: 1.minute } diff --git a/spec/controllers/profiles_controller_spec.rb b/spec/controllers/profiles_controller_spec.rb index 9a1f8a8442d..6e7cc058fbc 100644 --- a/spec/controllers/profiles_controller_spec.rb +++ b/spec/controllers/profiles_controller_spec.rb @@ -153,9 +153,12 @@ RSpec.describe ProfilesController, :request_store do let(:gitlab_shell) { Gitlab::Shell.new } let(:new_username) { generate(:username) } - it 'allows username change' do + before do sign_in(user) + allow(::Gitlab::ApplicationRateLimiter).to receive(:throttled?).and_return(false) + end + it 'allows username change' do put :update_username, params: { user: { username: new_username } } @@ -166,8 +169,6 @@ RSpec.describe ProfilesController, :request_store do end it 'updates a username using JSON request' do - sign_in(user) - put :update_username, params: { user: { username: new_username } @@ -179,8 +180,6 @@ RSpec.describe ProfilesController, :request_store do end it 'renders an error message when the username was not updated' do - sign_in(user) - put :update_username, params: { user: { username: 'invalid username.git' } @@ -192,8 +191,6 @@ RSpec.describe ProfilesController, :request_store do end it 'raises a correct error when the username is missing' do - sign_in(user) - expect { put :update_username, params: { user: { gandalf: 'you shall not pass' } } } .to raise_error(ActionController::ParameterMissing) end @@ -202,8 +199,6 @@ RSpec.describe ProfilesController, :request_store do it 'moves dependent projects to new namespace' do project = create(:project_empty_repo, :legacy_storage, namespace: namespace) - sign_in(user) - put :update_username, params: { user: { username: new_username } } @@ -220,8 +215,6 @@ RSpec.describe ProfilesController, :request_store do before_disk_path = project.disk_path - sign_in(user) - put :update_username, params: { user: { username: new_username } } @@ -232,5 +225,18 @@ RSpec.describe ProfilesController, :request_store do expect(before_disk_path).to eq(project.disk_path) end end + + context 'when the rate limit is reached' do + it 'does not update the username and returns status 429 Too Many Requests' do + expect(::Gitlab::ApplicationRateLimiter).to receive(:throttled?).with(:profile_update_username, scope: user).and_return(true) + + expect do + put :update_username, + params: { user: { username: new_username } } + end.not_to change { user.reload.username } + + expect(response).to have_gitlab_http_status(:too_many_requests) + end + end end end diff --git a/spec/support/flaky_tests.rb b/spec/support/flaky_tests.rb index 0c211af695d..5ce55c47aab 100644 --- a/spec/support/flaky_tests.rb +++ b/spec/support/flaky_tests.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true return unless ENV['CI'] -return unless ENV['SKIP_FLAKY_TESTS_AUTOMATICALLY'] == "true" +return if ENV['SKIP_FLAKY_TESTS_AUTOMATICALLY'] == "false" return if ENV['CI_MERGE_REQUEST_LABELS'].to_s.include?('pipeline:run-flaky-tests') require_relative '../../tooling/rspec_flaky/report'