summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--app/assets/javascripts/ide/lib/editor.js5
-rw-r--r--app/assets/javascripts/performance_bar/components/request_selector.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/remove_member_modal.vue1
-rw-r--r--app/controllers/ide_controller.rb1
-rw-r--r--app/helpers/operations_helper.rb5
-rw-r--r--app/models/ci/job_artifact.rb6
-rw-r--r--app/models/ci/pipeline.rb4
-rw-r--r--app/serializers/pipeline_serializer.rb4
-rw-r--r--app/serializers/triggered_pipeline_entity.rb8
-rw-r--r--app/views/projects/services/alerts/_help.html.haml8
-rw-r--r--changelogs/unreleased/john_long-support-multiple-mailbox-email-check.yml5
-rw-r--r--changelogs/unreleased/render-job-details-on-downstream-pipelines.yml5
-rw-r--r--db/migrate/20200707095849_add_load_performance_to_plan_limits.rb9
-rw-r--r--db/structure.sql4
-rw-r--r--doc/ci/pipelines/job_artifacts.md11
-rw-r--r--doc/ci/yaml/README.md5
-rw-r--r--doc/development/README.md1
-rw-r--r--doc/development/feature_categorization/index.md130
-rw-r--r--doc/development/sidekiq_style_guide.md51
-rw-r--r--doc/topics/autodevops/customize.md3
-rw-r--r--doc/topics/git/partial_clone.md2
-rw-r--r--doc/user/project/merge_requests/img/load_performance_testing.pngbin0 -> 60196 bytes
-rw-r--r--doc/user/project/merge_requests/load_performance_testing.md197
-rw-r--r--doc/user/project/static_site_editor/index.md2
-rw-r--r--lib/gitlab/ci/config/entry/reports.rb3
-rw-r--r--lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Jobs/Load-Performance-Testing.gitlab-ci.yml29
-rw-r--r--lib/gitlab/ci/templates/Verify/Load-Performance-Testing.gitlab-ci.yml23
-rw-r--r--lib/system_check/incoming_email/imap_authentication_check.rb11
-rw-r--r--locale/gitlab.pot21
-rw-r--r--qa/qa/fixtures/monitored_auto_devops/.gitlab-ci.yml338
-rw-r--r--qa/qa/page/group/sub_menus/members.rb14
-rw-r--r--qa/qa/page/project/job/show.rb3
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/composer/index.json29
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/composer/package.json65
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/composer/provider.json25
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/group_package.json33
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/group_packages.json4
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/npm_package.json8
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/npm_package_tags.json7
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/npm_package_version.json46
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/nuget/dependency_group.json22
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/nuget/download_versions.json10
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/nuget/package_metadata.json28
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/nuget/packages_metadata.json54
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/nuget/search.json39
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/nuget/service_index.json19
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/package.json41
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/package_files.json13
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/package_version.json19
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/package_with_build.json10
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/packages.json4
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/pipeline.json27
-rw-r--r--spec/frontend/ide/lib/editor_spec.js14
-rw-r--r--spec/helpers/operations_helper_spec.rb3
-rw-r--r--spec/lib/gitlab/ci/config/entry/reports_spec.rb1
-rw-r--r--spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb75
-rw-r--r--spec/models/plan_limits_spec.rb1
-rw-r--r--spec/serializers/pipeline_details_entity_spec.rb18
-rw-r--r--spec/serializers/pipeline_serializer_spec.rb27
-rw-r--r--spec/services/ci/retry_build_service_spec.rb2
62 files changed, 1132 insertions, 426 deletions
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 7b0f0a221f8..86016519ba8 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-13.2.0-rc2
+74fa51387fbc4ac199309f5c0461d4cdde2a1a2f
diff --git a/app/assets/javascripts/ide/lib/editor.js b/app/assets/javascripts/ide/lib/editor.js
index a70611413ae..6e90968f008 100644
--- a/app/assets/javascripts/ide/lib/editor.js
+++ b/app/assets/javascripts/ide/lib/editor.js
@@ -45,7 +45,10 @@ export default class Editor {
setupThemes();
registerLanguages(...languages);
- registerSchemas(...schemas);
+
+ if (gon.features?.schemaLinting) {
+ registerSchemas(...schemas);
+ }
this.debouncedUpdate = debounce(() => {
this.updateDimensions();
diff --git a/app/assets/javascripts/performance_bar/components/request_selector.vue b/app/assets/javascripts/performance_bar/components/request_selector.vue
index 115b2ff08ac..c22a648d17f 100644
--- a/app/assets/javascripts/performance_bar/components/request_selector.vue
+++ b/app/assets/javascripts/performance_bar/components/request_selector.vue
@@ -45,7 +45,7 @@ export default {
};
</script>
<template>
- <div id="peek-request-selector" data-qa-selector="request_dropdown">
+ <div id="peek-request-selector" data-qa-selector="request_dropdown" class="view">
<select v-model="currentRequestId">
<option
v-for="request in requests"
diff --git a/app/assets/javascripts/vue_shared/components/remove_member_modal.vue b/app/assets/javascripts/vue_shared/components/remove_member_modal.vue
index 08b5fff780c..88d1b15aee3 100644
--- a/app/assets/javascripts/vue_shared/components/remove_member_modal.vue
+++ b/app/assets/javascripts/vue_shared/components/remove_member_modal.vue
@@ -62,6 +62,7 @@ export default {
:action-cancel="$options.actionCancel"
:action-primary="actionPrimary"
:title="actionText"
+ data-qa-selector="remove_member_modal_content"
@primary="submitForm"
>
<form ref="form" :action="modalData.memberPath" method="post">
diff --git a/app/controllers/ide_controller.rb b/app/controllers/ide_controller.rb
index 2bf7bdd1ae0..2c17f5b5542 100644
--- a/app/controllers/ide_controller.rb
+++ b/app/controllers/ide_controller.rb
@@ -8,6 +8,7 @@ class IdeController < ApplicationController
before_action do
push_frontend_feature_flag(:build_service_proxy)
+ push_frontend_feature_flag(:schema_linting)
end
def index
diff --git a/app/helpers/operations_helper.rb b/app/helpers/operations_helper.rb
index 419fdd521c2..42871e56a9d 100644
--- a/app/helpers/operations_helper.rb
+++ b/app/helpers/operations_helper.rb
@@ -15,7 +15,7 @@ module OperationsHelper
end
end
- def alerts_settings_data
+ def alerts_settings_data(disabled: false)
{
'prometheus_activated' => prometheus_service.manual_configuration?.to_s,
'activated' => alerts_service.activated?.to_s,
@@ -28,7 +28,8 @@ module OperationsHelper
'prometheus_url' => notify_project_prometheus_alerts_url(@project, format: :json),
'url' => alerts_service.url,
'alerts_setup_url' => help_page_path('user/project/integrations/generic_alerts.md', anchor: 'setting-up-generic-alerts'),
- 'alerts_usage_url' => project_alert_management_index_path(@project)
+ 'alerts_usage_url' => project_alert_management_index_path(@project),
+ 'disabled' => disabled.to_s
}
end
end
diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb
index d2aa336d12f..d20fdce10ef 100644
--- a/app/models/ci/job_artifact.rb
+++ b/app/models/ci/job_artifact.rb
@@ -35,6 +35,7 @@ module Ci
license_scanning: 'gl-license-scanning-report.json',
performance: 'performance.json',
browser_performance: 'browser-performance.json',
+ load_performance: 'load-performance.json',
metrics: 'metrics.txt',
lsif: 'lsif.json',
dotenv: '.env',
@@ -75,6 +76,7 @@ module Ci
license_scanning: :raw,
performance: :raw,
browser_performance: :raw,
+ load_performance: :raw,
terraform: :raw,
requirements: :raw,
coverage_fuzzing: :raw
@@ -96,6 +98,7 @@ module Ci
metrics
performance
browser_performance
+ load_performance
sast
secret_detection
requirements
@@ -196,7 +199,8 @@ module Ci
secret_detection: 21, ## EE-specific
requirements: 22, ## EE-specific
coverage_fuzzing: 23, ## EE-specific
- browser_performance: 24 ## EE-specific
+ browser_performance: 24, ## EE-specific
+ load_performance: 25 ## EE-specific
}
enum file_format: {
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 7d13adb22f0..7a7dbda8026 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -447,6 +447,10 @@ module Ci
end
end
+ def triggered_pipelines_with_preloads
+ triggered_pipelines.preload(:source_job)
+ end
+
def legacy_stages
if ::Gitlab::Ci::Features.composite_status?(project)
legacy_stages_using_composite_status
diff --git a/app/serializers/pipeline_serializer.rb b/app/serializers/pipeline_serializer.rb
index 21d49c6c292..bfd6851647f 100644
--- a/app/serializers/pipeline_serializer.rb
+++ b/app/serializers/pipeline_serializer.rb
@@ -60,8 +60,8 @@ class PipelineSerializer < BaseSerializer
},
pending_builds: :project,
project: [:route, { namespace: :route }],
- triggered_by_pipeline: [:project, :user],
- triggered_pipelines: [:project, :user]
+ triggered_by_pipeline: [{ project: [:route, { namespace: :route }] }, :user],
+ triggered_pipelines: [{ project: [:route, { namespace: :route }] }, :user, :source_job]
}
]
end
diff --git a/app/serializers/triggered_pipeline_entity.rb b/app/serializers/triggered_pipeline_entity.rb
index fd7e4454abf..47f51a6d76a 100644
--- a/app/serializers/triggered_pipeline_entity.rb
+++ b/app/serializers/triggered_pipeline_entity.rb
@@ -11,6 +11,12 @@ class TriggeredPipelineEntity < Grape::Entity
expose :coverage
expose :source
+ expose :source_job do
+ expose :name do |pipeline|
+ pipeline.source_job&.name
+ end
+ end
+
expose :path do |pipeline|
project_pipeline_path(pipeline.project, pipeline)
end
@@ -27,7 +33,7 @@ class TriggeredPipelineEntity < Grape::Entity
as: :triggered_by, with: TriggeredPipelineEntity,
if: -> (_, opts) { can_read_details? && expand_for_path?(opts) }
- expose :triggered_pipelines,
+ expose :triggered_pipelines_with_preloads,
as: :triggered, using: TriggeredPipelineEntity,
if: -> (_, opts) { can_read_details? && expand_for_path?(opts) }
diff --git a/app/views/projects/services/alerts/_help.html.haml b/app/views/projects/services/alerts/_help.html.haml
index 318d46e962a..7abd198bea5 100644
--- a/app/views/projects/services/alerts/_help.html.haml
+++ b/app/views/projects/services/alerts/_help.html.haml
@@ -1,7 +1 @@
-.js-alerts-service-settings{ data: { activated: @service.activated?.to_s,
- form_path: scoped_integration_path(@service),
- authorization_key: @service.token,
- url: @service.url || _('<namespace / project>'),
- disabled: 'true',
- alerts_setup_url: help_page_path('user/project/integrations/generic_alerts.md', anchor: 'setting-up-generic-alerts'),
- alerts_usage_url: help_page_path('user/project/operations/alert_management.md') } }
+.js-alerts-service-settings{ data: alerts_settings_data(disabled: true) }
diff --git a/changelogs/unreleased/john_long-support-multiple-mailbox-email-check.yml b/changelogs/unreleased/john_long-support-multiple-mailbox-email-check.yml
new file mode 100644
index 00000000000..a566fb73d2c
--- /dev/null
+++ b/changelogs/unreleased/john_long-support-multiple-mailbox-email-check.yml
@@ -0,0 +1,5 @@
+---
+title: Support multiple mailboxes incoming email check
+merge_request: 35639
+author:
+type: fixed
diff --git a/changelogs/unreleased/render-job-details-on-downstream-pipelines.yml b/changelogs/unreleased/render-job-details-on-downstream-pipelines.yml
new file mode 100644
index 00000000000..eb939b76873
--- /dev/null
+++ b/changelogs/unreleased/render-job-details-on-downstream-pipelines.yml
@@ -0,0 +1,5 @@
+---
+title: Render source job info in TriggeredPipelineEntity
+merge_request: 35232
+author:
+type: added
diff --git a/db/migrate/20200707095849_add_load_performance_to_plan_limits.rb b/db/migrate/20200707095849_add_load_performance_to_plan_limits.rb
new file mode 100644
index 00000000000..df95956f089
--- /dev/null
+++ b/db/migrate/20200707095849_add_load_performance_to_plan_limits.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddLoadPerformanceToPlanLimits < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :plan_limits, "ci_max_artifact_size_load_performance", :integer, default: 0, null: false
+ end
+end
diff --git a/db/structure.sql b/db/structure.sql
index 9c48e97aaf7..8393b4fb730 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -13815,7 +13815,8 @@ CREATE TABLE public.plan_limits (
ci_max_artifact_size_secret_detection integer DEFAULT 0 NOT NULL,
ci_max_artifact_size_requirements integer DEFAULT 0 NOT NULL,
ci_max_artifact_size_coverage_fuzzing integer DEFAULT 0 NOT NULL,
- ci_max_artifact_size_browser_performance integer DEFAULT 0 NOT NULL
+ ci_max_artifact_size_browser_performance integer DEFAULT 0 NOT NULL,
+ ci_max_artifact_size_load_performance integer DEFAULT 0 NOT NULL
);
CREATE SEQUENCE public.plan_limits_id_seq
@@ -23648,5 +23649,6 @@ COPY "schema_migrations" (version) FROM STDIN;
20200706170536
20200707071941
20200707094341
+20200707095849
\.
diff --git a/doc/ci/pipelines/job_artifacts.md b/doc/ci/pipelines/job_artifacts.md
index c2aad1ac6e4..1b6378c904d 100644
--- a/doc/ci/pipelines/job_artifacts.md
+++ b/doc/ci/pipelines/job_artifacts.md
@@ -257,6 +257,17 @@ as artifacts.
The collected Browser Performance report will be uploaded to GitLab as an artifact and will
be automatically shown in merge requests.
+#### `artifacts:reports:load_performance` **(PREMIUM)**
+
+> - Introduced in [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35260) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
+> - Requires GitLab Runner 11.5 and above.
+
+The `load_performance` report collects [Load Performance Testing metrics](../../user/project/merge_requests/load_performance_testing.md)
+as artifacts.
+
+The report is uploaded to GitLab as an artifact and is
+shown in merge requests automatically.
+
#### `artifacts:reports:metrics` **(PREMIUM)**
> Introduced in GitLab 11.10.
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 62dadaed9f5..68bbe74e2a4 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -117,7 +117,7 @@ The following table lists available parameters for jobs:
| [`when`](#when) | When to run job. Also available: `when:manual` and `when:delayed`. |
| [`environment`](#environment) | Name of an environment to which the job deploys. Also available: `environment:name`, `environment:url`, `environment:on_stop`, `environment:auto_stop_in` and `environment:action`. |
| [`cache`](#cache) | List of files that should be cached between subsequent runs. Also available: `cache:paths`, `cache:key`, `cache:untracked`, and `cache:policy`. |
-| [`artifacts`](#artifacts) | List of files and directories to attach to a job on success. Also available: `artifacts:paths`, `artifacts:exclude`, `artifacts:expose_as`, `artifacts:name`, `artifacts:untracked`, `artifacts:when`, `artifacts:expire_in`, `artifacts:reports`, `artifacts:reports:junit`, `artifacts:reports:cobertura`, and `artifacts:reports:terraform`.<br><br>In GitLab [Enterprise Edition](https://about.gitlab.com/pricing/), these are available: `artifacts:reports:codequality`, `artifacts:reports:sast`, `artifacts:reports:dependency_scanning`, `artifacts:reports:container_scanning`, `artifacts:reports:dast`, `artifacts:reports:license_scanning`, `artifacts:reports:license_management` (removed in GitLab 13.0), `artifacts:reports:performance` and `artifacts:reports:metrics`. |
+| [`artifacts`](#artifacts) | List of files and directories to attach to a job on success. Also available: `artifacts:paths`, `artifacts:exclude`, `artifacts:expose_as`, `artifacts:name`, `artifacts:untracked`, `artifacts:when`, `artifacts:expire_in`, `artifacts:reports`, `artifacts:reports:junit`, `artifacts:reports:cobertura`, and `artifacts:reports:terraform`.<br><br>In GitLab [Enterprise Edition](https://about.gitlab.com/pricing/), these are available: `artifacts:reports:codequality`, `artifacts:reports:sast`, `artifacts:reports:dependency_scanning`, `artifacts:reports:container_scanning`, `artifacts:reports:dast`, `artifacts:reports:license_scanning`, `artifacts:reports:license_management` (removed in GitLab 13.0), `artifacts:reports:performance`, `artifacts:reports:load_performance`, and `artifacts:reports:metrics`. |
| [`dependencies`](#dependencies) | Restrict which artifacts are passed to a specific job by providing a list of jobs to fetch artifacts from. |
| [`coverage`](#coverage) | Code coverage settings for a given job. |
| [`retry`](#retry) | When and how many times a job can be auto-retried in case of a failure. |
@@ -3148,7 +3148,8 @@ These are the available report types:
| [`artifacts:reports:dast`](../pipelines/job_artifacts.md#artifactsreportsdast-ultimate) **(ULTIMATE)** | The `dast` report collects Dynamic Application Security Testing vulnerabilities. |
| [`artifacts:reports:license_management`](../pipelines/job_artifacts.md#artifactsreportslicense_management-ultimate) **(ULTIMATE)** | The `license_management` report collects Licenses (*removed from GitLab 13.0*). |
| [`artifacts:reports:license_scanning`](../pipelines/job_artifacts.md#artifactsreportslicense_scanning-ultimate) **(ULTIMATE)** | The `license_scanning` report collects Licenses. |
-| [`artifacts:reports:performance`](../pipelines/job_artifacts.md#artifactsreportsperformance-premium) **(PREMIUM)** | The `performance` report collects Browser Performance metrics. |
+| [`artifacts:reports:performance`](../pipelines/job_artifacts.md#artifactsreportsperformance-premium) **(PREMIUM)** | The `performance` report collects Browser Performance metrics. |
+| [`artifacts:reports:load_performance`](../pipelines/job_artifacts.md#artifactsreportsload_performance-premium) **(PREMIUM)** | The `load_performance` report collects load performance metrics. |
| [`artifacts:reports:metrics`](../pipelines/job_artifacts.md#artifactsreportsmetrics-premium) **(PREMIUM)** | The `metrics` report collects Metrics. |
#### `dependencies`
diff --git a/doc/development/README.md b/doc/development/README.md
index 88abc638ac6..ab86c252948 100644
--- a/doc/development/README.md
+++ b/doc/development/README.md
@@ -101,6 +101,7 @@ Complementary reads:
- [Windows Development on GCP](windows.md)
- [Code Intelligence](code_intelligence/index.md)
- [Approval Rules](approval_rules.md)
+- [Feature categorization](feature_categorization/index.md)
## Performance guides
diff --git a/doc/development/feature_categorization/index.md b/doc/development/feature_categorization/index.md
new file mode 100644
index 00000000000..bcd5e16cc2b
--- /dev/null
+++ b/doc/development/feature_categorization/index.md
@@ -0,0 +1,130 @@
+# Feature Categorization
+
+> [Introduced](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/269) in GitLab 13.2.
+
+Each Sidekiq worker, controller action, or (eventually) API endpoint
+must declare a `feature_category` attribute. This attribute maps each
+of these to a [feature
+category](https://about.gitlab.com/handbook/product/product-categories/). This
+is done for error budgeting, alert routing, and team attribution.
+
+The list of feature categories can be found in the file `config/feature_categories.yml`.
+This file is generated from the
+[`stages.yml`](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml)
+data file used in the GitLab Handbook and other GitLab resources.
+
+## Updating `config/feature_categories.yml`
+
+Occasionally new features will be added to GitLab stages, groups, and
+product categories. When this occurs, you can automatically update
+`config/feature_categories.yml` by running
+`scripts/update-feature-categories`. This script will fetch and parse
+[`stages.yml`](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml)
+and generate a new version of the file, which needs to be committed to
+the repository.
+
+The [Scalabilitity
+team](https://about.gitlab.com/handbook/engineering/infrastructure/team/scalability)
+currently maintains the `stages.yml` file. They will automatically be
+notified on Slack when the file becomes outdated.
+
+## Sidekiq workers
+
+The declaration uses the `feature_category` class method, as shown below.
+
+```ruby
+class SomeScheduledTaskWorker
+ include ApplicationWorker
+
+ # Declares that this worker is part of the
+ # `continuous_integration` feature category
+ feature_category :continuous_integration
+
+ # ...
+end
+```
+
+The feature categories specified using `feature_category` should be
+defined in
+[`config/feature_categories.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/feature_categories.yml). If
+not, the specs will fail.
+
+### Excluding Sidekiq workers from feature categorization
+
+A few Sidekiq workers, that are used across all features, cannot be mapped to a
+single category. These should be declared as such using the `feature_category_not_owned!`
+declaration, as shown below:
+
+```ruby
+class SomeCrossCuttingConcernWorker
+ include ApplicationWorker
+
+ # Declares that this worker does not map to a feature category
+ feature_category_not_owned!
+
+ # ...
+end
+```
+
+## Rails controllers
+
+Specifying feature categories on controller actions can be done using
+the `feature_category` class method.
+
+A feature category can be specified on an entire controller
+using:
+
+```ruby
+class Projects::MergeRequestsController < ApplicationController
+ feature_category :source_code_management
+end
+```
+
+The feature category can be limited to a list of actions using the
+`only` argument, actions can be excluded using the `except` argument.
+
+```ruby
+class Projects::MergeRequestsController < ApplicationController
+ feature_category :code_testing, only: [:metrics_reports]
+ feature_category :source_code_management, except: [:test_reports, :coverage_reports]
+end
+```
+
+`except` and `only` arguments can not be combined.
+
+When specifying `except` all other actions will get the specified
+category assigned.
+
+The assignment can also be scoped using `if` and `unless` procs:
+
+```ruby
+class Projects::MergeRequestsController < ApplicationController
+ feature_category :source_code_management,
+ unless: -> (action) { action.include?("reports") }
+ if: -> (action) { action.include?("widget") }
+end
+```
+
+In this case, both procs need to be satisfied for the action to get
+the category assigned.
+
+### Excluding controller actions from feature categorization
+
+In the rare case an action cannot be tied to a feature category this
+can be done using the `not_owned` feature category.
+
+```ruby
+class Admin::LogsController < ApplicationController
+ feature_category :not_owned
+end
+```
+
+### Ensuring feature categories are valid
+
+The `spec/controllers/every_controller_spec.rb` will iterate over all
+defined routes, and check the controller to see if a category is
+assigned to all actions.
+
+The spec also validates if the used feature categories are known. And
+if the actions used in `only` and `except` configuration still exist
+as routes.
diff --git a/doc/development/sidekiq_style_guide.md b/doc/development/sidekiq_style_guide.md
index 86979c18a57..04c310288d2 100644
--- a/doc/development/sidekiq_style_guide.md
+++ b/doc/development/sidekiq_style_guide.md
@@ -378,55 +378,10 @@ We use the following approach to determine whether a worker is CPU-bound:
- Note that these values should not be used over small sample sizes, but
rather over fairly large aggregates.
-## Feature Categorization
+## Feature category
-Each Sidekiq worker, or one of its ancestor classes, must declare a
-`feature_category` attribute. This attribute maps each worker to a feature
-category. This is done for error budgeting, alert routing, and team attribution
-for Sidekiq workers.
-
-The declaration uses the `feature_category` class method, as shown below.
-
-```ruby
-class SomeScheduledTaskWorker
- include ApplicationWorker
-
- # Declares that this worker is part of the
- # `continuous_integration` feature category
- feature_category :continuous_integration
-
- # ...
-end
-```
-
-The list of value values can be found in the file `config/feature_categories.yml`.
-This file is, in turn generated from the [`stages.yml` from the GitLab Company Handbook
-source](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml).
-
-### Updating `config/feature_categories.yml`
-
-Occasionally new features will be added to GitLab stages. When this occurs, you
-can automatically update `config/feature_categories.yml` by running
-`scripts/update-feature-categories`. This script will fetch and parse
-[`stages.yml`](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml)
-and generate a new version of the file, which needs to be checked into source control.
-
-### Excluding Sidekiq workers from feature categorization
-
-A few Sidekiq workers, that are used across all features, cannot be mapped to a
-single category. These should be declared as such using the `feature_category_not_owned!`
- declaration, as shown below:
-
-```ruby
-class SomeCrossCuttingConcernWorker
- include ApplicationWorker
-
- # Declares that this worker does not map to a feature category
- feature_category_not_owned!
-
- # ...
-end
-```
+All Sidekiq workers must define a known [feature
+category](feature_categorization/index.md#sidekiq-workers).
## Job weights
diff --git a/doc/topics/autodevops/customize.md b/doc/topics/autodevops/customize.md
index 57851565e23..046db7a944b 100644
--- a/doc/topics/autodevops/customize.md
+++ b/doc/topics/autodevops/customize.md
@@ -364,7 +364,8 @@ The following table lists variables used to disable jobs.
| `DAST_DISABLED` | From GitLab 11.0, used to disable the `dast` job. If the variable is present, the job won't be created. |
| `DEPENDENCY_SCANNING_DISABLED` | From GitLab 11.0, used to disable the `dependency_scanning` job. If the variable is present, the job won't be created. |
| `LICENSE_MANAGEMENT_DISABLED` | From GitLab 11.0, used to disable the `license_management` job. If the variable is present, the job won't be created. |
-| `PERFORMANCE_DISABLED` | From GitLab 11.0, used to disable the `performance` job. If the variable is present, the job won't be created. |
+| `PERFORMANCE_DISABLED` | From GitLab 11.0, used to disable the browser `performance` job. If the variable is present, the job won't be created. |
+| `LOAD_PERFORMANCE_DISABLED` | From GitLab 13.2, used to disable the `load_performance` job. If the variable is present, the job won't be created. |
| `REVIEW_DISABLED` | From GitLab 11.0, used to disable the `review` and the manual `review:stop` job. If the variable is present, these jobs won't be created. |
| `SAST_DISABLED` | From GitLab 11.0, used to disable the `sast` job. If the variable is present, the job won't be created. |
| `TEST_DISABLED` | From GitLab 11.0, used to disable the `test` job. If the variable is present, the job won't be created. |
diff --git a/doc/topics/git/partial_clone.md b/doc/topics/git/partial_clone.md
index 25619b9d2a6..de25c8a3283 100644
--- a/doc/topics/git/partial_clone.md
+++ b/doc/topics/git/partial_clone.md
@@ -84,7 +84,7 @@ Updating files: 100% (28/28), done.
$ cd www-gitlab-com
-$ git sparse-checkout init --cone
+$ git sparse-checkout init --clone
$ git sparse-checkout add data
remote: Enumerating objects: 301, done.
diff --git a/doc/user/project/merge_requests/img/load_performance_testing.png b/doc/user/project/merge_requests/img/load_performance_testing.png
new file mode 100644
index 00000000000..3a58e9c28d4
--- /dev/null
+++ b/doc/user/project/merge_requests/img/load_performance_testing.png
Binary files differ
diff --git a/doc/user/project/merge_requests/load_performance_testing.md b/doc/user/project/merge_requests/load_performance_testing.md
new file mode 100644
index 00000000000..3239269109d
--- /dev/null
+++ b/doc/user/project/merge_requests/load_performance_testing.md
@@ -0,0 +1,197 @@
+---
+stage: Verify
+group: Testing
+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/#designated-technical-writers
+type: reference, howto
+---
+
+# Load Performance Testing **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10683) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
+
+With Load Performance Testing, you can test the impact of any pending code changes
+to your application's backend in [GitLab CI/CD](../../../ci/README.md).
+
+GitLab uses [k6](https://k6.io/), a free and open source
+tool, for measuring the system performance of applications under
+load.
+
+Unlike [Browser Performance Testing](browser_performance_testing.md), which is
+used to measure how web sites perform in client browsers, Load Performance Testing
+can be used to perform various types of [load tests](https://k6.io/docs/#use-cases)
+against application endpoints such as APIs, Web Controllers, and so on.
+This can be used to test how the backend or the server performs at scale.
+
+For example, you can use Load Performance Testing to perform many concurrent
+GET calls to a popular API endpoint in your application to see how it performs.
+
+## How Load Performance Testing works
+
+First, define a job in your `.gitlab-ci.yml` file that generates the
+[Load Performance report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportsload_performance-premium).
+GitLab checks this report, compares key load performance metrics
+between the source and target branches, and then shows the information in a merge request widget:
+
+![Load Performance Widget](img/load_performance_testing.png)
+
+Next, you need to configure the test environment and write the k6 test.
+
+The key performance metrics that the merge request widget shows after the test completes are:
+
+- Checks: The percentage pass rate of the [checks](https://k6.io/docs/using-k6/checks) configured in the k6 test.
+- TTFB P90: The 90th percentile of how long it took to start receiving responses, aka the [Time to First Byte](https://en.wikipedia.org/wiki/Time_to_first_byte) (TTFB).
+- TTFB P95: The 95th percentile for TTFB.
+- RPS: The average requests per second (RPS) rate the test was able to achieve.
+
+NOTE: **Note:**
+If the Load Performance report has no data to compare, such as when you add the
+Load Performance job in your `.gitlab-ci.yml` for the very first time,
+the Load Performance report widget won't show. It must have run at least
+once on the target branch (`master`, for example), before it will display in a
+merge request targeting that branch.
+
+## Configure the Load Performance Testing job
+
+Configuring your Load Performance Testing job can be broken down into several distinct parts:
+
+- Determine the test parameters such as throughput, and so on.
+- Set up the target test environment for load performance testing.
+- Design and write the k6 test.
+
+### Determine the test parameters
+
+The first thing you need to do is determine the [type of load test](https://k6.io/docs/test-types/introduction)
+you want to run, and how it will run (for example, the number of users, throughput, and so on).
+
+Refer to the [k6 docs](https://k6.io/docs/), especially the [k6 testing guides](https://k6.io/docs/testing-guides),
+for guidance on the above and more.
+
+### Test Environment setup
+
+A large part of the effort around load performance testing is to prepare the target test environment
+for high loads. You should ensure it's able to handle the
+[throughput](https://k6.io/blog/monthly-visits-concurrent-users) it will be tested with.
+
+It's also typically required to have representative test data in the target environment
+for the load performance test to use.
+
+We strongly recommend [not running these tests against a production environment](https://k6.io/our-beliefs#load-test-in-a-pre-production-environment).
+
+### Write the load performance test
+
+After the environment is prepared, you can write the k6 test itself. k6 is a flexible
+tool and can be used to run [many kinds of performance tests](https://k6.io/docs/test-types/introduction).
+Refer to the [k6 documentation](https://k6.io/docs/) for detailed information on how to write tests.
+
+### Configure the test in GitLab CI/CD
+
+When your k6 test is ready, the next step is to configure the load performance
+testing job in GitLab CI/CD. The easiest way to do this is to use the
+[`Verify/Load-Performance-Testing.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Verify/Load-Performance-Testing.gitlab-ci.yml)
+template that is included with GitLab.
+
+NOTE: **Note:**
+For large scale k6 tests you need to ensure the GitLab Runner instance performing the actual
+test is able to handle running the test. Refer to [k6's guidance](https://k6.io/docs/testing-guides/running-large-tests#hardware-considerations)
+for spec details. The [default shared GitLab.com runners](../../gitlab_com/#linux-shared-runners)
+likely have insufficient specs to handle most large k6 tests.
+
+This template runs the
+[k6 Docker container](https://hub.docker.com/r/loadimpact/k6/) in the job and provides several ways to customize the
+job.
+
+An example configuration workflow:
+
+1. Set up a GitLab Runner that can run Docker containers, such as a Runner using the
+ [Docker-in-Docker workflow](../../../ci/docker/using_docker_build.md#use-docker-in-docker-workflow-with-docker-executor).
+1. Configure the default Load Performance Testing CI job in your `.gitlab-ci.yml` file.
+ You need to include the template and configure it with variables:
+
+ ```yaml
+ include:
+ template: Verify/Load-Performance-Testing.gitlab-ci.yml
+
+ load_performance:
+ variables:
+ K6_TEST_FILE: <PATH TO K6 TEST FILE IN PROJECT>
+ ```
+
+The above example creates a `load_performance` job in your CI/CD pipeline that runs
+the k6 test.
+
+NOTE: **Note:**
+For Kubernetes setups a different template should be used: [`Jobs/Load-Performance-Testing.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Load-Performance-Testing.gitlab-ci.yml).
+
+k6 has [various options](https://k6.io/docs/using-k6/options) to configure how it will run tests, such as what throughput (RPS) to run with,
+how long the test should run, and so on. Almost all options can be configured in the test itself, but as
+you can also pass command line options via the `K6_OPTIONS` variable.
+
+For example, you can override the duration of the test with a CLI option:
+
+```yaml
+ include:
+ template: Verify/Load-Performance-Testing.gitlab-ci.yml
+
+ load_performance:
+ variables:
+ K6_TEST_FILE: <PATH TO K6 TEST FILE IN PROJECT>
+ K6_OPTIONS: '--duration 30s'
+```
+
+GitLab only displays the key performance metrics in the MR widget if k6's results are saved
+via [summary export](https://k6.io/docs/results-visualization/json#summary-export)
+as a [Load Performance report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportsload_performance-premium).
+The latest Load Performance artifact available is always used.
+
+If [GitLab Pages](../pages/index.md) is enabled, you can view the report directly in your browser.
+
+### Load Performance testing in Review Apps
+
+The CI/CD YAML configuration example above works for testing against static environments,
+but it can be extended to work with [review apps](../../../ci/review_apps) or
+[dynamic environments](../../../ci/environments) with a few extra steps.
+
+The best approach is to capture the dynamic URL into a custom environment variable that
+is then [inherited](../../../ci/variables/README.md#inherit-environment-variables)
+by the `load_performance` job. The k6 test script to be run should then be configured to
+use that environment URL, such as: ``http.get(`${__ENV.ENVIRONMENT_URL`})``.
+
+For example:
+
+1. In the `review` job:
+ 1. Capture the dynamic URL and save it into a `.env` file, e.g. `echo "ENVIRONMENT_URL=$CI_ENVIRONMENT_URL" >> review.env`.
+ 1. Set the `.env` file to be an [`artifacts:reports:dotenv` report](../../../ci/variables/README.md#inherit-environment-variables).
+1. Set the `load_performance` job to depend on the review job, so it inherits the environment variable.
+1. Configure the k6 test script to use the environment variable in it's steps.
+
+Your `.gitlab-ci.yml` file might be similar to:
+
+```yaml
+stages:
+ - deploy
+ - performance
+
+include:
+ template: Verify/Load-Performance-Testing.gitlab-ci.yml
+
+review:
+ stage: deploy
+ environment:
+ name: review/$CI_COMMIT_REF_NAME
+ url: http://$CI_ENVIRONMENT_SLUG.example.com
+ script:
+ - run_deploy_script
+ - echo "ENVIRONMENT_URL=$CI_ENVIRONMENT_URL" >> review.env
+ artifacts:
+ reports:
+ dotenv:
+ review.env
+ rules:
+ - if: '$CI_COMMIT_BRANCH' # Modify to match your pipeline rules, or use `only/except` if needed.
+
+load_performance:
+ dependencies:
+ - review
+ rules:
+ - if: '$CI_COMMIT_BRANCH' # Modify to match your pipeline rules, or use `only/except` if needed.
+```
diff --git a/doc/user/project/static_site_editor/index.md b/doc/user/project/static_site_editor/index.md
index 15c3bd5522e..8653bb5001a 100644
--- a/doc/user/project/static_site_editor/index.md
+++ b/doc/user/project/static_site_editor/index.md
@@ -9,6 +9,7 @@ description: "The static site editor enables users to edit content on static web
> - WYSIWYG editor [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214559) in GitLab 13.0.
> - Support for adding images through the WYSIWYG editor [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216640) in GitLab 13.1.
> - Markdown front matter hidden on the WYSIWYG editor [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216834) in GitLab 13.1.
+> - Support for `*.md.erb` files [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/223171) in GitLab 13.2.
DANGER: **Danger:**
In GitLab 13.0, we [introduced breaking changes](https://gitlab.com/gitlab-org/gitlab/-/issues/213282)
@@ -100,5 +101,4 @@ company and a new feature has been added to the company product.
## Limitations
-- Currently, the Static Site Editor only works for files ending in `.md`. For example, it will not work for a file `index.html.md.erb` while it works for `index.html.md`.
- The Static Site Editor still cannot be quickly added to existing Middleman sites. Follow this [epic](https://gitlab.com/groups/gitlab-org/-/epics/2784) for updates.
diff --git a/lib/gitlab/ci/config/entry/reports.rb b/lib/gitlab/ci/config/entry/reports.rb
index 8be18c059a3..0ae65f43723 100644
--- a/lib/gitlab/ci/config/entry/reports.rb
+++ b/lib/gitlab/ci/config/entry/reports.rb
@@ -13,7 +13,7 @@ module Gitlab
ALLOWED_KEYS =
%i[junit codequality sast secret_detection dependency_scanning container_scanning
- dast performance browser_performance license_management license_scanning metrics lsif
+ dast performance browser_performance load_performance license_management license_scanning metrics lsif
dotenv cobertura terraform accessibility cluster_applications
requirements coverage_fuzzing].freeze
@@ -34,6 +34,7 @@ module Gitlab
validates :dast, array_of_strings_or_string: true
validates :performance, array_of_strings_or_string: true
validates :browser_performance, array_of_strings_or_string: true
+ validates :load_performance, array_of_strings_or_string: true
validates :license_management, array_of_strings_or_string: true
validates :license_scanning, array_of_strings_or_string: true
validates :metrics, array_of_strings_or_string: true
diff --git a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
index e37cd14d1d1..bcd1e092191 100644
--- a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
@@ -12,6 +12,7 @@
# * code_quality: CODE_QUALITY_DISABLED
# * license_management: LICENSE_MANAGEMENT_DISABLED
# * performance: PERFORMANCE_DISABLED
+# * load_performance: LOAD_PERFORMANCE_DISABLED
# * sast: SAST_DISABLED
# * secret_detection: SECRET_DETECTION_DISABLED
# * dependency_scanning: DEPENDENCY_SCANNING_DISABLED
diff --git a/lib/gitlab/ci/templates/Jobs/Load-Performance-Testing.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Load-Performance-Testing.gitlab-ci.yml
new file mode 100644
index 00000000000..b437ddbd734
--- /dev/null
+++ b/lib/gitlab/ci/templates/Jobs/Load-Performance-Testing.gitlab-ci.yml
@@ -0,0 +1,29 @@
+load_performance:
+ stage: performance
+ image: docker:19.03.11
+ allow_failure: true
+ variables:
+ DOCKER_TLS_CERTDIR: ""
+ K6_IMAGE: loadimpact/k6
+ K6_VERSION: 0.26.2
+ K6_TEST_FILE: github.com/loadimpact/k6/samples/http_get.js
+ K6_OPTIONS: ''
+ services:
+ - docker:19.03.11-dind
+ script:
+ - |
+ if ! docker info &>/dev/null; then
+ if [ -z "$DOCKER_HOST" -a "$KUBERNETES_PORT" ]; then
+ export DOCKER_HOST='tcp://localhost:2375'
+ fi
+ fi
+ - docker run --rm -v "$(pwd)":/k6 -w /k6 $K6_IMAGE:$K6_VERSION run $K6_TEST_FILE --summary-export=load-performance.json $K6_OPTIONS
+ artifacts:
+ reports:
+ load_performance: load-performance.json
+ rules:
+ - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ when: never
+ - if: '$LOAD_PERFORMANCE_DISABLED'
+ when: never
+ - if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH'
diff --git a/lib/gitlab/ci/templates/Verify/Load-Performance-Testing.gitlab-ci.yml b/lib/gitlab/ci/templates/Verify/Load-Performance-Testing.gitlab-ci.yml
new file mode 100644
index 00000000000..d39bd234020
--- /dev/null
+++ b/lib/gitlab/ci/templates/Verify/Load-Performance-Testing.gitlab-ci.yml
@@ -0,0 +1,23 @@
+# Read more about the feature here: https://docs.gitlab.com/ee/user/project/merge_requests/load_performance_testing.html
+
+stages:
+ - build
+ - test
+ - deploy
+ - performance
+
+load_performance:
+ stage: performance
+ image: docker:git
+ variables:
+ K6_IMAGE: loadimpact/k6
+ K6_VERSION: 0.26.2
+ K6_TEST_FILE: github.com/loadimpact/k6/samples/http_get.js
+ K6_OPTIONS: ''
+ services:
+ - docker:stable-dind
+ script:
+ - docker run --rm -v "$(pwd)":/k6 -w /k6 $K6_IMAGE:$K6_VERSION run $K6_TEST_FILE --summary-export=load-performance.json $K6_OPTIONS
+ artifacts:
+ reports:
+ load_performance: load-performance.json
diff --git a/lib/system_check/incoming_email/imap_authentication_check.rb b/lib/system_check/incoming_email/imap_authentication_check.rb
index 613c2296375..056021d460c 100644
--- a/lib/system_check/incoming_email/imap_authentication_check.rb
+++ b/lib/system_check/incoming_email/imap_authentication_check.rb
@@ -28,9 +28,12 @@ module SystemCheck
private
def try_connect_imap
- imap = Net::IMAP.new(config[:host], port: config[:port], ssl: config[:ssl])
- imap.starttls if config[:start_tls]
- imap.login(config[:email], config[:password])
+ config.each do |mailbox|
+ $stdout.puts "Checking #{mailbox[:email]}"
+ imap = Net::IMAP.new(mailbox[:host], port: mailbox[:port], ssl: mailbox[:ssl])
+ imap.starttls if mailbox[:start_tls]
+ imap.login(mailbox[:email], mailbox[:password])
+ end
true
rescue => error
@error = error
@@ -51,7 +54,7 @@ module SystemCheck
erb.filename = mail_room_config_path
config_file = YAML.load(erb.result)
- config_file.dig(:mailboxes, 0)
+ config_file[:mailboxes]
end
end
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index ddd3429c495..058eb4fe0d2 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -986,9 +986,6 @@ msgstr ""
msgid "<code>Protected</code> to expose them to protected branches or tags only."
msgstr ""
-msgid "<namespace / project>"
-msgstr ""
-
msgid "<no name set>"
msgstr ""
@@ -27247,6 +27244,9 @@ msgstr ""
msgid "ciReport|Browser performance test metrics: No changes"
msgstr ""
+msgid "ciReport|Checks"
+msgstr ""
+
msgid "ciReport|Code quality"
msgstr ""
@@ -27307,6 +27307,12 @@ msgstr ""
msgid "ciReport|Learn more about interacting with security reports"
msgstr ""
+msgid "ciReport|Load performance test metrics: "
+msgstr ""
+
+msgid "ciReport|Load performance test metrics: No changes"
+msgstr ""
+
msgid "ciReport|Loading %{reportName} report"
msgstr ""
@@ -27322,6 +27328,9 @@ msgstr ""
msgid "ciReport|No code quality issues found"
msgstr ""
+msgid "ciReport|RPS"
+msgstr ""
+
msgid "ciReport|Resolve with merge request"
msgstr ""
@@ -27349,6 +27358,12 @@ msgstr ""
msgid "ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code."
msgstr ""
+msgid "ciReport|TTFB P90"
+msgstr ""
+
+msgid "ciReport|TTFB P95"
+msgstr ""
+
msgid "ciReport|There was an error creating the issue. Please try again."
msgstr ""
diff --git a/qa/qa/fixtures/monitored_auto_devops/.gitlab-ci.yml b/qa/qa/fixtures/monitored_auto_devops/.gitlab-ci.yml
deleted file mode 100644
index 052ba1c14fb..00000000000
--- a/qa/qa/fixtures/monitored_auto_devops/.gitlab-ci.yml
+++ /dev/null
@@ -1,338 +0,0 @@
-# This is stripped down version of the .gitlab-ci.yml found
-# here: https://gitlab.com/joshlambert/autodevops-deploy.
-#
-# It performs only the deploy stage.
-
-image: alpine:latest
-
-variables:
- # AUTO_DEVOPS_DOMAIN is the application deployment domain and should be set as a variable at the group or project level.
- AUTO_DEVOPS_DOMAIN: $AUTO_DEVOPS_DOMAIN
-
- POSTGRES_USER: user
- POSTGRES_PASSWORD: testing-password
- POSTGRES_ENABLED: 'false'
- POSTGRES_DB: $CI_ENVIRONMENT_SLUG
-
- KUBERNETES_VERSION: 1.11.6
- HELM_VERSION: 2.12.2
-
- DOCKER_DRIVER: overlay2
-
-stages:
- - production
-
-# This job continuously deploys to production on every push to `master`.
-
-production:
- stage: production
- tags:
- - qa
- script:
- - check_kube_domain
- - install_dependencies
- - download_chart
- - ensure_namespace
- - initialize_tiller
- - create_secret
- - deploy
- environment:
- name: production
- url: http://$CI_PROJECT_PATH_SLUG.$AUTO_DEVOPS_DOMAIN
- artifacts:
- paths: [environment_url.txt]
- only:
- refs:
- - master
- kubernetes: active
-
-# ---------------------------------------------------------------------------
-
-.auto_devops: &auto_devops |
- # Auto DevOps variables and functions
- [[ "$TRACE" ]] && set -x
- auto_database_url=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${CI_ENVIRONMENT_SLUG}-postgres:5432/${POSTGRES_DB}
- export DATABASE_URL=${DATABASE_URL-$auto_database_url}
- export CI_APPLICATION_REPOSITORY=$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG
- export CI_APPLICATION_TAG=$CI_COMMIT_SHA
- export CI_CONTAINER_NAME=ci_job_build_${CI_JOB_ID}
- export TILLER_NAMESPACE=$KUBE_NAMESPACE
- # Extract "MAJOR.MINOR" from CI_SERVER_VERSION and generate "MAJOR-MINOR-stable" for Security Products
- export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
-
-
- function get_replicas() {
- track="${1:-stable}"
- percentage="${2:-100}"
-
- env_track=$( echo $track | tr -s '[:lower:]' '[:upper:]' )
- env_slug=$( echo ${CI_ENVIRONMENT_SLUG//-/_} | tr -s '[:lower:]' '[:upper:]' )
-
- if [[ "$track" == "stable" ]] || [[ "$track" == "rollout" ]]; then
- # for stable track get number of replicas from `PRODUCTION_REPLICAS`
- eval new_replicas=\$${env_slug}_REPLICAS
- if [[ -z "$new_replicas" ]]; then
- new_replicas=$REPLICAS
- fi
- else
- # for all tracks get number of replicas from `CANARY_PRODUCTION_REPLICAS`
- eval new_replicas=\$${env_track}_${env_slug}_REPLICAS
- if [[ -z "$new_replicas" ]]; then
- eval new_replicas=\${env_track}_REPLICAS
- fi
- fi
-
- replicas="${new_replicas:-1}"
- replicas="$(($replicas * $percentage / 100))"
-
- # always return at least one replicas
- if [[ $replicas -gt 0 ]]; then
- echo "$replicas"
- else
- echo 1
- fi
- }
-
-
- # Extracts variables prefixed with K8S_SECRET_
- # and creates a Kubernetes secret.
- #
- # e.g. If we have the following environment variables:
- # K8S_SECRET_A=value1
- # K8S_SECRET_B=multi\ word\ value
- #
- # Then we will create a secret with the following key-value pairs:
- # data:
- # A: dmFsdWUxCg==
- # B: bXVsdGkgd29yZCB2YWx1ZQo=
- function create_application_secret() {
- track="${1-stable}"
- export APPLICATION_SECRET_NAME=$(application_secret_name "$track")
-
- env | sed -n "s/^K8S_SECRET_\(.*\)$/\1/p" > k8s_prefixed_variables
-
- kubectl create secret \
- -n "$KUBE_NAMESPACE" generic "$APPLICATION_SECRET_NAME" \
- --from-env-file k8s_prefixed_variables -o yaml --dry-run |
- kubectl replace -n "$KUBE_NAMESPACE" --force -f -
-
- export APPLICATION_SECRET_CHECKSUM=$(cat k8s_prefixed_variables | sha256sum | cut -d ' ' -f 1)
-
- rm k8s_prefixed_variables
- }
-
- function deploy_name() {
- name="$CI_ENVIRONMENT_SLUG"
- track="${1-stable}"
-
- if [[ "$track" != "stable" ]]; then
- name="$name-$track"
- fi
-
- echo $name
- }
-
- function application_secret_name() {
- track="${1-stable}"
- name=$(deploy_name "$track")
-
- echo "${name}-secret"
- }
-
-
- function deploy() {
- track="${1-stable}"
- percentage="${2:-100}"
- name=$(deploy_name "$track")
-
- replicas="1"
- service_enabled="true"
- postgres_enabled="$POSTGRES_ENABLED"
-
- # if track is different than stable,
- # re-use all attached resources
- if [[ "$track" != "stable" ]]; then
- service_enabled="false"
- postgres_enabled="false"
- fi
-
- replicas=$(get_replicas "$track" "$percentage")
-
- if [[ "$CI_PROJECT_VISIBILITY" != "public" ]]; then
- secret_name='gitlab-registry'
- else
- secret_name=''
- fi
-
- create_application_secret "$track"
-
- env_slug=$(echo ${CI_ENVIRONMENT_SLUG//-/_} | tr -s '[:lower:]' '[:upper:]')
- eval env_ADDITIONAL_HOSTS=\$${env_slug}_ADDITIONAL_HOSTS
- if [ -n "$env_ADDITIONAL_HOSTS" ]; then
- additional_hosts="{$env_ADDITIONAL_HOSTS}"
- elif [ -n "$ADDITIONAL_HOSTS" ]; then
- additional_hosts="{$ADDITIONAL_HOSTS}"
- fi
-
- if [[ -n "$DB_INITIALIZE" && -z "$(helm ls -q "^$name$")" ]]; then
- echo "Deploying first release with database initialization..."
- helm upgrade --install \
- --wait \
- --set service.enabled="$service_enabled" \
- --set releaseOverride="$CI_ENVIRONMENT_SLUG" \
- --set image.repository="registry.gitlab.com/joshlambert/ruby-gke/master" \
- --set image.tag="63492726c2264a0277141d6a6573c3d22ecd7de3" \
- --set image.pullPolicy=IfNotPresent \
- --set image.secrets[0].name="$secret_name" \
- --set application.track="$track" \
- --set application.database_url="$DATABASE_URL" \
- --set application.secretName="$APPLICATION_SECRET_NAME" \
- --set application.secretChecksum="$APPLICATION_SECRET_CHECKSUM" \
- --set service.url="$CI_ENVIRONMENT_URL" \
- --set service.additionalHosts="$additional_hosts" \
- --set replicaCount="$replicas" \
- --set postgresql.enabled="$postgres_enabled" \
- --set postgresql.nameOverride="postgres" \
- --set postgresql.postgresUser="$POSTGRES_USER" \
- --set postgresql.postgresPassword="$POSTGRES_PASSWORD" \
- --set postgresql.postgresDatabase="$POSTGRES_DB" \
- --set application.initializeCommand="$DB_INITIALIZE" \
- --set gitlab.app="$CI_PROJECT_PATH_SLUG" \
- --set gitlab.env="$CI_ENVIRONMENT_SLUG" \
- --namespace="$KUBE_NAMESPACE" \
- "$name" \
- chart/
-
- echo "Deploying second release..."
- helm upgrade --reuse-values \
- --wait \
- --set application.initializeCommand="" \
- --set application.migrateCommand="$DB_MIGRATE" \
- --namespace="$KUBE_NAMESPACE" \
- "$name" \
- chart/
- else
- echo "Deploying new release..."
- helm upgrade --install \
- --wait \
- --set service.enabled="$service_enabled" \
- --set releaseOverride="$CI_ENVIRONMENT_SLUG" \
- --set image.repository="registry.gitlab.com/joshlambert/ruby-gke/master" \
- --set image.tag="63492726c2264a0277141d6a6573c3d22ecd7de3" \
- --set image.pullPolicy=IfNotPresent \
- --set image.secrets[0].name="$secret_name" \
- --set application.track="$track" \
- --set application.database_url="$DATABASE_URL" \
- --set application.secretName="$APPLICATION_SECRET_NAME" \
- --set application.secretChecksum="$APPLICATION_SECRET_CHECKSUM" \
- --set service.url="$CI_ENVIRONMENT_URL" \
- --set service.additionalHosts="$additional_hosts" \
- --set replicaCount="$replicas" \
- --set postgresql.enabled="$postgres_enabled" \
- --set postgresql.nameOverride="postgres" \
- --set postgresql.postgresUser="$POSTGRES_USER" \
- --set postgresql.postgresPassword="$POSTGRES_PASSWORD" \
- --set postgresql.postgresDatabase="$POSTGRES_DB" \
- --set application.migrateCommand="$DB_MIGRATE" \
- --set gitlab.app="$CI_PROJECT_PATH_SLUG" \
- --set gitlab.env="$CI_ENVIRONMENT_SLUG" \
- --namespace="$KUBE_NAMESPACE" \
- "$name" \
- chart/
- fi
-
- kubectl rollout status -n "$KUBE_NAMESPACE" -w "deployment/$name"
- }
-
-
- function install_dependencies() {
- apk add -U openssl curl tar gzip bash ca-certificates git
- wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub
- wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.23-r3/glibc-2.23-r3.apk
- apk add glibc-2.23-r3.apk
- rm glibc-2.23-r3.apk
-
- curl "https://kubernetes-helm.storage.googleapis.com/helm-v${HELM_VERSION}-linux-amd64.tar.gz" | tar zx
- mv linux-amd64/helm /usr/bin/
- mv linux-amd64/tiller /usr/bin/
- helm version --client
- tiller -version
-
- curl -L -o /usr/bin/kubectl "https://storage.googleapis.com/kubernetes-release/release/v${KUBERNETES_VERSION}/bin/linux/amd64/kubectl"
- chmod +x /usr/bin/kubectl
- kubectl version --client
- }
-
- function download_chart() {
- if [[ ! -d chart ]]; then
- auto_chart=${AUTO_DEVOPS_CHART:-gitlab/auto-deploy-app}
- auto_chart_name=$(basename $auto_chart)
- auto_chart_name=${auto_chart_name%.tgz}
- else
- auto_chart="chart"
- auto_chart_name="chart"
- fi
-
- helm init --client-only
- helm repo add gitlab https://charts.gitlab.io
- if [[ ! -d "$auto_chart" ]]; then
- helm fetch ${auto_chart} --untar
- fi
- if [ "$auto_chart_name" != "chart" ]; then
- mv ${auto_chart_name} chart
- fi
-
- helm dependency update chart/
- helm dependency build chart/
- }
-
- function ensure_namespace() {
- kubectl describe namespace "$KUBE_NAMESPACE" || kubectl create namespace "$KUBE_NAMESPACE"
- }
-
- function check_kube_domain() {
- if [ -z ${AUTO_DEVOPS_DOMAIN+x} ]; then
- echo "In order to deploy or use Review Apps, AUTO_DEVOPS_DOMAIN variable must be set"
- echo "You can do it in Auto DevOps project settings or defining a secret variable at group or project level"
- echo "You can also manually add it in .gitlab-ci.yml"
- false
- else
- true
- fi
- }
-
- function initialize_tiller() {
- echo "Checking Tiller..."
-
- export HELM_HOST="localhost:44134"
- tiller -listen ${HELM_HOST} -alsologtostderr > /dev/null 2>&1 &
- echo "Tiller is listening on ${HELM_HOST}"
-
- if ! helm version --debug; then
- echo "Failed to init Tiller."
- return 1
- fi
- echo ""
- }
-
- function create_secret() {
- echo "Create secret..."
- if [[ "$CI_PROJECT_VISIBILITY" == "public" ]]; then
- return
- fi
-
- kubectl create secret -n "$KUBE_NAMESPACE" \
- docker-registry gitlab-registry \
- --docker-server="$CI_REGISTRY" \
- --docker-username="$CI_REGISTRY_USER" \
- --docker-password="$CI_REGISTRY_PASSWORD" \
- --docker-email="$GITLAB_USER_EMAIL" \
- -o yaml --dry-run | kubectl replace -n "$KUBE_NAMESPACE" --force -f -
- }
-
- function persist_environment_url() {
- echo $CI_ENVIRONMENT_URL > environment_url.txt
- }
-
-before_script:
- - *auto_devops
diff --git a/qa/qa/page/group/sub_menus/members.rb b/qa/qa/page/group/sub_menus/members.rb
index 33c4caaddcb..895da639c02 100644
--- a/qa/qa/page/group/sub_menus/members.rb
+++ b/qa/qa/page/group/sub_menus/members.rb
@@ -7,6 +7,10 @@ module QA
class Members < Page::Base
include Page::Component::UsersSelect
+ view 'app/assets/javascripts/vue_shared/components/remove_member_modal.vue' do
+ element :remove_member_modal_content
+ end
+
view 'app/views/shared/members/_invite_member.html.haml' do
element :member_select_field
element :invite_member_button
@@ -32,10 +36,12 @@ module QA
end
def remove_member(username)
- page.accept_confirm do
- within_element(:member_row, text: username) do
- click_element :delete_member_button
- end
+ within_element(:member_row, text: username) do
+ click_element :delete_member_button
+ end
+
+ within_element(:remove_member_modal_content) do
+ click_button("Remove member")
end
end
end
diff --git a/qa/qa/page/project/job/show.rb b/qa/qa/page/project/job/show.rb
index 971b8c5e5f8..6243dc92b45 100644
--- a/qa/qa/page/project/job/show.rb
+++ b/qa/qa/page/project/job/show.rb
@@ -23,6 +23,9 @@ module QA
raise "Timed out waiting for the build trace to load" unless loaded?
raise "Timed out waiting for the status to be a valid completed state" unless completed?(timeout: timeout)
+ job_log = find_element(:job_log_content).text
+ QA::Runtime::Logger.debug(" \n\n ------- Job log: ------- \n\n #{job_log} \n -------")
+
passed?
end
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/composer/index.json b/spec/fixtures/api/schemas/public_api/v4/packages/composer/index.json
new file mode 100644
index 00000000000..2245b39cabe
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/composer/index.json
@@ -0,0 +1,29 @@
+{
+ "type": "object",
+ "required": ["packages", "provider-includes", "providers-url"],
+ "properties": {
+ "packages": {
+ "type": "array",
+ "items": { "type": "integer" }
+ },
+ "providers-url": {
+ "type": "string"
+ },
+ "provider-includes": {
+ "type": "object",
+ "required": ["p/%hash%.json"],
+ "properties": {
+ "p/%hash%.json": {
+ "type": "object",
+ "required": ["sha256"],
+ "properties": {
+ "sha256": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/composer/package.json b/spec/fixtures/api/schemas/public_api/v4/packages/composer/package.json
new file mode 100644
index 00000000000..324a8a4e00c
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/composer/package.json
@@ -0,0 +1,65 @@
+{
+ "type": "object",
+ "required": [
+ "packages"
+ ],
+ "properties": {
+ "packages": {
+ "type": "object",
+ "propertyNames": {
+ "pattern": "^[A-Za-z_]+"
+ },
+ "patternProperties": {
+ "^[A-Za-z_]+": {
+ "type": "object",
+ "propertyNames": {
+ "pattern": "^[A-Za-z_0-9.]+"
+ },
+ "patternProperties": {
+ "^[A-Za-z_0-9.]+": {
+ "type": "object",
+ "required": [
+ "dist",
+ "uid",
+ "version"
+ ],
+ "properties": {
+ "uid": {
+ "type": "integer"
+ },
+ "version": {
+ "type": "string"
+ },
+ "dist": {
+ "type": "object",
+ "required": [
+ "type",
+ "url",
+ "reference",
+ "shasum"
+ ],
+ "properties": {
+ "type": {
+ "type": "string"
+ },
+ "url": {
+ "type": "string"
+ },
+ "reference": {
+ "type": "string"
+ },
+ "shasum": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/composer/provider.json b/spec/fixtures/api/schemas/public_api/v4/packages/composer/provider.json
new file mode 100644
index 00000000000..5335fa9ad64
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/composer/provider.json
@@ -0,0 +1,25 @@
+{
+ "type": "object",
+ "required": ["providers"],
+ "properties": {
+ "providers": {
+ "type": "object",
+ "propertyNames": {
+ "pattern": "^[A-Za-z_]+"
+ },
+ "patternProperties": {
+ "^[A-Za-z_]+": {
+ "type": "object",
+ "required": ["sha256"],
+ "properties": {
+ "sha256": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/group_package.json b/spec/fixtures/api/schemas/public_api/v4/packages/group_package.json
new file mode 100644
index 00000000000..f18e314a287
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/group_package.json
@@ -0,0 +1,33 @@
+{
+ "type": "object",
+ "required": ["name", "version", "package_type", "_links", "project_id", "project_path"],
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "version": {
+ "type": "string"
+ },
+ "package_type": {
+ "type": "string"
+ },
+ "_links": {
+ "type": "object",
+ "required": ["web_path"],
+ "properties": {
+ "details": {
+ "type": "string"
+ }
+ }
+ },
+ "created_at": {
+ "type": "string"
+ },
+ "project_id": {
+ "type": "integer"
+ },
+ "project_path": {
+ "type": "string"
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/group_packages.json b/spec/fixtures/api/schemas/public_api/v4/packages/group_packages.json
new file mode 100644
index 00000000000..3169bbc8f25
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/group_packages.json
@@ -0,0 +1,4 @@
+{
+ "type": "array",
+ "items": { "$ref": "./group_package.json" }
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/npm_package.json b/spec/fixtures/api/schemas/public_api/v4/packages/npm_package.json
new file mode 100644
index 00000000000..d7e8a872abe
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/npm_package.json
@@ -0,0 +1,8 @@
+{
+ "type": "object",
+ "required" : ["name", "versions"],
+ "properties" : {
+ "name": { "type": "string" },
+ "versions": { "type": "object" }
+ }
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/npm_package_tags.json b/spec/fixtures/api/schemas/public_api/v4/packages/npm_package_tags.json
new file mode 100644
index 00000000000..db64fe1de23
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/npm_package_tags.json
@@ -0,0 +1,7 @@
+{
+ "type": "object",
+ "properties" : {
+ "$tag": { "type": "string" },
+ "$version": { "type": "string" }
+ }
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/npm_package_version.json b/spec/fixtures/api/schemas/public_api/v4/packages/npm_package_version.json
new file mode 100644
index 00000000000..3e74dc0a1c2
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/npm_package_version.json
@@ -0,0 +1,46 @@
+{
+ "type": "object",
+ "required": ["name", "version", "dist"],
+ "properties" : {
+ "name": { "type": "string" },
+ "version": { "type": "string" },
+ "dist": {
+ "type": "object",
+ "required": ["shasum", "tarball"],
+ "properties" : {
+ "shasum": { "type": "string" },
+ "tarball": { "type": "string" }
+ }
+ },
+ "dependencies": {
+ "type": "object",
+ "patternProperties": {
+ ".{1,}": { "type": "string" }
+ }
+ },
+ "devDependencies": {
+ "type": "object",
+ "patternProperties": {
+ ".{1,}": { "type": "string" }
+ }
+ },
+ "bundleDependencies": {
+ "type": "object",
+ "patternProperties": {
+ ".{1,}": { "type": "string" }
+ }
+ },
+ "peerDependencies": {
+ "type": "object",
+ "patternProperties": {
+ ".{1,}": { "type": "string" }
+ }
+ },
+ "deprecated": {
+ "type": "object",
+ "patternProperties": {
+ ".{1,}": { "type": "string" }
+ }
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/nuget/dependency_group.json b/spec/fixtures/api/schemas/public_api/v4/packages/nuget/dependency_group.json
new file mode 100644
index 00000000000..87dc2794b61
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/nuget/dependency_group.json
@@ -0,0 +1,22 @@
+{
+ "type": "object",
+ "required": ["@id", "@type", "dependencies"],
+ "properties": {
+ "@id": { "type": "string" },
+ "@type": { "const": "PackageDependencyGroup" },
+ "targetFramework": { "type": "string" },
+ "dependencies": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": ["@id", "@type", "id", "range"],
+ "properties": {
+ "@id": { "type": "string" },
+ "@type": { "const": "PackageDependency" },
+ "id": { "type": "string" },
+ "range": { "type": "string" }
+ }
+ }
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/nuget/download_versions.json b/spec/fixtures/api/schemas/public_api/v4/packages/nuget/download_versions.json
new file mode 100644
index 00000000000..ab40dfbbc4c
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/nuget/download_versions.json
@@ -0,0 +1,10 @@
+{
+ "type": "object",
+ "required": ["versions"],
+ "properties": {
+ "versions": {
+ "type": "array",
+ "items": { "type": "string" }
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/nuget/package_metadata.json b/spec/fixtures/api/schemas/public_api/v4/packages/nuget/package_metadata.json
new file mode 100644
index 00000000000..1244cbe474e
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/nuget/package_metadata.json
@@ -0,0 +1,28 @@
+{
+ "type": "object",
+ "required": ["@id", "packageContent", "catalogEntry"],
+ "properties": {
+ "@id": { "type": "string" },
+ "packageContent": { "type": "string" },
+ "catalogEntry": {
+ "type": "object",
+ "required": ["@id", "authors", "dependencyGroups", "id", "packageContent", "summary", "version"],
+ "properties": {
+ "@id": { "type": "string" },
+ "authors": { "const": "" },
+ "id": { "type": "string" },
+ "packageContent": { "type": "string" },
+ "summary": { "const": "" },
+ "tags": { "type": "string" },
+ "projectUrl": { "type": "string" },
+ "licenseUrl": { "type": "string" },
+ "iconUrl": { "type": "string" },
+ "version": { "type": "string" },
+ "dependencyGroups": {
+ "type": "array",
+ "items": { "$ref": "./dependency_group.json" }
+ }
+ }
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/nuget/packages_metadata.json b/spec/fixtures/api/schemas/public_api/v4/packages/nuget/packages_metadata.json
new file mode 100644
index 00000000000..724df5a437d
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/nuget/packages_metadata.json
@@ -0,0 +1,54 @@
+{
+ "type": "object",
+ "required": ["count", "items"],
+ "properties": {
+ "count": { "const": 0 },
+ "items": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": ["lower", "upper", "count", "items"],
+ "properties": {
+ "lower": { "type": "string" },
+ "upper": { "type": "string" },
+ "count": { "type": "integer" },
+ "items": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": ["@id", "packageContent", "catalogEntry"],
+ "properties": {
+ "@id": { "type": "string" },
+ "packageContent": { "type": "string" },
+ "catalogEntry": {
+ "type": "object",
+ "required": ["@id", "authors", "dependencyGroups", "id", "packageContent", "summary", "version"],
+ "properties": {
+ "@id": { "type": "string" },
+ "authors": { "const": "" },
+ "id": { "type": "string" },
+ "packageContent": { "type": "string" },
+ "summary": { "const": "" },
+ "tags": { "type": "string" },
+ "projectUrl": { "type": "string" },
+ "licenseUrl": { "type": "string" },
+ "iconUrl": { "type": "string" },
+ "version": { "type": "string" },
+ "dependencyGroups": {
+ "type": "array",
+ "items": { "$ref": "./dependency_group.json" }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+
+
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/nuget/search.json b/spec/fixtures/api/schemas/public_api/v4/packages/nuget/search.json
new file mode 100644
index 00000000000..73d0927e24c
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/nuget/search.json
@@ -0,0 +1,39 @@
+{
+ "type": "object",
+ "required": ["totalHits", "data"],
+ "properties": {
+ "totalHits": { "type": "integer" },
+ "data": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": ["@type", "authors", "id", "summary", "title", "totalDownloads", "verified", "versions"],
+ "properties": {
+ "@type": { "const": "Package" },
+ "authors": { "const": "" },
+ "id": { "type": "string" },
+ "summary": { "const": "" },
+ "title": { "type": "string" },
+ "totalDownloads": { "const": 0 },
+ "verified": { "const": true },
+ "tags": { "type": "string" },
+ "projectUrl": { "type": "string" },
+ "licenseUrl": { "type": "string" },
+ "iconUrl": { "type": "string" },
+ "versions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": ["@id", "version", "downloads"],
+ "properties": {
+ "@id": { "type": "string" },
+ "version": { "type": "string" },
+ "downloads": { "const": 0 }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/nuget/service_index.json b/spec/fixtures/api/schemas/public_api/v4/packages/nuget/service_index.json
new file mode 100644
index 00000000000..405018f8c37
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/nuget/service_index.json
@@ -0,0 +1,19 @@
+{
+ "type": "object",
+ "required": ["version", "resources"],
+ "properties": {
+ "version": { "const": "3.0.0" },
+ "resources": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": ["@id", "@type", "comment"],
+ "properties": {
+ "@id": { "type": "string" },
+ "@type": { "type": "string" },
+ "comment": { "type": "string" }
+ }
+ }
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/package.json b/spec/fixtures/api/schemas/public_api/v4/packages/package.json
new file mode 100644
index 00000000000..757e5fd26b6
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/package.json
@@ -0,0 +1,41 @@
+{
+ "type": "object",
+ "required": [
+ "name",
+ "version",
+ "package_type",
+ "_links",
+ "versions"
+ ],
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "version": {
+ "type": "string"
+ },
+ "package_type": {
+ "type": "string"
+ },
+ "_links": {
+ "type": "object",
+ "required": [
+ "web_path"
+ ],
+ "properties": {
+ "details": {
+ "type": "string"
+ }
+ }
+ },
+ "created_at": {
+ "type": "string"
+ },
+ "versions": {
+ "type": "array",
+ "items": {
+ "$ref": "package_version.json"
+ }
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/package_files.json b/spec/fixtures/api/schemas/public_api/v4/packages/package_files.json
new file mode 100644
index 00000000000..f057adba65c
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/package_files.json
@@ -0,0 +1,13 @@
+{
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required" : ["id", "package_id", "file_name"],
+ "properties" : {
+ "id": { "type": "integer" },
+ "package_id": { "type": "integer" },
+ "file_name": { "type": "string" },
+ "file_sha1": { "type": "string" }
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/package_version.json b/spec/fixtures/api/schemas/public_api/v4/packages/package_version.json
new file mode 100644
index 00000000000..72f2a2121ad
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/package_version.json
@@ -0,0 +1,19 @@
+{
+ "type": "object",
+ "required": [
+ "version",
+ "created_at",
+ "pipeline"
+ ],
+ "properties": {
+ "version": {
+ "type": "string"
+ },
+ "created_at": {
+ "type": "string"
+ },
+ "pipeline": {
+ "$ref": "../pipeline.json"
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/package_with_build.json b/spec/fixtures/api/schemas/public_api/v4/packages/package_with_build.json
new file mode 100644
index 00000000000..de3ef94138e
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/package_with_build.json
@@ -0,0 +1,10 @@
+{
+ "type": "object",
+ "required": ["name", "version", "package_type", "pipeline"],
+ "properties": {
+ "name": { "type": "string" },
+ "version": { "type": "string" },
+ "package_type": { "type": "string" },
+ "pipeline": { "$ref": "../pipeline.json" }
+ }
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/packages.json b/spec/fixtures/api/schemas/public_api/v4/packages/packages.json
new file mode 100644
index 00000000000..66364da4fdb
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/packages.json
@@ -0,0 +1,4 @@
+{
+ "type": "array",
+ "items": { "$ref": "./package.json" }
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/pipeline.json b/spec/fixtures/api/schemas/public_api/v4/pipeline.json
new file mode 100644
index 00000000000..f83844a115d
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/pipeline.json
@@ -0,0 +1,27 @@
+{
+ "type": "object",
+ "required": ["id", "sha", "ref", "status", "created_at", "updated_at", "web_url"],
+ "properties": {
+ "id": {
+ "type": "integer"
+ },
+ "sha": {
+ "type": "string"
+ },
+ "ref": {
+ "type": "string"
+ },
+ "status": {
+ "type": "string"
+ },
+ "created_at": {
+ "type": "string"
+ },
+ "updated_at": {
+ "type": "string"
+ },
+ "web_url": {
+ "type": "string"
+ }
+ }
+}
diff --git a/spec/frontend/ide/lib/editor_spec.js b/spec/frontend/ide/lib/editor_spec.js
index 0952facf3ee..5f28309422d 100644
--- a/spec/frontend/ide/lib/editor_spec.js
+++ b/spec/frontend/ide/lib/editor_spec.js
@@ -200,6 +200,20 @@ describe('Multi-file editor library', () => {
});
describe('schemas', () => {
+ let originalGon;
+
+ beforeEach(() => {
+ originalGon = window.gon;
+ window.gon = { features: { schemaLinting: true } };
+
+ delete Editor.editorInstance;
+ instance = Editor.create();
+ });
+
+ afterEach(() => {
+ window.gon = originalGon;
+ });
+
it('registers custom schemas defined with Monaco', () => {
expect(monacoLanguages.yaml.yamlDefaults.diagnosticsOptions).toMatchObject({
schemas: [{ fileMatch: ['*.gitlab-ci.yml'] }],
diff --git a/spec/helpers/operations_helper_spec.rb b/spec/helpers/operations_helper_spec.rb
index 40f92c538e0..7050a7b9290 100644
--- a/spec/helpers/operations_helper_spec.rb
+++ b/spec/helpers/operations_helper_spec.rb
@@ -39,7 +39,8 @@ RSpec.describe OperationsHelper do
'prometheus_authorization_key' => nil,
'prometheus_api_url' => nil,
'prometheus_activated' => 'false',
- 'prometheus_url' => notify_project_prometheus_alerts_url(project, format: :json)
+ 'prometheus_url' => notify_project_prometheus_alerts_url(project, format: :json),
+ 'disabled' => 'false'
)
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/reports_spec.rb b/spec/lib/gitlab/ci/config/entry/reports_spec.rb
index 3a6e228ce97..98105ebcd55 100644
--- a/spec/lib/gitlab/ci/config/entry/reports_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/reports_spec.rb
@@ -46,6 +46,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Reports do
:performance | 'performance.json'
:browser_performance | 'browser-performance.json'
:browser_performance | 'performance.json'
+ :load_performance | 'load-performance.json'
:lsif | 'lsif.json'
:dotenv | 'build.dotenv'
:cobertura | 'cobertura-coverage.xml'
diff --git a/spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb
new file mode 100644
index 00000000000..9711df55226
--- /dev/null
+++ b/spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Verify/Load-Performance-Testing.gitlab-ci.yml' do
+ subject(:template) do
+ <<~YAML
+ stages:
+ - test
+ - performance
+
+ include:
+ - template: 'Verify/Load-Performance-Testing.gitlab-ci.yml'
+
+ placeholder:
+ script:
+ - keep pipeline validator happy by having a job when stages are intentionally empty
+ YAML
+ end
+
+ describe 'the created pipeline' do
+ let(:user) { create(:admin) }
+ let(:project) { create(:project, :repository) }
+
+ let(:default_branch) { 'master' }
+ let(:pipeline_ref) { default_branch }
+ let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_ref) }
+ let(:pipeline) { service.execute!(:push) }
+ let(:build_names) { pipeline.builds.pluck(:name) }
+
+ before do
+ stub_ci_pipeline_yaml_file(template)
+
+ allow_any_instance_of(Ci::BuildScheduleWorker).to receive(:perform).and_return(true)
+ allow(project).to receive(:default_branch).and_return(default_branch)
+ end
+
+ it 'has no errors' do
+ expect(pipeline.errors).to be_empty
+ end
+
+ shared_examples_for 'load_performance job on tag or branch' do
+ it 'by default' do
+ expect(build_names).to include('load_performance')
+ end
+ end
+
+ context 'on master' do
+ it_behaves_like 'load_performance job on tag or branch'
+ end
+
+ context 'on another branch' do
+ let(:pipeline_ref) { 'feature' }
+
+ it_behaves_like 'load_performance job on tag or branch'
+ end
+
+ context 'on tag' do
+ let(:pipeline_ref) { 'v1.0.0' }
+
+ it_behaves_like 'load_performance job on tag or branch'
+ end
+
+ context 'on merge request' do
+ let(:service) { MergeRequests::CreatePipelineService.new(project, user) }
+ let(:merge_request) { create(:merge_request, :simple, source_project: project) }
+ let(:pipeline) { service.execute(merge_request) }
+
+ it 'has no jobs' do
+ expect(pipeline).to be_merge_request_event
+ expect(build_names).to be_empty
+ end
+ end
+ end
+end
diff --git a/spec/models/plan_limits_spec.rb b/spec/models/plan_limits_spec.rb
index 4b67d4f2964..831fd0dcbc3 100644
--- a/spec/models/plan_limits_spec.rb
+++ b/spec/models/plan_limits_spec.rb
@@ -191,6 +191,7 @@ RSpec.describe PlanLimits do
ci_max_artifact_size_license_scanning
ci_max_artifact_size_performance
ci_max_artifact_size_browser_performance
+ ci_max_artifact_size_load_performance
ci_max_artifact_size_metrics
ci_max_artifact_size_metrics_referee
ci_max_artifact_size_network_referee
diff --git a/spec/serializers/pipeline_details_entity_spec.rb b/spec/serializers/pipeline_details_entity_spec.rb
index 55bb9720957..35ce7c7175c 100644
--- a/spec/serializers/pipeline_details_entity_spec.rb
+++ b/spec/serializers/pipeline_details_entity_spec.rb
@@ -157,20 +157,30 @@ RSpec.describe PipelineDetailsEntity do
context 'when pipeline triggered other pipeline' do
let(:pipeline) { create(:ci_empty_pipeline) }
- let(:build) { create(:ci_build, pipeline: pipeline) }
+ let(:build) { create(:ci_build, name: 'child', stage: 'test', pipeline: pipeline) }
+ let(:bridge) { create(:ci_bridge, name: 'cross-project', stage: 'build', pipeline: pipeline) }
+ let(:child_pipeline) { create(:ci_pipeline, project: pipeline.project) }
+ let(:cross_project_pipeline) { create(:ci_pipeline) }
before do
- create(:ci_sources_pipeline, source_job: build)
- create(:ci_sources_pipeline, source_job: build)
+ create(:ci_sources_pipeline, source_job: build, pipeline: child_pipeline)
+ create(:ci_sources_pipeline, source_job: bridge, pipeline: cross_project_pipeline)
end
- it 'contains an information about depedent pipeline' do
+ it 'contains an information about dependent pipeline', :aggregate_failures do
expect(subject[:triggered]).to be_a(Array)
expect(subject[:triggered].length).to eq(2)
expect(subject[:triggered].first[:path]).not_to be_nil
expect(subject[:triggered].first[:details]).not_to be_nil
expect(subject[:triggered].first[:details][:status]).not_to be_nil
expect(subject[:triggered].first[:project]).not_to be_nil
+
+ source_jobs = subject[:triggered]
+ .index_by { |pipeline| pipeline[:id] }
+ .transform_values { |pipeline| pipeline.fetch(:source_job) }
+
+ expect(source_jobs[cross_project_pipeline.id][:name]).to eq('cross-project')
+ expect(source_jobs[child_pipeline.id][:name]).to eq('child')
end
end
end
diff --git a/spec/serializers/pipeline_serializer_spec.rb b/spec/serializers/pipeline_serializer_spec.rb
index cdff5f0e001..c1386ac4eb2 100644
--- a/spec/serializers/pipeline_serializer_spec.rb
+++ b/spec/serializers/pipeline_serializer_spec.rb
@@ -211,6 +211,33 @@ RSpec.describe PipelineSerializer do
end
end
+ context 'with triggered pipelines' do
+ let(:ref) { 'feature' }
+
+ before do
+ pipeline_1 = create(:ci_pipeline)
+ build_1 = create(:ci_build, pipeline: pipeline_1)
+ create(:ci_sources_pipeline, source_job: build_1)
+
+ pipeline_2 = create(:ci_pipeline)
+ build_2 = create(:ci_build, pipeline: pipeline_2)
+ create(:ci_sources_pipeline, source_job: build_2)
+ end
+
+ it 'verifies number of queries', :request_store do
+ recorded = ActiveRecord::QueryRecorder.new { subject }
+
+ # 99 queries by default + 2 related to preloading
+ # :source_pipeline and :source_job
+ # Existing numbers are high and require performance optimization
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/225156
+ expected_queries = Gitlab.ee? ? 101 : 92
+
+ expect(recorded.count).to be_within(2).of(expected_queries)
+ expect(recorded.cached_count).to eq(0)
+ end
+ end
+
def create_pipeline(status)
create(:ci_empty_pipeline,
project: project,
diff --git a/spec/services/ci/retry_build_service_spec.rb b/spec/services/ci/retry_build_service_spec.rb
index 690b6c7b9d4..02fc0fd4a43 100644
--- a/spec/services/ci/retry_build_service_spec.rb
+++ b/spec/services/ci/retry_build_service_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe Ci::RetryBuildService do
job_artifacts_sast job_artifacts_secret_detection job_artifacts_dependency_scanning
job_artifacts_container_scanning job_artifacts_dast
job_artifacts_license_management job_artifacts_license_scanning
- job_artifacts_performance job_artifacts_browser_performance
+ job_artifacts_performance job_artifacts_browser_performance job_artifacts_load_performance
job_artifacts_lsif job_artifacts_terraform job_artifacts_cluster_applications
job_artifacts_codequality job_artifacts_metrics scheduled_at
job_variables waiting_for_resource_at job_artifacts_metrics_referee