diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-11-03 18:13:40 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-11-03 18:13:40 +0000 |
commit | bbc36645d34c557df40d031a1a41fbd05e491644 (patch) | |
tree | 55529c6e93d72f7e35e78488a397f50098f137a5 | |
parent | 70a50740a20ab0027e0490487f6244f5ec961eee (diff) | |
download | gitlab-ce-bbc36645d34c557df40d031a1a41fbd05e491644.tar.gz |
Add latest changes from gitlab-org/gitlab@master
27 files changed, 666 insertions, 386 deletions
diff --git a/.gitlab/issue_templates/Feature proposal - detailed.md b/.gitlab/issue_templates/Feature proposal - detailed.md index 6448553d1b0..c787fc99333 100644 --- a/.gitlab/issue_templates/Feature proposal - detailed.md +++ b/.gitlab/issue_templates/Feature proposal - detailed.md @@ -31,6 +31,14 @@ Personas are described at https://about.gitlab.com/handbook/marketing/product-ma * [Eddie (Content Editor)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#eddie-content-editor) --> +### Metrics + +<!-- How are you going to track uage of this feature? Think about user behavior and their interaction with the product. What indicates someone is getting value from it? + +Create tracking issue using the Snowplow event tracking template. See https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Snowplow%20event%20tracking.md + +--> + ### User experience goal <!-- What is the single user experience workflow this problem addresses? diff --git a/CHANGELOG.md b/CHANGELOG.md index 83934210e78..fd895fc2220 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3064,6 +3064,13 @@ No changes. - [Add missing metrics information](gitlab-org/gitlab@89cd7fe3b95323e635b2d73e08549b2e6153dc4d) ([merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61772/edit)) - [Track usage of the resolve UI](gitlab-org/gitlab@35c8e30fce288cecefcf2f7c0077d4608e696519) ([merge request](gitlab-org/gitlab!61654)) +## 13.12.14 (2021-11-03) + +### Fixed (2 changes) + +- [Allow nil for remaining ci cd settings](gitlab-org/gitlab@896fd7ecf23714fa9f710efa4af245a26c677dce) ([merge request](gitlab-org/gitlab!73522)) +- [Allow nil on delegated CI/CD settings](gitlab-org/gitlab@d57a9ea79080fc473eb54c0ee696a50fd270e8a4) ([merge request](gitlab-org/gitlab!73522)) + ## 13.12.13 (2021-10-29) No changes. diff --git a/app/assets/javascripts/boards/components/board_filtered_search.vue b/app/assets/javascripts/boards/components/board_filtered_search.vue index 6352228b057..86f512a5117 100644 --- a/app/assets/javascripts/boards/components/board_filtered_search.vue +++ b/app/assets/javascripts/boards/components/board_filtered_search.vue @@ -1,5 +1,5 @@ <script> -import { pickBy } from 'lodash'; +import { pickBy, isEmpty } from 'lodash'; import { mapActions } from 'vuex'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import { updateHistory, setUrlParams } from '~/lib/utils/url_utility'; @@ -20,6 +20,11 @@ export default { type: Array, required: true, }, + eeFilters: { + required: false, + type: Object, + default: () => ({}), + }, }, data() { return { @@ -27,61 +32,6 @@ export default { }; }, computed: { - urlParams() { - const { - authorUsername, - labelName, - assigneeUsername, - search, - milestoneTitle, - types, - weight, - epicId, - } = this.filterParams; - - let notParams = {}; - - if (Object.prototype.hasOwnProperty.call(this.filterParams, 'not')) { - notParams = pickBy( - { - 'not[label_name][]': this.filterParams.not.labelName, - 'not[author_username]': this.filterParams.not.authorUsername, - 'not[assignee_username]': this.filterParams.not.assigneeUsername, - 'not[types]': this.filterParams.not.types, - 'not[milestone_title]': this.filterParams.not.milestoneTitle, - 'not[weight]': this.filterParams.not.weight, - 'not[epic_id]': this.filterParams.not.epicId, - }, - undefined, - ); - } - - return { - ...notParams, - author_username: authorUsername, - 'label_name[]': labelName, - assignee_username: assigneeUsername, - milestone_title: milestoneTitle, - search, - types, - weight, - epic_id: getIdFromGraphQLId(epicId), - }; - }, - }, - methods: { - ...mapActions(['performSearch']), - handleFilter(filters) { - this.filterParams = this.getFilterParams(filters); - - updateHistory({ - url: setUrlParams(this.urlParams, window.location.href, true, false, true), - title: document.title, - replace: true, - }); - - this.performSearch(); - }, getFilteredSearchValue() { const { authorUsername, @@ -203,6 +153,66 @@ export default { return filteredSearchValue; }, + urlParams() { + const { + authorUsername, + labelName, + assigneeUsername, + search, + milestoneTitle, + types, + weight, + epicId, + } = this.filterParams; + + let notParams = {}; + + if (Object.prototype.hasOwnProperty.call(this.filterParams, 'not')) { + notParams = pickBy( + { + 'not[label_name][]': this.filterParams.not.labelName, + 'not[author_username]': this.filterParams.not.authorUsername, + 'not[assignee_username]': this.filterParams.not.assigneeUsername, + 'not[types]': this.filterParams.not.types, + 'not[milestone_title]': this.filterParams.not.milestoneTitle, + 'not[weight]': this.filterParams.not.weight, + 'not[epic_id]': this.filterParams.not.epicId, + }, + undefined, + ); + } + + return { + ...notParams, + author_username: authorUsername, + 'label_name[]': labelName, + assignee_username: assigneeUsername, + milestone_title: milestoneTitle, + search, + types, + weight, + epic_id: getIdFromGraphQLId(epicId), + }; + }, + }, + created() { + if (!isEmpty(this.eeFilters)) { + this.filterParams = this.eeFilters; + } + }, + methods: { + ...mapActions(['performSearch']), + handleFilter(filters) { + this.filterParams = this.getFilterParams(filters); + + updateHistory({ + url: setUrlParams(this.urlParams, window.location.href, true, false, true), + title: document.title, + replace: true, + }); + + this.performSearch(); + }, getFilterParams(filters = []) { const notFilters = filters.filter((item) => item.value.operator === '!='); const equalsFilters = filters.filter( @@ -266,7 +276,7 @@ export default { namespace="" :tokens="tokens" :search-input-placeholder="$options.i18n.search" - :initial-filter-value="getFilteredSearchValue()" + :initial-filter-value="getFilteredSearchValue" @onFilter="handleFilter" /> </template> diff --git a/app/assets/javascripts/pipelines/constants.js b/app/assets/javascripts/pipelines/constants.js index 5678b613ec6..d123f7a203c 100644 --- a/app/assets/javascripts/pipelines/constants.js +++ b/app/assets/javascripts/pipelines/constants.js @@ -49,3 +49,5 @@ export const PipelineKeyOptions = [ key: 'iid', }, ]; + +export const TOAST_MESSAGE = s__('Pipeline|Creating pipeline.'); diff --git a/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js b/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js index 082d67c938c..3201f88a9e3 100644 --- a/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js +++ b/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js @@ -4,7 +4,7 @@ import { historyPushState, buildUrlWithCurrentLocation } from '~/lib/utils/commo import Poll from '~/lib/utils/poll'; import { __ } from '~/locale'; import { validateParams } from '~/pipelines/utils'; -import { CANCEL_REQUEST } from '../constants'; +import { CANCEL_REQUEST, TOAST_MESSAGE } from '../constants'; import eventHub from '../event_hub'; export default { @@ -191,7 +191,10 @@ export default { this.service .runMRPipeline(options) - .then(() => this.updateTable()) + .then(() => { + this.$toast.show(TOAST_MESSAGE); + this.updateTable(); + }) .catch(() => { createFlash({ message: __( diff --git a/app/controllers/jira_connect/app_descriptor_controller.rb b/app/controllers/jira_connect/app_descriptor_controller.rb index e96242c7052..16bd73f5ab6 100644 --- a/app/controllers/jira_connect/app_descriptor_controller.rb +++ b/app/controllers/jira_connect/app_descriptor_controller.rb @@ -32,7 +32,7 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController apiVersion: 1, apiMigrations: { 'context-qsh': true, - 'signed-install': signed_install_active?, + 'signed-install': true, gdpr: true } } diff --git a/app/controllers/jira_connect/application_controller.rb b/app/controllers/jira_connect/application_controller.rb index 1d1575f3a05..352e78d6255 100644 --- a/app/controllers/jira_connect/application_controller.rb +++ b/app/controllers/jira_connect/application_controller.rb @@ -74,8 +74,4 @@ class JiraConnect::ApplicationController < ApplicationController params[:jwt] || request.headers['Authorization']&.split(' ', 2)&.last end end - - def signed_install_active? - Feature.enabled?(:jira_connect_asymmetric_jwt, default_enabled: :yaml) - end end diff --git a/app/controllers/jira_connect/events_controller.rb b/app/controllers/jira_connect/events_controller.rb index 76ac15f7631..1ea0a92662b 100644 --- a/app/controllers/jira_connect/events_controller.rb +++ b/app/controllers/jira_connect/events_controller.rb @@ -4,14 +4,9 @@ class JiraConnect::EventsController < JiraConnect::ApplicationController # See https://developer.atlassian.com/cloud/jira/software/app-descriptor/#lifecycle skip_before_action :verify_atlassian_jwt! - before_action :verify_asymmetric_atlassian_jwt!, if: :signed_install_active? - - before_action :verify_atlassian_jwt!, only: :uninstalled, unless: :signed_install_active? - before_action :verify_qsh_claim!, only: :uninstalled, unless: :signed_install_active? + before_action :verify_asymmetric_atlassian_jwt! def installed - return head :ok if !signed_install_active? && atlassian_jwt_valid? - return head :ok if current_jira_installation installation = JiraConnectInstallation.new(event_params) diff --git a/config/feature_flags/development/jira_connect_asymmetric_jwt.yml b/config/feature_flags/development/rate_limiter_safe_increment.yml index 48684e80d0c..16e8f2fe7c7 100644 --- a/config/feature_flags/development/jira_connect_asymmetric_jwt.yml +++ b/config/feature_flags/development/rate_limiter_safe_increment.yml @@ -1,8 +1,8 @@ --- -name: jira_connect_asymmetric_jwt -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71080 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/342808 -milestone: '14.4' +name: rate_limiter_safe_increment +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73343 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/285352 +milestone: '14.5' type: development -group: group::integrations -default_enabled: true +group: group::project management +default_enabled: false diff --git a/config/metrics/counts_28d/20210216184822_i_package_generic_deploy_token_monthly.yml b/config/metrics/counts_28d/20210216184822_i_package_generic_deploy_token_monthly.yml index 84da476edb5..a09e973206d 100644 --- a/config/metrics/counts_28d/20210216184822_i_package_generic_deploy_token_monthly.yml +++ b/config/metrics/counts_28d/20210216184822_i_package_generic_deploy_token_monthly.yml @@ -8,8 +8,7 @@ product_stage: package product_group: group::package product_category: package registry value_type: number -status: broken -repair_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331455 +status: active time_frame: 28d data_source: redis_hll instrumentation_class: RedisHLLMetric diff --git a/config/metrics/counts_28d/20210216184910_i_package_generic_user_monthly.yml b/config/metrics/counts_28d/20210216184910_i_package_generic_user_monthly.yml index f028719bfe1..93f551178c3 100644 --- a/config/metrics/counts_28d/20210216184910_i_package_generic_user_monthly.yml +++ b/config/metrics/counts_28d/20210216184910_i_package_generic_user_monthly.yml @@ -8,8 +8,7 @@ product_stage: package product_group: group::package product_category: package registry value_type: number -status: broken -repair_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331455 +status: active time_frame: 28d data_source: redis_hll instrumentation_class: RedisHLLMetric diff --git a/config/metrics/counts_7d/20210216184908_i_package_generic_user_weekly.yml b/config/metrics/counts_7d/20210216184908_i_package_generic_user_weekly.yml index 63278bcfbd8..d529d1c2f38 100644 --- a/config/metrics/counts_7d/20210216184908_i_package_generic_user_weekly.yml +++ b/config/metrics/counts_7d/20210216184908_i_package_generic_user_weekly.yml @@ -8,8 +8,7 @@ product_stage: package product_group: group::package product_category: package registry value_type: number -status: broken -repair_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331455 +status: active time_frame: 7d data_source: redis_hll instrumentation_class: RedisHLLMetric diff --git a/doc/api/lint.md b/doc/api/lint.md index 9f95b9a94ae..e5b5e0e2be8 100644 --- a/doc/api/lint.md +++ b/doc/api/lint.md @@ -30,6 +30,7 @@ POST /ci/lint | ---------- | ------- | -------- | -------- | | `content` | string | yes | The CI/CD configuration content. | | `include_merged_yaml` | boolean | no | If the [expanded CI/CD configuration](#yaml-expansion) should be included in the response. | +| `include_jobs` | boolean | no | If the list of jobs should be included in the response. This is false by default. | ```shell curl --header "Content-Type: application/json" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/ci/lint" --data '{"content": "{ \"image\": \"ruby:2.6\", \"services\": [\"postgres\"], \"before_script\": [\"bundle install\", \"bundle exec rake db:create\"], \"variables\": {\"DB_NAME\": \"postgres\"}, \"types\": [\"test\", \"deploy\", \"notify\"], \"rspec\": { \"script\": \"rake spec\", \"tags\": [\"ruby\", \"postgres\"], \"only\": [\"branches\"]}}"}' @@ -91,7 +92,7 @@ work for CI configuration added with [`include: local`](../ci/yaml/index.md#incl or with [`extends:`](../ci/yaml/index.md#extends). Example contents of a `.gitlab-ci.yml` passed to the CI Lint API with -`include_merged_yaml` set as true: +`include_merged_yaml` and `include_jobs` set as true: ```yaml include: @@ -118,7 +119,39 @@ Example response: { "status": "valid", "errors": [], - "merged_yaml": "---\n:another_test:\n :stage: test\n :script: echo 2\n:test:\n :stage: test\n :script: echo 1\n" + "merged_yaml": "---\n:another_test:\n :stage: test\n :script: echo 2\n:test:\n :stage: test\n :script: echo 1\n", + "jobs": [ + { + "name":"test", + "stage":"test", + "before_script":[], + "script":["echo 1"], + "after_script":[], + "tag_list":[], + "environment":null, + "when":"on_success", + "allow_failure":false, + "only":{ + "refs":["branches","tags"] + }, + "except":null + }, + { + "name":"another_test", + "stage":"test", + "before_script":[], + "script":["echo 2"], + "after_script":[], + "tag_list":[], + "environment":null, + "when":"on_success", + "allow_failure":false, + "only":{ + "refs":["branches","tags"] + }, + "except":null + } + ] } ``` @@ -137,6 +170,7 @@ POST /projects/:id/ci/lint | ---------- | ------- | -------- | -------- | | `content` | string | yes | The CI/CD configuration content. | | `dry_run` | boolean | no | Run [pipeline creation simulation](../ci/lint.md#pipeline-simulation), or only do static check. This is false by default. | +| `include_jobs` | boolean | no | If the list of jobs that would exist in a static check or pipeline simulation should be included in the response. This is false by default. | Example request: @@ -185,6 +219,7 @@ GET /projects/:id/ci/lint | Attribute | Type | Required | Description | | ---------- | ------- | -------- | -------- | | `dry_run` | boolean | no | Run pipeline creation simulation, or only do static check. | +| `include_jobs` | boolean | no | If the list of jobs that would exist in a static check or pipeline simulation should be included in the response. This is false by default. | Example request: diff --git a/doc/development/service_ping/index.md b/doc/development/service_ping/index.md index cd702720319..152eec87d5d 100644 --- a/doc/development/service_ping/index.md +++ b/doc/development/service_ping/index.md @@ -50,6 +50,8 @@ We use the following terminology to describe the Service Ping components: - **Metrics**: primarily made up of row counts for different tables in an instance's database. Each metric has a corresponding [metric definition](metrics_dictionary.md#metrics-definition-and-validation) in a YAML file. +- **MAU**: monthly active users. +- **WAU**: weekly active users. ### Why should we enable Service Ping? diff --git a/doc/user/admin_area/settings/index.md b/doc/user/admin_area/settings/index.md index 5b78eecad5d..7945e5d790f 100644 --- a/doc/user/admin_area/settings/index.md +++ b/doc/user/admin_area/settings/index.md @@ -7,124 +7,186 @@ type: index # Admin Area settings **(FREE SELF)** -As an administrator of a GitLab self-managed instance, you can manage the behavior of your deployment. To do so, select **Admin Area > Settings**. +As an administrator of a GitLab self-managed instance, you can manage the behavior of your +deployment. -The Admin Area is not accessible on GitLab.com, and settings can only be changed by the -GitLab.com administrators. See the [GitLab.com settings](../../gitlab_com/index.md) -documentation for all current settings and limits on the GitLab.com instance. +The **Admin Area** is not accessible on GitLab.com, and settings can only be changed by the +GitLab.com administrators. For the settings and limits on the GitLab.com instance, +read [GitLab.com settings](../../gitlab_com/index.md). -## General +## Access the Admin Area -To access the default page for Admin Area settings: +To access the **Admin Area**: +1. Sign in to your GitLab instance as an administrator. 1. On the top bar, select **Menu > Admin**. -1. On the left sidebar, select **Settings > General**. - -| Option | Description | -| ------ | ----------- | -| [Visibility and access controls](visibility_and_access_controls.md) | Set default and restrict visibility levels. Configure import sources and Git access protocol. | -| [Account and limit](account_and_limit_settings.md) | Set projects and maximum size limits, session duration, user options, and check feature availability for namespace plan. | -| [Diff limits](../diff_limits.md) | Diff content limits. | -| [Sign-up restrictions](sign_up_restrictions.md) | Configure the way a user creates a new account. | -| [Sign in restrictions](sign_in_restrictions.md) | Set requirements for a user to sign in. Enable mandatory two-factor authentication. | -| [Terms of Service and Privacy Policy](terms.md) | Include a Terms of Service agreement and Privacy Policy that all users must accept. | -| [External Authentication](external_authorization.md#configuration) | External Classification Policy Authorization | -| [Web terminal](../../../administration/integration/terminal.md#limiting-websocket-connection-time) | Set max session time for web terminal. | -| [Web IDE](../../project/web_ide/index.md#enable-live-preview) | Manage Web IDE features. | -| [FLoC](floc.md) | Enable or disable [Federated Learning of Cohorts (FLoC)](https://en.wikipedia.org/wiki/Federated_Learning_of_Cohorts) tracking. | - -## Integrations - -| Option | Description | -| ------ | ----------- | -| [Elasticsearch](../../../integration/elasticsearch.md#enable-advanced-search) | Elasticsearch integration. Elasticsearch AWS IAM. | -| [Kroki](../../../administration/integration/kroki.md#enable-kroki-in-gitlab) | Allow rendering of diagrams in AsciiDoc and Markdown documents using [kroki.io](https://kroki.io). | -| [Mailgun](../../../administration/integration/mailgun.md) | Enable your GitLab instance to receive invite email bounce events from Mailgun, if it is your email provider. | -| [PlantUML](../../../administration/integration/plantuml.md) | Allow rendering of PlantUML diagrams in documents. | -| [Slack application](../../../user/project/integrations/gitlab_slack_application.md#configuration) | Slack integration allows you to interact with GitLab via slash commands in a chat window. This option is only available on GitLab.com, though it may be [available for self-managed instances in the future](https://gitlab.com/gitlab-org/gitlab/-/issues/28164). | -| [Third party offers](third_party_offers.md) | Control the display of third party offers. | -| [Snowplow](../../../development/snowplow/index.md) | Configure the Snowplow integration. | -| [Google GKE](../../project/clusters/add_gke_clusters.md) | Google GKE integration allows you to provision GKE clusters from GitLab. | -| [Amazon EKS](../../project/clusters/add_eks_clusters.md) | Amazon EKS integration allows you to provision EKS clusters from GitLab. | - -## Repository - -| Option | Description | -| ------ | ----------- | -| [Repository's custom initial branch name](../../project/repository/branches/default.md#instance-level-custom-initial-branch-name) | Set a custom branch name for new repositories created in your instance. | -| [Repository mirror](visibility_and_access_controls.md#enable-project-mirroring) | Configure repository mirroring. | -| [Repository storage](../../../administration/repository_storage_types.md) | Configure storage path settings. | -| Repository maintenance | ([Repository checks](../../../administration/repository_checks.md) and [Housekeeping](../../../administration/housekeeping.md)). Configure automatic Git checks and housekeeping on repositories. | -| [Repository static objects](../../../administration/static_objects_external_storage.md) | Serve repository static objects (for example, archives and blobs) from an external storage (for example, a CDN). | - -## Templates **(PREMIUM SELF)** - -| Option | Description | -| ------ | ----------- | -| [Templates](instance_template_repository.md#configuration) | Set instance-wide template repository. | -| [Custom project templates](../custom_project_templates.md) | Select the custom project template source group. | - -## CI/CD - -| Option | Description | -| ------ | ----------- | -| [Continuous Integration and Deployment](continuous_integration.md) | Auto DevOps, runners and job artifacts. | -| [Required pipeline configuration](continuous_integration.md#required-pipeline-configuration) | Set an instance-wide auto included [pipeline configuration](../../../ci/yaml/index.md). This pipeline configuration is run after the project's own configuration. | -| [Package Registry](continuous_integration.md#package-registry-configuration) | Settings related to the use and experience of using the GitLab Package Registry. Note there are [risks involved](../../packages/container_registry/index.md#use-with-external-container-registries) in enabling some of these settings. | - -## Reporting - -| Option | Description | -| ------ | ----------- | -| [Spam and Anti-bot Protection](../../../integration/recaptcha.md) | Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support [v2](https://developers.google.com/recaptcha/docs/versions). | -| [Abuse reports](../review_abuse_reports.md) | Set notification email for abuse reports. | - -## Metrics and profiling - -| Option | Description | -| ------ | ----------- | -| [Metrics - Prometheus](../../../administration/monitoring/prometheus/gitlab_metrics.md) | Enable and configure Prometheus metrics. | -| [Metrics - Grafana](../../../administration/monitoring/performance/grafana_configuration.md#integration-with-gitlab-ui) | Enable and configure Grafana. | -| [Profiling - Performance bar](../../../administration/monitoring/performance/performance_bar.md#enable-the-performance-bar-for-non-administrators) | Enable access to the Performance Bar for non-administrator users in a given group. | -| [Self monitoring](../../../administration/monitoring/gitlab_self_monitoring_project/index.md#create-the-self-monitoring-project) | Enable or disable instance self monitoring. | -| [Usage statistics](usage_statistics.md) | Enable or disable version check and Service Ping. | -| [Pseudonymizer data collection](../../../administration/pseudonymizer.md) | Enable or disable the Pseudonymizer data collection. | - -## Network - -| Option | Description | -| ------ | ----------- | -| Performance optimization | [Write to "authorized_keys" file](../../../administration/operations/fast_ssh_key_lookup.md#setting-up-fast-lookup-via-gitlab-shell) and [Push event activities limit and bulk push events](push_event_activities_limit.md). Various settings that affect GitLab performance. | -| [User and IP rate limits](user_and_ip_rate_limits.md) | Configure limits for web and API requests. | -| [Package Registry Rate Limits](package_registry_rate_limits.md) | Configure specific limits for Packages API requests that supersede the user and IP rate limits. | -| [Git LFS Rate Limits](git_lfs_rate_limits.md) | Configure specific limits for Git LFS requests that supersede the user and IP rate limits. | -| [Files API Rate Limits](files_api_rate_limits.md) | Configure specific limits for Files API requests that supersede the user and IP rate limits. | -| [Deprecated API Rate Limits](deprecated_api_rate_limits.md) | Configure specific limits for deprecated API requests that supersede the user and IP rate limits. | -| [Outbound requests](../../../security/webhooks.md) | Allow requests to the local network from hooks and services. | -| [Protected Paths](protected_paths.md) | Configure paths to be protected by Rack Attack. | -| [Incident Management](../../../operations/incident_management/index.md) Limits | Limit the number of inbound alerts that can be sent to a project. | -| [Notes creation limit](rate_limit_on_notes_creation.md)| Set a rate limit on the note creation requests. | - -## Geo **(PREMIUM SELF)** - -| Option | Description | -| ------ | ----------- | -| [Geo](../../../administration/geo/index.md) | Geo allows you to replicate your GitLab instance to other geographical locations. Redirects to **Admin Area > Geo > Settings** are no longer available at **Admin Area > Settings > Geo** in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/36896). | - -## Preferences - -| Option | Description | -| ------ | ----------- | -| [Email](email.md) | Various email settings. | -| [What's new](../../../administration/whats-new.md) | Configure What's new drawer and content. | -| [Help page](help_page.md) | Help page text and support page URL. | -| [Pages](../../../administration/pages/index.md#custom-domain-verification) | Size and domain settings for static websites | -| [Polling interval multiplier](../../../administration/polling.md) | Configure how frequently the GitLab UI polls for updates. | -| [Gitaly timeouts](gitaly_timeouts.md) | Configure Gitaly timeouts. | -| Localization | [Default first day of the week](../../profile/preferences.md) and [Time tracking](../../project/time_tracking.md#limit-displayed-units-to-hours). | -| [Sidekiq Job Limits](sidekiq_job_limits.md) | Limit the size of Sidekiq jobs stored in Redis. | - -### Default first day of the week +1. On the left sidebar, select **Settings**, and the group of settings to view: + - [General](#general) + - [Geo](#geo) + - [CI/CD](#cicd) + - [Integrations](#integrations) + - [Metrics and profiling](#metrics-and-profiling) + - [Network](#network) + - [Preferences](#preferences) + - [Reporting](#reporting) + - [Repository](#repository) + - [Templates](#templates) + +### General + +The **General** settings contain: + +- [Visibility and access controls](visibility_and_access_controls.md) - Set default and + restrict visibility levels. Configure import sources and Git access protocol. +- [Account and limit](account_and_limit_settings.md) - Set projects and maximum size limits, + session duration, user options, and check feature availability for namespace plan. +- [Diff limits](../diff_limits.md) - Diff content limits. +- [Sign-up restrictions](sign_up_restrictions.md) - Configure the way a user creates a new account. +- [Sign in restrictions](sign_in_restrictions.md) - Set requirements for a user to sign in. + Enable mandatory two-factor authentication. +- [Terms of Service and Privacy Policy](terms.md) - Include a Terms of Service agreement + and Privacy Policy that all users must accept. +- [External Authentication](external_authorization.md#configuration) - External Classification Policy Authorization. +- [Web terminal](../../../administration/integration/terminal.md#limiting-websocket-connection-time) - + Set max session time for web terminal. +- [Web IDE](../../project/web_ide/index.md#enable-live-preview) - Manage Web IDE features. +- [FLoC](floc.md) - Enable or disable + [Federated Learning of Cohorts (FLoC)](https://en.wikipedia.org/wiki/Federated_Learning_of_Cohorts) tracking. + +### CI/CD + +The **CI/CD** settings contain: + +- [Continuous Integration and Deployment](continuous_integration.md) - + Auto DevOps, runners and job artifacts. +- [Required pipeline configuration](continuous_integration.md#required-pipeline-configuration) - + Set an instance-wide auto included [pipeline configuration](../../../ci/yaml/index.md). + This pipeline configuration is run after the project's own configuration. +- [Package Registry](continuous_integration.md#package-registry-configuration) - + Settings related to the use and experience of using the GitLab Package Registry. Some + [risks are involved](../../packages/container_registry/index.md#use-with-external-container-registries) + in enabling some of these settings. + +### Geo **(PREMIUM SELF)** + +The **Geo** setting contains: + +- [Geo](../../../administration/geo/index.md) - Replicate your GitLab instance to other + geographical locations. Redirects to **Admin Area > Geo > Settings** are no + longer available at **Admin Area > Settings > Geo** in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/36896). + +### Integrations + +The **Integrations** settings contain: + +- [Elasticsearch](../../../integration/elasticsearch.md#enable-advanced-search) - + Elasticsearch integration. Elasticsearch AWS IAM. +- [Kroki](../../../administration/integration/kroki.md#enable-kroki-in-gitlab) - + Allow rendering of diagrams in AsciiDoc and Markdown documents using [kroki.io](https://kroki.io). +- [Mailgun](../../../administration/integration/mailgun.md) - Enable your GitLab instance + to receive invite email bounce events from Mailgun, if it is your email provider. +- [PlantUML](../../../administration/integration/plantuml.md) - Allow rendering of PlantUML + diagrams in documents. +- [Slack application](../../../user/project/integrations/gitlab_slack_application.md#configuration) - + Slack integration allows you to interact with GitLab via slash commands in a chat window. + This option is only available on GitLab.com, though it may be + [available for self-managed instances in the future](https://gitlab.com/gitlab-org/gitlab/-/issues/28164). +- [Third party offers](third_party_offers.md) - Control the display of third-party offers. +- [Snowplow](../../../development/snowplow/index.md) - Configure the Snowplow integration. +- [Google GKE](../../project/clusters/add_gke_clusters.md) - Google GKE integration enables + you to provision GKE clusters from GitLab. +- [Amazon EKS](../../project/clusters/add_eks_clusters.md) - Amazon EKS integration enables + you to provision EKS clusters from GitLab. + +### Metrics and profiling + +The **Metrics and profiling** settings contain: + +- [Metrics - Prometheus](../../../administration/monitoring/prometheus/gitlab_metrics.md) - + Enable and configure Prometheus metrics. +- [Metrics - Grafana](../../../administration/monitoring/performance/grafana_configuration.md#integration-with-gitlab-ui) - + Enable and configure Grafana. +- [Profiling - Performance bar](../../../administration/monitoring/performance/performance_bar.md#enable-the-performance-bar-for-non-administrators) - + Enable access to the Performance Bar for non-administrator users in a given group. +- [Self monitoring](../../../administration/monitoring/gitlab_self_monitoring_project/index.md#create-the-self-monitoring-project) - + Enable or disable instance self monitoring. +- [Usage statistics](usage_statistics.md) - Enable or disable version check and Service Ping. +- [Pseudonymizer data collection](../../../administration/pseudonymizer.md) - + Enable or disable the Pseudonymizer data collection. + +### Network + +The **Network** settings contain: + +- Performance optimization - Various settings that affect GitLab performance, including: + - [Write to `authorized_keys` file](../../../administration/operations/fast_ssh_key_lookup.md#setting-up-fast-lookup-via-gitlab-shell). + - [Push event activities limit and bulk push events](push_event_activities_limit.md). +- [User and IP rate limits](user_and_ip_rate_limits.md) - Configure limits for web and API requests. + These rate limits can be overridden: + - [Package Registry Rate Limits](package_registry_rate_limits.md) - Configure specific + limits for Packages API requests that supersede the user and IP rate limits. + - [Git LFS Rate Limits](git_lfs_rate_limits.md) - Configure specific limits for + Git LFS requests that supersede the user and IP rate limits. + - [Files API Rate Limits](files_api_rate_limits.md) - Configure specific limits for + Files API requests that supersede the user and IP rate limits. + - [Deprecated API Rate Limits](deprecated_api_rate_limits.md) - Configure specific limits + for deprecated API requests that supersede the user and IP rate limits. +- [Outbound requests](../../../security/webhooks.md) - Allow requests to the local network from hooks and services. +- [Protected Paths](protected_paths.md) - Configure paths to be protected by Rack Attack. +- [Incident Management Limits](../../../operations/incident_management/index.md) - Limit the + number of inbound alerts that can be sent to a project. +- [Notes creation limit](rate_limit_on_notes_creation.md) - Set a rate limit on the note creation requests. + +### Preferences + +The **Preferences** settings contain: + +- [Email](email.md) - Various email settings. +- [What's new](../../../administration/whats-new.md) - Configure **What's new** drawer and content. +- [Help page](help_page.md) - Help page text and support page URL. +- [Pages](../../../administration/pages/index.md#custom-domain-verification) - + Size and domain settings for static websites. +- [Polling interval multiplier](../../../administration/polling.md) - + Configure how frequently the GitLab UI polls for updates. +- [Gitaly timeouts](gitaly_timeouts.md) - Configure Gitaly timeouts. +- Localization: + - [Default first day of the week](../../profile/preferences.md). + - [Time tracking](../../project/time_tracking.md#limit-displayed-units-to-hours). +- [Sidekiq Job Limits](sidekiq_job_limits.md) - Limit the size of Sidekiq jobs stored in Redis. + +### Reporting + +The **Reporting** settings contain: + +- [Spam and Anti-bot Protection](../../../integration/recaptcha.md) - + Enable anti-spam services, like reCAPTCHA or Akismet, and set IP limits. +- [Abuse reports](../review_abuse_reports.md) - Set notification email for abuse reports. + +### Repository + +The **Repository** settings contain: + +- [Repository's custom initial branch name](../../project/repository/branches/default.md#instance-level-custom-initial-branch-name) - + Set a custom branch name for new repositories created in your instance. +- [Repository mirror](visibility_and_access_controls.md#enable-project-mirroring) - + Configure repository mirroring. +- [Repository storage](../../../administration/repository_storage_types.md) - Configure storage path settings. +- Repository maintenance: + - [Repository checks](../../../administration/repository_checks.md) - Configure + automatic Git checks on repositories. + - [Housekeeping](../../../administration/housekeeping.md)). Configure automatic + Git housekeeping on repositories. +- [Repository static objects](../../../administration/static_objects_external_storage.md) - + Serve repository static objects (for example, archives and blobs) from an external storage (for example, a CDN). + +### Templates **(PREMIUM SELF)** + +The **Templates** settings contain: + +- [Templates](instance_template_repository.md#configuration) - Set instance-wide template repository. +- [Custom project templates](../custom_project_templates.md) - Select the custom project template source group. + +## Default first day of the week You can change the [Default first day of the week](../../profile/preferences.md) for the entire GitLab instance: diff --git a/doc/user/project/integrations/microsoft_teams.md b/doc/user/project/integrations/microsoft_teams.md index 07a4307da43..6679bab745b 100644 --- a/doc/user/project/integrations/microsoft_teams.md +++ b/doc/user/project/integrations/microsoft_teams.md @@ -18,8 +18,8 @@ in Microsoft Teams. To integrate the services, you must: To configure Microsoft Teams to listen for notifications from GitLab: -1. In Microsoft Teams, search for "incoming webhook" in the search bar, and select the - **Incoming Webhook** item: +1. In Microsoft Teams, type `incoming webhook` in the search bar, and select + **Incoming Webhook**: ![Select Incoming Webhook](img/microsoft_teams_select_incoming_webhook.png) @@ -34,11 +34,12 @@ To configure Microsoft Teams to listen for notifications from GitLab: After you configure Microsoft Teams to receive notifications, you must configure GitLab to send the notifications: -1. Sign in to GitLab as a user with [Administrator](../../permissions.md) and go - to your project's page. -1. Go to **Settings > Integrations** and select **Microsoft Teams Notification**. -1. Select **Active** to enable the integration. -1. Select the checkbox next to each **Trigger** to enable: +1. Sign in to GitLab as an administrator. +1. On the top bar, select **Menu > Projects** and find your project. +1. On the left sidebar, select **Settings > Integrations**. +1. Select **Microsoft Teams notifications**. +1. To enable the integration, select **Active**. +1. In the **Trigger** section, select the checkbox next to each event to enable it: - Push - Issue - Confidential issue @@ -46,11 +47,11 @@ GitLab to send the notifications: - Note - Confidential note - Tag push - - Pipeline - If you enable this trigger, you can also select **Notify only broken pipelines** to be notified only about failed pipelines. + - Pipeline - Wiki page 1. In **Webhook**, paste the URL you copied when you [configured Microsoft Teams](#configure-microsoft-teams). -1. (Optional) If you enabled the pipeline trigger, you can select the +1. Optional. If you enable the pipeline trigger, select the **Notify only broken pipelines** checkbox to push notifications only when pipelines break. 1. Select the branches you want to send notifications for. 1. Select **Save changes**. diff --git a/doc/user/project/repository/vscode.md b/doc/user/project/repository/vscode.md index c021d999588..bbf14a71653 100644 --- a/doc/user/project/repository/vscode.md +++ b/doc/user/project/repository/vscode.md @@ -4,9 +4,9 @@ group: Code Review 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 --- -# GitLab Workflow VS Code extension **(FREE)** +# GitLab Workflow extension for VS Code **(FREE)** -The [GitLab VS Code Extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow) +The [GitLab Workflow extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow) integrates GitLab with Visual Studio Code. You can decrease context switching and do more day-to-day tasks in Visual Studio Code, such as: diff --git a/lib/api/entities/ci/lint/result.rb b/lib/api/entities/ci/lint/result.rb index 0e4aa238ba2..39039868bba 100644 --- a/lib/api/entities/ci/lint/result.rb +++ b/lib/api/entities/ci/lint/result.rb @@ -9,6 +9,7 @@ module API expose :errors expose :warnings expose :merged_yaml + expose :jobs, if: -> (result, options) { options[:include_jobs] } end end end diff --git a/lib/api/lint.rb b/lib/api/lint.rb index fa871b4bc57..f1e19e9c3c5 100644 --- a/lib/api/lint.rb +++ b/lib/api/lint.rb @@ -9,6 +9,7 @@ module API params do requires :content, type: String, desc: 'Content of .gitlab-ci.yml' optional :include_merged_yaml, type: Boolean, desc: 'Whether or not to include merged CI config yaml in the response' + optional :include_jobs, type: Boolean, desc: 'Whether or not to include CI jobs in the response' end post '/lint' do unauthorized! if (Gitlab::CurrentSettings.signup_disabled? || Gitlab::CurrentSettings.signup_limited?) && current_user.nil? @@ -17,7 +18,7 @@ module API .validate(params[:content], dry_run: false) status 200 - Entities::Ci::Lint::Result.represent(result, current_user: current_user).serializable_hash.tap do |presented_result| + Entities::Ci::Lint::Result.represent(result, current_user: current_user, include_jobs: params[:include_jobs]).serializable_hash.tap do |presented_result| presented_result[:status] = presented_result[:valid] ? 'valid' : 'invalid' presented_result.delete(:merged_yaml) unless params[:include_merged_yaml] end @@ -30,6 +31,7 @@ module API end params do optional :dry_run, type: Boolean, default: false, desc: 'Run pipeline creation simulation, or only do static check.' + optional :include_jobs, type: Boolean, desc: 'Whether or not to include CI jobs in the response' end get ':id/ci/lint' do authorize! :download_code, user_project @@ -39,7 +41,7 @@ module API .new(project: user_project, current_user: current_user) .validate(content, dry_run: params[:dry_run]) - present result, with: Entities::Ci::Lint::Result, current_user: current_user + present result, with: Entities::Ci::Lint::Result, current_user: current_user, include_jobs: params[:include_jobs] end end @@ -50,6 +52,7 @@ module API params do requires :content, type: String, desc: 'Content of .gitlab-ci.yml' optional :dry_run, type: Boolean, default: false, desc: 'Run pipeline creation simulation, or only do static check.' + optional :include_jobs, type: Boolean, desc: 'Whether or not to include CI jobs in the response' end post ':id/ci/lint' do authorize! :create_pipeline, user_project @@ -59,7 +62,7 @@ module API .validate(params[:content], dry_run: params[:dry_run]) status 200 - present result, with: Entities::Ci::Lint::Result, current_user: current_user + present result, with: Entities::Ci::Lint::Result, current_user: current_user, include_jobs: params[:include_jobs] end end end diff --git a/lib/gitlab/application_rate_limiter.rb b/lib/gitlab/application_rate_limiter.rb index c17c452056a..ef8fd9504f7 100644 --- a/lib/gitlab/application_rate_limiter.rb +++ b/lib/gitlab/application_rate_limiter.rb @@ -66,7 +66,6 @@ module Gitlab # @param key [Symbol] Key attribute registered in `.rate_limits` # @option scope [Array<ActiveRecord>] Array of ActiveRecord models to scope throttling to a specific request (e.g. per user per project) # @option threshold [Integer] Optional threshold value to override default one registered in `.rate_limits` - # @option interval [Integer] Optional interval value to override default one registered in `.rate_limits` # @option users_allowlist [Array<String>] Optional list of usernames to exclude from the limit. This param will only be functional if Scope includes a current user. # # @return [Boolean] Whether or not a request should be throttled @@ -77,7 +76,7 @@ module Gitlab threshold_value = options[:threshold] || threshold(key) threshold_value > 0 && - increment(key, options[:scope], options[:interval]) > threshold_value + increment(key, options[:scope]) > threshold_value end # Increments the given cache key and increments the value by 1 with the @@ -85,12 +84,13 @@ module Gitlab # # @param key [Symbol] Key attribute registered in `.rate_limits` # @option scope [Array<ActiveRecord>] Array of ActiveRecord models to scope throttling to a specific request (e.g. per user per project) - # @option interval [Integer] Optional interval value to override default one registered in `.rate_limits` # # @return [Integer] incremented value - def increment(key, scope, interval = nil) + def increment(key, scope) + return safe_increment(key, scope) if Feature.enabled?(:rate_limiter_safe_increment, default_enabled: :yaml) + value = 0 - interval_value = interval || interval(key) + interval_value = interval(key) ::Gitlab::Redis::RateLimiting.with do |redis| cache_key = action_key(key, scope) @@ -101,6 +101,32 @@ module Gitlab value end + # Increments a cache key that is based on the current time and interval. + # So that when time passes to the next interval, the key changes and the count starts again from 0. + # + # Based on https://github.com/rack/rack-attack/blob/886ba3a18d13c6484cd511a4dc9b76c0d14e5e96/lib/rack/attack/cache.rb#L63-L68 + # + # @param key [Symbol] Key attribute registered in `.rate_limits` + # @option scope [Array<ActiveRecord>] Array of ActiveRecord models to scope throttling to a specific request (e.g. per user per project) + # + # @return [Integer] incremented value + def safe_increment(key, scope) + interval_value = interval(key) + + period_key, time_elapsed_in_period = Time.now.to_i.divmod(interval_value) + + cache_key = "#{action_key(key, scope)}:#{period_key}" + # We add a 1 second buffer to avoid timing issues when we're at the end of a period + expiry = interval_value - time_elapsed_in_period + 1 + + ::Gitlab::Redis::RateLimiting.with do |redis| + redis.pipelined do + redis.incr(cache_key) + redis.expire(cache_key, expiry) + end.first + end + end + # Logs request using provided logger # # @param request [Http::Request] - Web request to be logged diff --git a/locale/gitlab.pot b/locale/gitlab.pot index bcb066ea996..766114b5255 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -8216,9 +8216,6 @@ msgstr "" msgid "Code" msgstr "" -msgid "Code Coverage: %{coveragePercentage}" -msgstr "" - msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}" msgstr "" @@ -14075,6 +14072,12 @@ msgstr "" msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used." msgstr "" +msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}." +msgstr "" + +msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}" +msgstr "" + msgid "ExternalWikiService|External wiki" msgstr "" @@ -19655,9 +19658,6 @@ msgstr "" msgid "JiraService|No available statuses" msgstr "" -msgid "JiraService|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}Jira%{linkEnd}." -msgstr "" - msgid "JiraService|Open Jira" msgstr "" @@ -19688,9 +19688,6 @@ msgstr "" msgid "JiraService|This is an Ultimate feature" msgstr "" -msgid "JiraService|This issue is synchronized with Jira" -msgstr "" - msgid "JiraService|Transition Jira issues to their final state:" msgstr "" @@ -25534,6 +25531,9 @@ msgstr "" msgid "Pipeline|Created" msgstr "" +msgid "Pipeline|Creating pipeline." +msgstr "" + msgid "Pipeline|Date" msgstr "" @@ -29002,6 +29002,9 @@ msgstr "" msgid "RepositoriesAnalytics|Average test coverage last 30 days" msgstr "" +msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}" +msgstr "" + msgid "RepositoriesAnalytics|Coverage" msgstr "" @@ -29023,6 +29026,9 @@ msgstr "" msgid "RepositoriesAnalytics|Jobs with Coverage" msgstr "" +msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}" +msgstr "" + msgid "RepositoriesAnalytics|Last Update" msgstr "" @@ -29041,6 +29047,9 @@ msgstr "" msgid "RepositoriesAnalytics|Projects with Coverage" msgstr "" +msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}" +msgstr "" + msgid "RepositoriesAnalytics|Test Code Coverage" msgstr "" @@ -39914,15 +39923,9 @@ msgstr "" msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page." msgstr "" -msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}." -msgstr "" - msgid "ZenTaoIntegration|This is a ZenTao user." msgstr "" -msgid "ZenTaoIntegration|This issue is synchronized with ZenTao" -msgstr "" - msgid "ZenTaoIntegration|ZenTao user" msgstr "" @@ -40304,6 +40307,9 @@ msgstr "" msgid "ciReport|Failed to load %{reportName} report" msgstr "" +msgid "ciReport|Failed to load Code Quality report" +msgstr "" + msgid "ciReport|Fixed" msgstr "" @@ -40336,6 +40342,9 @@ msgstr "" msgid "ciReport|Loading %{reportName} report" msgstr "" +msgid "ciReport|Loading Code Quality report" +msgstr "" + msgid "ciReport|Manage licenses" msgstr "" @@ -40372,6 +40381,9 @@ msgstr "" msgid "ciReport|Security scanning failed loading any results" msgstr "" +msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items" +msgstr "" + msgid "ciReport|Solution" msgstr "" diff --git a/spec/controllers/jira_connect/app_descriptor_controller_spec.rb b/spec/controllers/jira_connect/app_descriptor_controller_spec.rb index 9d890efdd33..4f8b2b90637 100644 --- a/spec/controllers/jira_connect/app_descriptor_controller_spec.rb +++ b/spec/controllers/jira_connect/app_descriptor_controller_spec.rb @@ -90,17 +90,5 @@ RSpec.describe JiraConnect::AppDescriptorController do ) ) end - - context 'when jira_connect_asymmetric_jwt is disabled' do - before do - stub_feature_flags(jira_connect_asymmetric_jwt: false) - end - - specify do - get :show - - expect(json_response).to include('apiMigrations' => include('signed-install' => false)) - end - end end end diff --git a/spec/controllers/jira_connect/events_controller_spec.rb b/spec/controllers/jira_connect/events_controller_spec.rb index 78bd0dc8318..2a70a2ea683 100644 --- a/spec/controllers/jira_connect/events_controller_spec.rb +++ b/spec/controllers/jira_connect/events_controller_spec.rb @@ -77,18 +77,6 @@ RSpec.describe JiraConnect::EventsController do expect(installation.base_url).to eq('https://test.atlassian.net') end - context 'when jira_connect_asymmetric_jwt is disabled' do - before do - stub_feature_flags(jira_connect_asymmetric_jwt: false) - end - - it 'saves the jira installation data without JWT validation' do - expect(Atlassian::JiraConnect::AsymmetricJwt).not_to receive(:new) - - expect { subject }.to change { JiraConnectInstallation.count }.by(1) - end - end - context 'when it is a version update and shared_secret is not sent' do let(:params) do { @@ -110,22 +98,6 @@ RSpec.describe JiraConnect::EventsController do expect { subject }.not_to change { JiraConnectInstallation.count } expect(response).to have_gitlab_http_status(:ok) end - - context 'when jira_connect_asymmetric_jwt is disabled' do - before do - stub_feature_flags(jira_connect_asymmetric_jwt: false) - end - - it 'decodes the JWT token in authorization header and returns 200 without creating a new installation' do - request.headers["Authorization"] = "Bearer #{Atlassian::Jwt.encode({ iss: client_key }, shared_secret)}" - - expect(Atlassian::JiraConnect::AsymmetricJwt).not_to receive(:new) - - expect { subject }.not_to change { JiraConnectInstallation.count } - - expect(response).to have_gitlab_http_status(:ok) - end - end end end end @@ -153,23 +125,6 @@ RSpec.describe JiraConnect::EventsController do it 'does not delete the installation' do expect { post_uninstalled }.not_to change { JiraConnectInstallation.count } end - - context 'when jira_connect_asymmetric_jwt is disabled' do - before do - stub_feature_flags(jira_connect_asymmetric_jwt: false) - request.headers['Authorization'] = 'JWT invalid token' - end - - it 'returns 403' do - post_uninstalled - - expect(response).to have_gitlab_http_status(:forbidden) - end - - it 'does not delete the installation' do - expect { post_uninstalled }.not_to change { JiraConnectInstallation.count } - end - end end context 'when JWT is valid' do @@ -197,36 +152,6 @@ RSpec.describe JiraConnect::EventsController do expect(response).to have_gitlab_http_status(:unprocessable_entity) end - - context 'when jira_connect_asymmetric_jwt is disabled' do - before do - stub_feature_flags(jira_connect_asymmetric_jwt: false) - - request.headers['Authorization'] = "JWT #{Atlassian::Jwt.encode({ iss: installation.client_key, qsh: qsh }, installation.shared_secret)}" - end - - let(:qsh) { Atlassian::Jwt.create_query_string_hash('https://gitlab.test/events/uninstalled', 'POST', 'https://gitlab.test') } - - it 'calls the DestroyService and returns ok in case of success' do - expect_next_instance_of(JiraConnectInstallations::DestroyService, installation, jira_base_path, jira_event_path) do |destroy_service| - expect(destroy_service).to receive(:execute).and_return(true) - end - - post_uninstalled - - expect(response).to have_gitlab_http_status(:ok) - end - - it 'calls the DestroyService and returns unprocessable_entity in case of failure' do - expect_next_instance_of(JiraConnectInstallations::DestroyService, installation, jira_base_path, jira_event_path) do |destroy_service| - expect(destroy_service).to receive(:execute).and_return(false) - end - - post_uninstalled - - expect(response).to have_gitlab_http_status(:unprocessable_entity) - end - end end end end diff --git a/spec/frontend/boards/components/board_filtered_search_spec.js b/spec/frontend/boards/components/board_filtered_search_spec.js index dc93890f27a..b858d6e95a0 100644 --- a/spec/frontend/boards/components/board_filtered_search_spec.js +++ b/spec/frontend/boards/components/board_filtered_search_spec.js @@ -7,6 +7,7 @@ import { __ } from '~/locale'; import FilteredSearchBarRoot from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue'; import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue'; import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue'; +import { createStore } from '~/boards/stores'; Vue.use(Vuex); @@ -42,17 +43,13 @@ describe('BoardFilteredSearch', () => { }, ]; - const createComponent = ({ initialFilterParams = {} } = {}) => { - store = new Vuex.Store({ - actions: { - performSearch: jest.fn(), - }, - }); - + const createComponent = ({ initialFilterParams = {}, props = {} } = {}) => { + store = createStore(); wrapper = shallowMount(BoardFilteredSearch, { provide: { initialFilterParams, fullPath: '' }, store, propsData: { + ...props, tokens, }, }); @@ -68,11 +65,7 @@ describe('BoardFilteredSearch', () => { beforeEach(() => { createComponent(); - jest.spyOn(store, 'dispatch'); - }); - - it('renders FilteredSearch', () => { - expect(findFilteredSearch().exists()).toBe(true); + jest.spyOn(store, 'dispatch').mockImplementation(); }); it('passes the correct tokens to FilteredSearch', () => { @@ -99,6 +92,22 @@ describe('BoardFilteredSearch', () => { }); }); + describe('when eeFilters is not empty', () => { + it('passes the correct initialFilterValue to FitleredSearchBarRoot', () => { + createComponent({ props: { eeFilters: { labelName: ['label'] } } }); + + expect(findFilteredSearch().props('initialFilterValue')).toEqual([ + { type: 'label_name', value: { data: 'label', operator: '=' } }, + ]); + }); + }); + + it('renders FilteredSearch', () => { + createComponent(); + + expect(findFilteredSearch().exists()).toBe(true); + }); + describe('when searching', () => { beforeEach(() => { createComponent(); diff --git a/spec/frontend/commit/pipelines/pipelines_table_spec.js b/spec/frontend/commit/pipelines/pipelines_table_spec.js index 17f7be9d1d7..51f5538b2a0 100644 --- a/spec/frontend/commit/pipelines/pipelines_table_spec.js +++ b/spec/frontend/commit/pipelines/pipelines_table_spec.js @@ -6,8 +6,13 @@ import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; import Api from '~/api'; import PipelinesTable from '~/commit/pipelines/pipelines_table.vue'; +import { TOAST_MESSAGE } from '~/pipelines/constants'; import axios from '~/lib/utils/axios_utils'; +const $toast = { + show: jest.fn(), +}; + describe('Pipelines table in Commits and Merge requests', () => { let wrapper; let pipeline; @@ -30,6 +35,9 @@ describe('Pipelines table in Commits and Merge requests', () => { errorStateSvgPath: 'foo', ...props, }, + mocks: { + $toast, + }, }), ); }; @@ -178,6 +186,12 @@ describe('Pipelines table in Commits and Merge requests', () => { await waitForPromises(); }); + it('displays a toast message during pipeline creation', async () => { + await findRunPipelineBtn().trigger('click'); + + expect($toast.show).toHaveBeenCalledWith(TOAST_MESSAGE); + }); + it('on desktop, shows a loading button', async () => { await findRunPipelineBtn().trigger('click'); diff --git a/spec/lib/gitlab/application_rate_limiter_spec.rb b/spec/lib/gitlab/application_rate_limiter_spec.rb index e13475d1108..ab6ac024af7 100644 --- a/spec/lib/gitlab/application_rate_limiter_spec.rb +++ b/spec/lib/gitlab/application_rate_limiter_spec.rb @@ -3,53 +3,29 @@ require 'spec_helper' RSpec.describe Gitlab::ApplicationRateLimiter do - let(:redis) { double('redis') } - let(:user) { create(:user) } - let(:project) { create(:project) } - let(:rate_limits) do - { - test_action: { - threshold: 1, - interval: 2.minutes - } - } - end - - let(:key) { rate_limits.keys[0] } + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project) } subject { described_class } - before do - allow(Gitlab::Redis::RateLimiting).to receive(:with).and_yield(redis) - allow(described_class).to receive(:rate_limits).and_return(rate_limits) - end - - shared_examples 'action rate limiter' do - it 'increases the throttle count and sets the expiration time' do - expect(redis).to receive(:incr).with(cache_key).and_return(1) - expect(redis).to receive(:expire).with(cache_key, 120) - - expect(subject.throttled?(key, scope: scope)).to be_falsy - end - - it 'returns true if the key is throttled' do - expect(redis).to receive(:incr).with(cache_key).and_return(2) - expect(redis).not_to receive(:expire) - - expect(subject.throttled?(key, scope: scope)).to be_truthy + describe '.throttled?' do + let(:rate_limits) do + { + test_action: { + threshold: 1, + interval: 2.minutes + }, + another_action: { + threshold: 2, + interval: 3.minutes + } + } end - context 'when throttling is disabled' do - it 'returns false and does not set expiration time' do - expect(redis).not_to receive(:incr) - expect(redis).not_to receive(:expire) - - expect(subject.throttled?(key, scope: scope, threshold: 0)).to be_falsy - end + before do + allow(described_class).to receive(:rate_limits).and_return(rate_limits) end - end - describe '.throttled?' do context 'when the key is invalid' do context 'is provided as a Symbol' do context 'but is not defined in the rate_limits Hash' do @@ -80,27 +56,116 @@ RSpec.describe Gitlab::ApplicationRateLimiter do end end - context 'when the key is an array of only ActiveRecord models' do - let(:scope) { [user, project] } + context 'when rate_limiter_safe_increment is disabled' do + let(:redis) { double('redis') } + let(:key) { rate_limits.keys[0] } + + before do + allow(Gitlab::Redis::RateLimiting).to receive(:with).and_yield(redis) + + stub_feature_flags(rate_limiter_safe_increment: false) + end + + shared_examples 'action rate limiter' do + it 'increases the throttle count and sets the expiration time' do + expect(redis).to receive(:incr).with(cache_key).and_return(1) + expect(redis).to receive(:expire).with(cache_key, 120) + + expect(subject.throttled?(key, scope: scope)).to be_falsy + end + + it 'returns true if the key is throttled' do + expect(redis).to receive(:incr).with(cache_key).and_return(2) + expect(redis).not_to receive(:expire) + + expect(subject.throttled?(key, scope: scope)).to be_truthy + end + + context 'when throttling is disabled' do + it 'returns false and does not set expiration time' do + expect(redis).not_to receive(:incr) + expect(redis).not_to receive(:expire) + + expect(subject.throttled?(key, scope: scope, threshold: 0)).to be_falsy + end + end + end + + context 'when the key is an array of only ActiveRecord models' do + let(:scope) { [user, project] } - let(:cache_key) do - "application_rate_limiter:test_action:user:#{user.id}:project:#{project.id}" + let(:cache_key) do + "application_rate_limiter:test_action:user:#{user.id}:project:#{project.id}" + end + + it_behaves_like 'action rate limiter' end - it_behaves_like 'action rate limiter' + context 'when the key is a combination of ActiveRecord models and strings' do + let(:project) { create(:project, :public, :repository) } + let(:commit) { project.repository.commit } + let(:path) { 'app/controllers/groups_controller.rb' } + let(:scope) { [project, commit, path] } + + let(:cache_key) do + "application_rate_limiter:test_action:project:#{project.id}:commit:#{commit.sha}:#{path}" + end + + it_behaves_like 'action rate limiter' + end end - context 'when they key a combination of ActiveRecord models and strings' do - let(:project) { create(:project, :public, :repository) } - let(:commit) { project.repository.commit } - let(:path) { 'app/controllers/groups_controller.rb' } - let(:scope) { [project, commit, path] } + context 'when rate_limiter_safe_increment is enabled', :clean_gitlab_redis_rate_limiting do + before do + stub_feature_flags(rate_limiter_safe_increment: true) + end + + shared_examples 'throttles based on key and scope' do + let(:start_time) { Time.current.beginning_of_hour } + + it 'returns true when threshold is exceeded' do + travel_to(start_time) do + expect(subject.throttled?(:test_action, scope: scope)).to eq(false) + end + + travel_to(start_time + 1.minute) do + expect(subject.throttled?(:test_action, scope: scope)).to eq(true) - let(:cache_key) do - "application_rate_limiter:test_action:project:#{project.id}:commit:#{commit.sha}:#{path}" + # Assert that it does not affect other actions or scope + expect(subject.throttled?(:another_action, scope: scope)).to eq(false) + expect(subject.throttled?(:test_action, scope: [user])).to eq(false) + end + end + + it 'returns false when interval has elapsed' do + travel_to(start_time) do + expect(subject.throttled?(:test_action, scope: scope)).to eq(false) + + # another_action has a threshold of 3 so we simulate 2 requests + expect(subject.throttled?(:another_action, scope: scope)).to eq(false) + expect(subject.throttled?(:another_action, scope: scope)).to eq(false) + end + + travel_to(start_time + 2.minutes) do + expect(subject.throttled?(:test_action, scope: scope)).to eq(false) + + # Assert that another_action has its own interval that hasn't elapsed + expect(subject.throttled?(:another_action, scope: scope)).to eq(true) + end + end end - it_behaves_like 'action rate limiter' + context 'when using ActiveRecord models as scope' do + let(:scope) { [user, project] } + + it_behaves_like 'throttles based on key and scope' + end + + context 'when using ActiveRecord models and strings as scope' do + let(:scope) { [project, 'app/controllers/groups_controller.rb'] } + + it_behaves_like 'throttles based on key and scope' + end end end @@ -134,7 +199,7 @@ RSpec.describe Gitlab::ApplicationRateLimiter do end context 'with a current_user' do - let(:current_user) { create(:user) } + let(:current_user) { user } let(:attributes) do base_attributes.merge({ diff --git a/spec/requests/api/lint_spec.rb b/spec/requests/api/lint_spec.rb index d7f22b9d619..ac30da99afe 100644 --- a/spec/requests/api/lint_spec.rb +++ b/spec/requests/api/lint_spec.rb @@ -102,6 +102,13 @@ RSpec.describe API::Lint do expect(response).to have_gitlab_http_status(:ok) expect(json_response).to have_key('merged_yaml') end + + it 'outputs jobs' do + post api('/ci/lint', api_user), params: { content: yaml_content, include_jobs: true } + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response).to have_key('jobs') + end end context 'with valid .gitlab-ci.yaml with warnings' do @@ -136,6 +143,13 @@ RSpec.describe API::Lint do expect(response).to have_gitlab_http_status(:ok) expect(json_response).to have_key('merged_yaml') end + + it 'outputs jobs' do + post api('/ci/lint', api_user), params: { content: yaml_content, include_jobs: true } + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response).to have_key('jobs') + end end context 'with invalid configuration' do @@ -156,6 +170,13 @@ RSpec.describe API::Lint do expect(response).to have_gitlab_http_status(:ok) expect(json_response).to have_key('merged_yaml') end + + it 'outputs jobs' do + post api('/ci/lint', api_user), params: { content: yaml_content, include_jobs: true } + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response).to have_key('jobs') + end end end @@ -171,10 +192,11 @@ RSpec.describe API::Lint do end describe 'GET /projects/:id/ci/lint' do - subject(:ci_lint) { get api("/projects/#{project.id}/ci/lint", api_user), params: { dry_run: dry_run } } + subject(:ci_lint) { get api("/projects/#{project.id}/ci/lint", api_user), params: { dry_run: dry_run, include_jobs: include_jobs } } let(:project) { create(:project, :repository) } let(:dry_run) { nil } + let(:include_jobs) { nil } RSpec.shared_examples 'valid config with warnings' do it 'passes validation with warnings' do @@ -359,6 +381,30 @@ RSpec.describe API::Lint do it_behaves_like 'valid config without warnings' end + context 'when running with include jobs' do + let(:include_jobs) { true } + + it_behaves_like 'valid config without warnings' + + it 'returns jobs key' do + ci_lint + + expect(json_response).to have_key('jobs') + end + end + + context 'when running without include jobs' do + let(:include_jobs) { false } + + it_behaves_like 'valid config without warnings' + + it 'does not return jobs key' do + ci_lint + + expect(json_response).not_to have_key('jobs') + end + end + context 'With warnings' do let(:yaml_content) { { job: { script: 'ls', rules: [{ when: 'always' }] } }.to_yaml } @@ -386,15 +432,40 @@ RSpec.describe API::Lint do it_behaves_like 'invalid config' end + + context 'when running with include jobs' do + let(:include_jobs) { true } + + it_behaves_like 'invalid config' + + it 'returns jobs key' do + ci_lint + + expect(json_response).to have_key('jobs') + end + end + + context 'when running without include jobs' do + let(:include_jobs) { false } + + it_behaves_like 'invalid config' + + it 'does not return jobs key' do + ci_lint + + expect(json_response).not_to have_key('jobs') + end + end end end end describe 'POST /projects/:id/ci/lint' do - subject(:ci_lint) { post api("/projects/#{project.id}/ci/lint", api_user), params: { dry_run: dry_run, content: yaml_content } } + subject(:ci_lint) { post api("/projects/#{project.id}/ci/lint", api_user), params: { dry_run: dry_run, content: yaml_content, include_jobs: include_jobs } } let(:project) { create(:project, :repository) } let(:dry_run) { nil } + let(:include_jobs) { nil } let_it_be(:api_user) { create(:user) } @@ -562,6 +633,30 @@ RSpec.describe API::Lint do it_behaves_like 'valid project config' end + + context 'when running with include jobs param' do + let(:include_jobs) { true } + + it_behaves_like 'valid project config' + + it 'contains jobs key' do + ci_lint + + expect(json_response).to have_key('jobs') + end + end + + context 'when running without include jobs param' do + let(:include_jobs) { false } + + it_behaves_like 'valid project config' + + it 'does not contain jobs key' do + ci_lint + + expect(json_response).not_to have_key('jobs') + end + end end context 'with invalid .gitlab-ci.yml content' do @@ -580,6 +675,30 @@ RSpec.describe API::Lint do it_behaves_like 'invalid project config' end + + context 'when running with include jobs set to false' do + let(:include_jobs) { false } + + it_behaves_like 'invalid project config' + + it 'does not contain jobs key' do + ci_lint + + expect(json_response).not_to have_key('jobs') + end + end + + context 'when running with param include jobs' do + let(:include_jobs) { true } + + it_behaves_like 'invalid project config' + + it 'contains jobs key' do + ci_lint + + expect(json_response).to have_key('jobs') + end + end end end end |