Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
1072f96e34
commit
4a72126942
|
@ -21,7 +21,7 @@ the noise (due to constantly failing tests, flaky tests, and so on) so that new
|
|||
- [ ] Quarantine test check-list
|
||||
- [ ] Follow the [Quarantining Tests guide](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#quarantining-tests).
|
||||
- [ ] Confirm the test has a [`quarantine:` tag with the specified quarantine type](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#quarantined-test-types).
|
||||
- [ ] Note if the test should be [quarantined for a specific environment](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/environment_selection.html#quarantining-a-test-for-a-specific-environment).
|
||||
- [ ] Note if the test should be [quarantined for a specific environment](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/execution_context_selection.html#quarantine-a-test-for-a-specific-environment).
|
||||
- [ ] Dequarantine test check-list
|
||||
- [ ] Follow the [Dequarantining Tests guide](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#dequarantining-tests).
|
||||
- [ ] Confirm the test consistently passes on the target GitLab environment(s).
|
||||
|
|
|
@ -162,8 +162,10 @@ export default {
|
|||
<div class="js-pipeline-graph">
|
||||
<div
|
||||
ref="mainPipelineContainer"
|
||||
class="gl-display-flex gl-position-relative gl-bg-gray-10 gl-white-space-nowrap gl-border-t-solid gl-border-t-1 gl-border-gray-100"
|
||||
:class="{ 'gl-pipeline-min-h gl-py-5 gl-overflow-auto': !isLinkedPipeline }"
|
||||
class="gl-display-flex gl-position-relative gl-bg-gray-10 gl-white-space-nowrap"
|
||||
:class="{
|
||||
'gl-pipeline-min-h gl-py-5 gl-overflow-auto gl-border-t-solid gl-border-t-1 gl-border-gray-100': !isLinkedPipeline,
|
||||
}"
|
||||
>
|
||||
<linked-graph-wrapper>
|
||||
<template #upstream>
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Mutations
|
||||
module Security
|
||||
module CiConfiguration
|
||||
class BaseSecurityAnalyzer < BaseMutation
|
||||
include FindsProject
|
||||
|
||||
argument :project_path, GraphQL::ID_TYPE,
|
||||
required: true,
|
||||
description: 'Full path of the project.'
|
||||
|
||||
field :success_path, GraphQL::STRING_TYPE, null: true,
|
||||
description: 'Redirect path to use when the response is successful.'
|
||||
|
||||
field :branch, GraphQL::STRING_TYPE, null: true,
|
||||
description: 'Branch that has the new/modified `.gitlab-ci.yml` file.'
|
||||
|
||||
authorize :push_code
|
||||
|
||||
def resolve(project_path:, **args)
|
||||
project = authorized_find!(project_path)
|
||||
|
||||
result = configure_analyzer(project, **args)
|
||||
prepare_response(result)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def configure_analyzer(project, **args)
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
def prepare_response(result)
|
||||
{
|
||||
branch: result.payload[:branch],
|
||||
success_path: result.payload[:success_path],
|
||||
errors: result.errors
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -3,9 +3,7 @@
|
|||
module Mutations
|
||||
module Security
|
||||
module CiConfiguration
|
||||
class ConfigureSast < BaseMutation
|
||||
include FindsProject
|
||||
|
||||
class ConfigureSast < BaseSecurityAnalyzer
|
||||
graphql_name 'ConfigureSast'
|
||||
description <<~DESC
|
||||
Configure SAST for a project by enabling SAST in a new or modified
|
||||
|
@ -13,37 +11,12 @@ module Mutations
|
|||
create a Merge Request are a part of the response.
|
||||
DESC
|
||||
|
||||
argument :project_path, GraphQL::ID_TYPE,
|
||||
required: true,
|
||||
description: 'Full path of the project.'
|
||||
|
||||
argument :configuration, ::Types::CiConfiguration::Sast::InputType,
|
||||
required: true,
|
||||
description: 'SAST CI configuration for the project.'
|
||||
|
||||
field :success_path, GraphQL::STRING_TYPE, null: true,
|
||||
description: 'Redirect path to use when the response is successful.'
|
||||
|
||||
field :branch, GraphQL::STRING_TYPE, null: true,
|
||||
description: 'Branch that has the new/modified `.gitlab-ci.yml` file.'
|
||||
|
||||
authorize :push_code
|
||||
|
||||
def resolve(project_path:, configuration:)
|
||||
project = authorized_find!(project_path)
|
||||
|
||||
result = ::Security::CiConfiguration::SastCreateService.new(project, current_user, configuration).execute
|
||||
prepare_response(result)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def prepare_response(result)
|
||||
{
|
||||
branch: result.payload[:branch],
|
||||
success_path: result.payload[:success_path],
|
||||
errors: result.errors
|
||||
}
|
||||
def configure_analyzer(project, **args)
|
||||
::Security::CiConfiguration::SastCreateService.new(project, current_user, args[:configuration]).execute
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,9 +3,7 @@
|
|||
module Mutations
|
||||
module Security
|
||||
module CiConfiguration
|
||||
class ConfigureSecretDetection < BaseMutation
|
||||
include FindsProject
|
||||
|
||||
class ConfigureSecretDetection < BaseSecurityAnalyzer
|
||||
graphql_name 'ConfigureSecretDetection'
|
||||
description <<~DESC
|
||||
Configure Secret Detection for a project by enabling Secret Detection
|
||||
|
@ -14,33 +12,8 @@ module Mutations
|
|||
response.
|
||||
DESC
|
||||
|
||||
argument :project_path, GraphQL::ID_TYPE,
|
||||
required: true,
|
||||
description: 'Full path of the project.'
|
||||
|
||||
field :success_path, GraphQL::STRING_TYPE, null: true,
|
||||
description: 'Redirect path to use when the response is successful.'
|
||||
|
||||
field :branch, GraphQL::STRING_TYPE, null: true,
|
||||
description: 'Branch that has the new/modified `.gitlab-ci.yml` file.'
|
||||
|
||||
authorize :push_code
|
||||
|
||||
def resolve(project_path:)
|
||||
project = authorized_find!(project_path)
|
||||
|
||||
result = ::Security::CiConfiguration::SecretDetectionCreateService.new(project, current_user).execute
|
||||
prepare_response(result)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def prepare_response(result)
|
||||
{
|
||||
branch: result.payload[:branch],
|
||||
success_path: result.payload[:success_path],
|
||||
errors: result.errors
|
||||
}
|
||||
def configure_analyzer(project, **_args)
|
||||
::Security::CiConfiguration::SecretDetectionCreateService.new(project, current_user).execute
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -95,7 +95,15 @@ module Types
|
|||
end
|
||||
|
||||
def feature_documentation_message(key, description)
|
||||
"#{description} Available only when feature flag `#{key}` is enabled."
|
||||
message_parts = ["#{description} Available only when feature flag `#{key}` is enabled."]
|
||||
|
||||
message_parts << if Feature::Definition.has_definition?(key) && Feature::Definition.default_enabled?(key)
|
||||
"This flag is enabled by default."
|
||||
else
|
||||
"This flag is disabled by default, because the feature is experimental and is subject to change without notice."
|
||||
end
|
||||
|
||||
message_parts.join(' ')
|
||||
end
|
||||
|
||||
def check_feature_flag(args)
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
= render_if_exists 'shared/pages/max_pages_size_input', form: f
|
||||
|
||||
.gl-mt-3
|
||||
= f.submit s_('GitLabPages|Save'), class: 'btn gl-button btn-confirm'
|
||||
= f.submit s_('GitLabPages|Save changes'), class: 'btn gl-button btn-confirm'
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
= nav_link(path: ['groups#show', 'groups#details'], html_options: { class: 'context-header' }) do
|
||||
= link_to group_path(@group), title: @group.name, data: { qa_selector: 'group_scope_link' } do
|
||||
%span{ class: ['avatar-container', 'rect-avatar', 'group-avatar' , 's32'] }
|
||||
= group_icon(@group, class: ['avatar', 'avatar-tile', 's32'])
|
||||
%span.sidebar-context-title
|
||||
= @group.name
|
|
@ -23,7 +23,7 @@
|
|||
display_path: true,
|
||||
extra_group: namespace_id),
|
||||
{},
|
||||
{ class: 'select2 js-select-namespace qa-project-namespace-select block-truncated', data: { track_label: "#{track_label}", track_event: "activate_form_input", track_property: "project_path", track_value: "" }})
|
||||
{ class: 'select2 js-select-namespace qa-project-namespace-select block-truncated', data: { track_label: "#{track_label}", track_event: "activate_form_input", track_property: "project_path", track_value: "", qa_selector: "select_namespace_dropdown" }})
|
||||
|
||||
- else
|
||||
.input-group-prepend.static-namespace.flex-shrink-0.has-tooltip{ title: user_url(current_user.username) + '/' }
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
- else
|
||||
.form-group
|
||||
= f.label :default_branch, "Default branch", class: 'label-bold'
|
||||
= f.select(:default_branch, @project.repository.branch_names, {}, {class: 'select2 select-wide'})
|
||||
= f.select(:default_branch, @project.repository.branch_names, {}, {class: 'select2 select-wide', data: { qa_selector: 'default_branch_dropdown' }})
|
||||
|
||||
.form-group
|
||||
.form-check
|
||||
|
@ -28,4 +28,4 @@
|
|||
= _("When merge requests and commits in the default branch close, any issues they reference also close.")
|
||||
= link_to sprite_icon('question-o'), help_page_path('user/project/issues/managing_issues.md', anchor: 'disabling-automatic-issue-closing'), target: '_blank'
|
||||
|
||||
= f.submit _('Save changes'), class: "gl-button btn btn-confirm"
|
||||
= f.submit _('Save changes'), class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
= form_for @project, url: project_pages_path(@project), html: { class: 'inline', title: pages_https_only_title } do |f|
|
||||
= render_if_exists 'shared/pages/max_pages_size_input', form: f
|
||||
- if can?(current_user, :update_max_pages_size)
|
||||
= render_if_exists 'shared/pages/max_pages_size_input', form: f
|
||||
.gl-mt-3
|
||||
= f.submit s_('GitLabPages|Save changes'), class: 'btn btn-confirm gl-button'
|
||||
|
||||
- if Gitlab.config.pages.external_http || Gitlab.config.pages.external_https
|
||||
|
||||
|
@ -15,4 +18,4 @@
|
|||
= s_("GitLabPages|When enabled, all attempts to visit your website through HTTP are automatically redirected to HTTPS using a response with status code 301. Requires a valid certificate for all domains. %{docs_link_start}Learn more.%{link_end}").html_safe % { docs_link_start: docs_link_start, link_end: link_end }
|
||||
|
||||
.gl-mt-3
|
||||
= f.submit s_('GitLabPages|Save'), class: 'btn btn-confirm gl-button'
|
||||
= f.submit s_('GitLabPages|Save changes'), class: 'btn btn-confirm gl-button'
|
||||
|
|
|
@ -547,12 +547,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
|
|||
end
|
||||
end
|
||||
|
||||
# TODO: Deprecated. This should be removed in 14.2.
|
||||
scope :usage_ping, controller: :service_ping do
|
||||
post :web_ide_clientside_preview # rubocop:todo Cop/PutProjectRoutesUnderScope
|
||||
post :web_ide_pipelines_count # rubocop:todo Cop/PutProjectRoutesUnderScope
|
||||
end
|
||||
|
||||
scope :service_ping, controller: :service_ping do
|
||||
post :web_ide_clientside_preview # rubocop:todo Cop/PutProjectRoutesUnderScope
|
||||
post :web_ide_pipelines_count # rubocop:todo Cop/PutProjectRoutesUnderScope
|
||||
|
|
|
@ -662,24 +662,27 @@ Follow the steps below to configure the proxy listener of GitLab Pages.
|
|||
|
||||
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
|
||||
|
||||
### Override maximum pages size per project or group **(PREMIUM SELF)**
|
||||
## Override maximum pages size per project or group **(PREMIUM SELF)**
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16610) in GitLab 12.7.
|
||||
|
||||
NOTE:
|
||||
Only GitLab admin users are able to view and override the **Maximum size of Pages** setting.
|
||||
Only GitLab administrators are able to view and override the **Maximum size of Pages** setting.
|
||||
|
||||
To override the global maximum pages size for a specific project:
|
||||
|
||||
1. Go to your project's **Settings > Pages** page.
|
||||
1. Edit the **Maximum size of pages**.
|
||||
1. Click **Save changes**.
|
||||
1. On the top bar, select **Menu > Projects** and find your project.
|
||||
1. On the left sidebar, select **Settings > Pages**.
|
||||
1. Enter a value under **Maximum size of pages** in MB.
|
||||
1. Select **Save changes**.
|
||||
|
||||
To override the global maximum pages size for a specific group:
|
||||
|
||||
1. Go to your group's **Settings > General** page and expand **Pages**.
|
||||
1. Edit the **Maximum size of pages**.
|
||||
1. Click **Save changes**.
|
||||
1. On the top bar, select **Menu > Groups** and find your group.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. Expand **Pages**.
|
||||
1. Enter a value under **Maximum size of pages** in MB.
|
||||
1. Select **Save changes**.
|
||||
|
||||
## Running GitLab Pages on a separate server
|
||||
|
||||
|
|
|
@ -294,7 +294,7 @@ Returns [`QueryComplexity`](#querycomplexity).
|
|||
|
||||
### `Query.runner`
|
||||
|
||||
Find a runner. Available only when feature flag `runner_graphql_query` is enabled.
|
||||
Find a runner. Available only when feature flag `runner_graphql_query` is enabled. This flag is enabled by default.
|
||||
|
||||
Returns [`CiRunner`](#cirunner).
|
||||
|
||||
|
@ -331,7 +331,7 @@ Returns [`RunnerSetup`](#runnersetup).
|
|||
|
||||
### `Query.runners`
|
||||
|
||||
Find runners visible to the current user. Available only when feature flag `runner_graphql_query` is enabled.
|
||||
Find runners visible to the current user. Available only when feature flag `runner_graphql_query` is enabled. This flag is enabled by default.
|
||||
|
||||
Returns [`CiRunnerConnection`](#cirunnerconnection).
|
||||
|
||||
|
@ -1121,7 +1121,7 @@ Input type: `CreateComplianceFrameworkInput`
|
|||
|
||||
### `Mutation.createCustomEmoji`
|
||||
|
||||
Available only when feature flag `custom_emoji` is enabled.
|
||||
Available only when feature flag `custom_emoji` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice.
|
||||
|
||||
Input type: `CreateCustomEmojiInput`
|
||||
|
||||
|
@ -3618,7 +3618,7 @@ Input type: `RepositionImageDiffNoteInput`
|
|||
|
||||
### `Mutation.runnerDelete`
|
||||
|
||||
Available only when feature flag `runner_graphql_query` is enabled.
|
||||
Available only when feature flag `runner_graphql_query` is enabled. This flag is enabled by default.
|
||||
|
||||
Input type: `RunnerDeleteInput`
|
||||
|
||||
|
@ -3638,7 +3638,7 @@ Input type: `RunnerDeleteInput`
|
|||
|
||||
### `Mutation.runnerUpdate`
|
||||
|
||||
Available only when feature flag `runner_graphql_query` is enabled.
|
||||
Available only when feature flag `runner_graphql_query` is enabled. This flag is enabled by default.
|
||||
|
||||
Input type: `RunnerUpdateInput`
|
||||
|
||||
|
@ -3668,7 +3668,7 @@ Input type: `RunnerUpdateInput`
|
|||
|
||||
### `Mutation.runnersRegistrationTokenReset`
|
||||
|
||||
Available only when feature flag `runner_graphql_query` is enabled.
|
||||
Available only when feature flag `runner_graphql_query` is enabled. This flag is enabled by default.
|
||||
|
||||
Input type: `RunnersRegistrationTokenResetInput`
|
||||
|
||||
|
@ -8552,7 +8552,7 @@ Snapshot.
|
|||
| <a id="devopsadoptionsnapshotrecordedat"></a>`recordedAt` | [`Time!`](#time) | The time the snapshot was recorded. |
|
||||
| <a id="devopsadoptionsnapshotrunnerconfigured"></a>`runnerConfigured` | [`Boolean!`](#boolean) | At least one runner was used. |
|
||||
| <a id="devopsadoptionsnapshotsastenabledcount"></a>`sastEnabledCount` | [`Int`](#int) | Total number of projects with enabled SAST. |
|
||||
| <a id="devopsadoptionsnapshotsecurityscansucceeded"></a>`securityScanSucceeded` | [`Boolean!`](#boolean) | At least one security scan succeeded. |
|
||||
| <a id="devopsadoptionsnapshotsecurityscansucceeded"></a>`securityScanSucceeded` **{warning-solid}** | [`Boolean!`](#boolean) | **Deprecated** in 14.1. Substituted with specific security metrics. Always false. |
|
||||
| <a id="devopsadoptionsnapshotstarttime"></a>`startTime` | [`Time!`](#time) | The start time for the snapshot where the data points were collected. |
|
||||
| <a id="devopsadoptionsnapshottotalprojectscount"></a>`totalProjectsCount` | [`Int`](#int) | Total number of projects. |
|
||||
| <a id="devopsadoptionsnapshotvulnerabilitymanagementusedcount"></a>`vulnerabilityManagementUsedCount` | [`Int`](#int) | Total number of projects with vulnerability management used at least once. |
|
||||
|
@ -9271,7 +9271,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
|
|||
| <a id="groupbillablememberscount"></a>`billableMembersCount` | [`Int`](#int) | The number of billable users in the group. |
|
||||
| <a id="groupcontainerrepositoriescount"></a>`containerRepositoriesCount` | [`Int!`](#int) | Number of container repositories in the group. |
|
||||
| <a id="groupcontainslockedprojects"></a>`containsLockedProjects` | [`Boolean!`](#boolean) | Includes at least one project where the repository size exceeds the limit. |
|
||||
| <a id="groupcustomemoji"></a>`customEmoji` | [`CustomEmojiConnection`](#customemojiconnection) | Custom emoji within this namespace. Available only when feature flag `custom_emoji` is enabled. (see [Connections](#connections)) |
|
||||
| <a id="groupcustomemoji"></a>`customEmoji` | [`CustomEmojiConnection`](#customemojiconnection) | Custom emoji within this namespace. Available only when feature flag `custom_emoji` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice. (see [Connections](#connections)) |
|
||||
| <a id="groupdescription"></a>`description` | [`String`](#string) | Description of the namespace. |
|
||||
| <a id="groupdescriptionhtml"></a>`descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
|
||||
| <a id="groupdora"></a>`dora` | [`Dora`](#dora) | The group's DORA metrics. |
|
||||
|
|
|
@ -1,89 +1,8 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
|
||||
redirect_to: 'execution_context_selection.md'
|
||||
---
|
||||
|
||||
# Environment selection
|
||||
This file was moved to [another location](execution_context_selection.md).
|
||||
|
||||
Some tests are designed to be run against specific environments or [pipelines](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#scheduled-qa-test-pipelines).
|
||||
We can specify what environments or pipelines to run tests against using the `only` metadata.
|
||||
|
||||
## Available switches
|
||||
|
||||
| Switch | Function | Type |
|
||||
| -------| ------- | ----- |
|
||||
| `tld` | Set the top-level domain matcher | `String` |
|
||||
| `subdomain` | Set the subdomain matcher | `Array` or `String` |
|
||||
| `domain` | Set the domain matcher | `String` |
|
||||
| `production` | Match against production | `Static` |
|
||||
| `pipeline` | Match against a pipeline | `Array` or `Static`|
|
||||
|
||||
WARNING:
|
||||
You cannot specify `:production` and `{ <switch>: 'value' }` simultaneously.
|
||||
These options are mutually exclusive. If you want to specify production, you
|
||||
can control the `tld` and `domain` independently.
|
||||
|
||||
## Examples
|
||||
|
||||
| Environment or pipeline | Key | Matches (regex for environments, string matching for pipelines) |
|
||||
| ---------------- | --- | --------------- |
|
||||
| `any` | `` | `.+.com` |
|
||||
| `gitlab.com` | `only: :production` | `gitlab.com` |
|
||||
| `staging.gitlab.com` | `only: { subdomain: :staging }` | `(staging).+.com` |
|
||||
| `gitlab.com and staging.gitlab.com` | `only: { subdomain: /(staging.)?/, domain: 'gitlab' }` | `(staging.)?gitlab.com` |
|
||||
| `dev.gitlab.org` | `only: { tld: '.org', domain: 'gitlab', subdomain: 'dev' }` | `(dev).gitlab.org` |
|
||||
| `staging.gitlab.com & domain.gitlab.com` | `only: { subdomain: %i[staging domain] }` | `(staging|domain).+.com` |
|
||||
| `nightly` | `only: { pipeline: :nightly }` | "nightly" |
|
||||
| `nightly`, `canary` | `only: { pipeline: [:nightly, :canary] }` | ["nightly"](https://gitlab.com/gitlab-org/quality/nightly) and ["canary"](https://gitlab.com/gitlab-org/quality/canary) |
|
||||
|
||||
```ruby
|
||||
RSpec.describe 'Area' do
|
||||
it 'runs in any environment or pipeline' do; end
|
||||
|
||||
it 'runs only in production environment', only: :production do; end
|
||||
|
||||
it 'runs only in staging environment', only: { subdomain: :staging } do; end
|
||||
|
||||
it 'runs in dev environment', only: { tld: '.org', domain: 'gitlab', subdomain: 'dev' } do; end
|
||||
|
||||
it 'runs in prod and staging environments', only: { subdomain: /(staging.)?/, domain: 'gitlab' } {}
|
||||
|
||||
it 'runs only in nightly pipeline', only: { pipeline: :nightly } do; end
|
||||
|
||||
it 'runs in nightly and canary pipelines', only: { pipeline: [:nightly, :canary] } do; end
|
||||
end
|
||||
```
|
||||
|
||||
If the test has a `before` or `after`, you must add the `only` metadata
|
||||
to the outer `RSpec.describe`.
|
||||
|
||||
If you want to run an `only: { :pipeline }` tagged test on your local GDK make sure either the `CI_PROJECT_NAME` CI/CD variable is unset, or that the `CI_PROJECT_NAME` variable matches the specified pipeline in the `only: { :pipeline }` tag, or just delete the `only: { :pipeline }` tag.
|
||||
|
||||
## Quarantining a test for a specific environment
|
||||
|
||||
Similarly to specifying that a test should only run against a specific environment, it's also possible to quarantine a
|
||||
test only when it runs against a specific environment. The syntax is exactly the same, except that the `only: { ... }`
|
||||
hash is nested in the [`quarantine: { ... }`](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#quarantining-tests) hash.
|
||||
For instance, `quarantine: { only: { subdomain: :staging } }` only quarantines the test when run against staging.
|
||||
|
||||
## Excluding a test from running in a particular job
|
||||
|
||||
Sometimes we need to skip a test in a particular job but allow it to run in other jobs of the same pipeline or environment.
|
||||
We can do it with the help of `exclude` metadata.
|
||||
|
||||
Examples:
|
||||
|
||||
```ruby
|
||||
RSpec.describe 'Excluding' do
|
||||
it 'skips given a single named job', exclude: { job: 'ee:instance-image' } do; end
|
||||
|
||||
it 'skips given a single regex pattern', exclude: { job: '.*:instance-image' } do; end
|
||||
|
||||
it 'skips given an array of jobs', exclude: { job: %w[ee:instance-image qa-schedules-browser_ui-3_create] } do; end
|
||||
|
||||
it 'skips given an array of regex patterns', exclude: { job: %w[ee:.* qa-schedules-browser_ui.*] } do; end
|
||||
|
||||
it 'skips given a mix of strings and regex patterns', exclude: { job: %w[ee:instance-image qa-schedules-browser_ui.*] } do; end
|
||||
end
|
||||
```
|
||||
<!-- This redirect file can be deleted after <2021-08-14>. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
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
|
||||
---
|
||||
|
||||
# Execution context selection
|
||||
|
||||
Some tests are designed to be run against specific environments, or in specific [pipelines](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#scheduled-qa-test-pipelines) or jobs. We can specify the test execution context using the `only` and `except` metadata.
|
||||
|
||||
## Available switches
|
||||
|
||||
| Switch | Function | Type |
|
||||
| -------| ------- | ----- |
|
||||
| `tld` | Set the top-level domain matcher | `String` |
|
||||
| `subdomain` | Set the subdomain matcher | `Array` or `String` |
|
||||
| `domain` | Set the domain matcher | `String` |
|
||||
| `production` | Match the production environment | `Static` |
|
||||
| `pipeline` | Match a pipeline | `Array` or `Static`|
|
||||
| `job` | Match a job | `Array` or `Static`|
|
||||
|
||||
WARNING:
|
||||
You cannot specify `:production` and `{ <switch>: 'value' }` simultaneously.
|
||||
These options are mutually exclusive. If you want to specify production, you
|
||||
can control the `tld` and `domain` independently.
|
||||
|
||||
## Examples
|
||||
|
||||
### Only
|
||||
|
||||
Run tests in only the specified context.
|
||||
|
||||
Matches use:
|
||||
|
||||
- Regex for environments.
|
||||
- String matching for pipelines.
|
||||
- Regex or string matching for jobs.
|
||||
|
||||
| Test execution context | Key | Matches |
|
||||
| ---------------- | --- | --------------- |
|
||||
| `gitlab.com` | `only: :production` | `gitlab.com` |
|
||||
| `staging.gitlab.com` | `only: { subdomain: :staging }` | `(staging).+.com` |
|
||||
| `gitlab.com and staging.gitlab.com` | `only: { subdomain: /(staging.)?/, domain: 'gitlab' }` | `(staging.)?gitlab.com` |
|
||||
| `dev.gitlab.org` | `only: { tld: '.org', domain: 'gitlab', subdomain: 'dev' }` | `(dev).gitlab.org` |
|
||||
| `staging.gitlab.com and domain.gitlab.com` | `only: { subdomain: %i[staging domain] }` | `(staging\|domain).+.com` |
|
||||
| The `nightly` pipeline | `only: { pipeline: :nightly }` | "nightly" |
|
||||
| The `nightly` and `canary` pipelines | `only: { pipeline: [:nightly, :canary] }` | ["nightly"](https://gitlab.com/gitlab-org/quality/nightly) and ["canary"](https://gitlab.com/gitlab-org/quality/canary) |
|
||||
| The `ee:instance` job | `only: { job: 'ee:instance' }` | The `ee:instance` job in any pipeline |
|
||||
| Any `quarantine` job | `only: { job: '.*quarantine' }` | Any job ending in `quarantine` in any pipeline |
|
||||
|
||||
```ruby
|
||||
RSpec.describe 'Area' do
|
||||
it 'runs in any environment or pipeline' do; end
|
||||
it 'runs only in production environment', only: :production do; end
|
||||
|
||||
it 'runs only in staging environment', only: { subdomain: :staging } do; end
|
||||
|
||||
it 'runs in dev environment', only: { tld: '.org', domain: 'gitlab', subdomain: 'dev' } do; end
|
||||
|
||||
it 'runs in prod and staging environments', only: { subdomain: /(staging.)?/, domain: 'gitlab' } {}
|
||||
|
||||
it 'runs only in nightly pipeline', only: { pipeline: :nightly } do; end
|
||||
|
||||
it 'runs in nightly and canary pipelines', only: { pipeline: [:nightly, :canary] } do; end
|
||||
end
|
||||
```
|
||||
|
||||
### Except
|
||||
|
||||
Run tests in their typical contexts _except_ as specified.
|
||||
|
||||
Matches use:
|
||||
|
||||
- Regex for environments.
|
||||
- String matching for pipelines.
|
||||
- Regex or string matching for jobs.
|
||||
|
||||
| Test execution context | Key | Matches |
|
||||
| ---------------- | --- | --------------- |
|
||||
| `gitlab.com` | `except: :production` | `gitlab.com` |
|
||||
| `staging.gitlab.com` | `except: { subdomain: :staging }` | `(staging).+.com` |
|
||||
| `gitlab.com and staging.gitlab.com` | `except: { subdomain: /(staging.)?/, domain: 'gitlab' }` | `(staging.)?gitlab.com` |
|
||||
| `dev.gitlab.org` | `except: { tld: '.org', domain: 'gitlab', subdomain: 'dev' }` | `(dev).gitlab.org` |
|
||||
| `staging.gitlab.com and domain.gitlab.com` | `except: { subdomain: %i[staging domain] }` | `(staging\|domain).+.com` |
|
||||
| The `nightly` pipeline | `except: { pipeline: :nightly }` | ["nightly"](https://gitlab.com/gitlab-org/quality/nightly) |
|
||||
| The `nightly` and `canary` pipelines | `except: { pipeline: [:nightly, :canary] }` | ["nightly"](https://gitlab.com/gitlab-org/quality/nightly) and ["canary"](https://gitlab.com/gitlab-org/quality/canary) |
|
||||
| The `ee:instance` job | `except: { job: 'ee:instance' }` | The `ee:instance` job in any pipeline |
|
||||
| Any `quarantine` job | `except: { job: '.*quarantine' }` | Any job ending in `quarantine` in any pipeline |
|
||||
|
||||
```ruby
|
||||
RSpec.describe 'Area' do
|
||||
it 'runs in any execution context except the production environment', except: :production do; end
|
||||
|
||||
it 'runs in any execution context except the staging environment', except: { subdomain: :staging } do; end
|
||||
|
||||
it 'runs in any execution context except the nightly pipeline', except: { pipeline: :nightly } do; end
|
||||
|
||||
it 'runs in any execution context except the ee:instance job', except: { job: 'ee:instance' } do; end
|
||||
end
|
||||
```
|
||||
|
||||
## Usage notes
|
||||
|
||||
If the test has a `before` or `after` block, you must add the `only` or `except` metadata to the outer `RSpec.describe` block.
|
||||
|
||||
To run a test tagged with `only` on your local GitLab instance, you can do one of the following:
|
||||
|
||||
- Make sure you **do not** have the `CI_PROJECT_NAME` or `CI_JOB_NAME` environment variables set.
|
||||
- Set the appropriate variable to match the metadata. For example, if the metadata is `only: { pipeline: :nightly }` then set `CI_PROJECT_NAME=nightly`. If the metadata is `only: { job: 'ee:instance' }` then set `CI_JOB_NAME=ee:instance`.
|
||||
- Temporarily remove the metadata.
|
||||
|
||||
To run a test tagged with `except` locally, you can either:
|
||||
|
||||
- Make sure you **do not** have the `CI_PROJECT_NAME` or `CI_JOB_NAME` environment variables set.
|
||||
- Temporarily remove the metadata.
|
||||
|
||||
## Quarantine a test for a specific environment
|
||||
|
||||
Similarly to specifying that a test should only run against a specific environment, it's also possible to quarantine a
|
||||
test only when it runs against a specific environment. The syntax is exactly the same, except that the `only: { ... }`
|
||||
hash is nested in the [`quarantine: { ... }`](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#quarantining-tests) hash.
|
||||
For example, `quarantine: { only: { subdomain: :staging } }` only quarantines the test when run against `staging`.
|
|
@ -212,6 +212,7 @@ Continued reading:
|
|||
- [Testing with feature flags](feature_flags.md)
|
||||
- [Flows](flows.md)
|
||||
- [RSpec metadata/tags](rspec_metadata_tests.md)
|
||||
- [Execution context selection](execution_context_selection.md)
|
||||
|
||||
## Where can I ask for help?
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ This is a partial list of the [RSpec metadata](https://relishapp.com/rspec/rspec
|
|||
| Tag | Description |
|
||||
|-----|-------------|
|
||||
| `:elasticsearch` | The test requires an Elasticsearch service. It is used by the [instance-level scenario](https://gitlab.com/gitlab-org/gitlab-qa#definitions) [`Test::Integration::Elasticsearch`](https://gitlab.com/gitlab-org/gitlab/-/blob/72b62b51bdf513e2936301cb6c7c91ec27c35b4d/qa/qa/ee/scenario/test/integration/elasticsearch.rb) to include only tests that require Elasticsearch. |
|
||||
| `:exclude` | The test is excluded from running in a specific job. See [Environment selection](environment_selection.md#excluding-a-test-from-running-in-a-particular-job) for more information. |
|
||||
| `:except` | The test is to be run in their typical execution contexts _except_ as specified. See [test execution context selection](execution_context_selection.md) for more information. |
|
||||
| `:geo` | The test requires two GitLab Geo instances - a primary and a secondary - to be spun up. |
|
||||
| `:gitaly_cluster` | The test runs against a GitLab instance where repositories are stored on redundant Gitaly nodes behind a Praefect node. All nodes are [separate containers](../../../administration/gitaly/praefect.md#requirements-for-configuring-a-gitaly-cluster). Tests that use this tag have a longer setup time since there are three additional containers that need to be started. |
|
||||
| `:github` | The test requires a GitHub personal access token. |
|
||||
|
@ -27,10 +27,10 @@ This is a partial list of the [RSpec metadata](https://relishapp.com/rspec/rspec
|
|||
| `:ldap_tls` | The test requires a GitLab instance to be configured to use an external LDAP server with TLS enabled. |
|
||||
| `:mattermost` | The test requires a GitLab Mattermost service on the GitLab instance. |
|
||||
| `:object_storage` | The test requires a GitLab instance to be configured to use multiple [object storage types](../../../administration/object_storage.md). Uses MinIO as the object storage server. |
|
||||
| `:only` | The test is only to be run against specific environments or pipelines. See [Environment selection](environment_selection.md) for more information. |
|
||||
| `:only` | The test is only to be run in specific execution contexts. See [test execution context selection](execution_context_selection.md) for more information. |
|
||||
| `:orchestrated` | The GitLab instance under test may be [configured by `gitlab-qa`](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/docs/what_tests_can_be_run.md#orchestrated-tests) to be different to the default GitLab configuration, or `gitlab-qa` may launch additional services in separate Docker containers, or both. Tests tagged with `:orchestrated` are excluded when testing environments where we can't dynamically modify the GitLab configuration (for example, Staging). |
|
||||
| `:packages` | The test requires a GitLab instance that has the [Package Registry](../../../administration/packages/#gitlab-package-registry-administration) enabled. |
|
||||
| `:quarantine` | The test has been [quarantined](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#quarantining-tests), runs in a separate job that only includes quarantined tests, and is allowed to fail. The test is skipped in its regular job so that if it fails it doesn't hold up the pipeline. Note that you can also [quarantine a test only when it runs against specific environment](environment_selection.md#quarantining-a-test-for-a-specific-environment). |
|
||||
| `:quarantine` | The test has been [quarantined](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#quarantining-tests), runs in a separate job that only includes quarantined tests, and is allowed to fail. The test is skipped in its regular job so that if it fails it doesn't hold up the pipeline. Note that you can also [quarantine a test only when it runs in a specific context](execution_context_selection.md#quarantine-a-test-for-a-specific-environment). |
|
||||
| `:relative_url` | The test requires a GitLab instance to be installed under a [relative URL](../../../install/relative_url.md). |
|
||||
| `:reliable` | The test has been [promoted to a reliable test](https://about.gitlab.com/handbook/engineering/quality/guidelines/reliable-tests/#promoting-an-existing-test-to-reliable) meaning it passes consistently in all pipelines, including merge requests. |
|
||||
| `:repository_storage` | The test requires a GitLab instance to be configured to use multiple [repository storage paths](../../../administration/repository_storage_paths.md). Paired with the `:orchestrated` tag. |
|
||||
|
|
|
@ -22436,7 +22436,7 @@ Group: `group::monitor`
|
|||
|
||||
Data Category: `Optional`
|
||||
|
||||
Status: `data_available`
|
||||
Status: `deprecated`
|
||||
|
||||
Tiers: `premium`, `ultimate`
|
||||
|
||||
|
|
|
@ -57,7 +57,6 @@ DevOps Adoption shows you which groups in your organization are using the most e
|
|||
- Sec
|
||||
- DAST
|
||||
- SAST
|
||||
- Scans
|
||||
- Ops
|
||||
- Deployments
|
||||
- Pipelines
|
||||
|
|
|
@ -7,7 +7,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
# GitLab Kubernetes Agent **(PREMIUM)**
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/223061) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.4.
|
||||
> - [In GitLab 13.10](https://gitlab.com/gitlab-org/gitlab/-/issues/300960), KAS became available on GitLab.com under `wss://kas.gitlab.com` through an Early Adopter Program.
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/issues/7) in GitLab 13.6, `grpcs` is supported.
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/300960) in GitLab 13.10, KAS became available on GitLab.com under `wss://kas.gitlab.com` through an Early Adopter Program.
|
||||
> - Introduced in GitLab 13.11, the GitLab Kubernetes Agent became available to every project on GitLab.com.
|
||||
|
||||
The [GitLab Kubernetes Agent](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent)
|
||||
|
@ -249,12 +250,11 @@ example [`resources.yml` file](#example-resourcesyml-file) in the following ways
|
|||
- Specify the `grpc` scheme if both Agent and Server are installed in one cluster.
|
||||
In this case, you may specify `kas-address` value as
|
||||
`grpc://gitlab-kas.<your-namespace>:8150`) to use gRPC directly, where `gitlab-kas`
|
||||
is the name of the service created by `gitlab-kas` chart, and `your-namespace`
|
||||
is the namespace where the chart was installed. Encrypted gRPC is not supported yet.
|
||||
Follow the
|
||||
[Support TLS for gRPC communication issue](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/issues/7)
|
||||
for progress updates.
|
||||
- When deploying KAS through the [GitLab chart](https://docs.gitlab.com/charts/), it's possible to customize the `kas-address` for `wss` and `ws` schemes to whatever you need.
|
||||
is the name of the service created by `gitlab-kas` chart, and `<your-namespace>`
|
||||
is the namespace where the chart was installed.
|
||||
- Specify the `grpcs` scheme to use an encrypted gRPC connection.
|
||||
- When deploying KAS through the [GitLab chart](https://docs.gitlab.com/charts/), it's possible to customize the
|
||||
`kas-address` for `wss` and `ws` schemes to whatever you need.
|
||||
Check the [chart's KAS Ingress documentation](https://docs.gitlab.com/charts/charts/gitlab/kas/#ingress)
|
||||
to learn more about it.
|
||||
- In the near future, Omnibus GitLab intends to provision `gitlab-kas` under a sub-domain by default, instead of the `/-/kubernetes-agent/` path. Please follow [this issue](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5784) for details.
|
||||
|
|
|
@ -27,7 +27,6 @@ Group DevOps Adoption shows you how individual groups and sub-groups within your
|
|||
- Sec
|
||||
- DAST
|
||||
- SAST
|
||||
- Scans
|
||||
- Ops
|
||||
- Deployments
|
||||
- Pipelines
|
||||
|
|
|
@ -6,14 +6,12 @@ group: Project Management
|
|||
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
|
||||
---
|
||||
|
||||
# Time Tracking **(FREE)**
|
||||
# Time tracking **(FREE)**
|
||||
|
||||
Time Tracking allows you to track estimates and time spent on issues and merge
|
||||
requests within GitLab.
|
||||
With time tracking you can track estimates and time spent on issues and merge
|
||||
requests in GitLab.
|
||||
|
||||
## Overview
|
||||
|
||||
Time Tracking allows you to:
|
||||
Use time tracking for these tasks:
|
||||
|
||||
- Record the time spent working on an issue or a merge request.
|
||||
- Add an estimate of the amount of time needed to complete an issue or a merge
|
||||
|
@ -22,14 +20,13 @@ Time Tracking allows you to:
|
|||
|
||||
You don't have to indicate an estimate to enter the time spent, and vice versa.
|
||||
|
||||
Data about time tracking is shown on the issue/merge request sidebar, as shown
|
||||
below.
|
||||
Data about time tracking shows up on the issue and merge request sidebar:
|
||||
|
||||
![Time tracking in the sidebar](img/time_tracking_sidebar_v13_12.png)
|
||||
|
||||
## How to enter data
|
||||
|
||||
Time Tracking uses two [quick actions](quick_actions.md): `/spend` and `/estimate`.
|
||||
Time tracking uses two [quick actions](quick_actions.md): `/spend` and `/estimate`.
|
||||
|
||||
If you use either quick action more than once in a single comment, only the last occurrence is applied.
|
||||
|
||||
|
@ -42,9 +39,10 @@ with [Reporter and higher permission levels](../permissions.md).
|
|||
|
||||
### Estimates
|
||||
|
||||
To enter an estimate, write `/estimate`, followed by the time. For example, if
|
||||
you need to enter an estimate of 1 month, 2 weeks, 3 days, 4 hours and 5 minutes,
|
||||
write `/estimate 1mo 2w 3d 4h 5m`.
|
||||
To enter an estimate, type `/estimate`, followed by the time.
|
||||
|
||||
For example, if you need to enter an estimate of 1 month, 2 weeks, 3 days, 4 hours, and 5 minutes,
|
||||
type `/estimate 1mo 2w 3d 4h 5m`.
|
||||
Check the [time units you can use](#configuration).
|
||||
|
||||
Every time you enter a new time estimate, any previous time estimates are
|
||||
|
@ -55,21 +53,22 @@ To remove an estimation entirely, use `/remove_estimate`.
|
|||
|
||||
### Time spent
|
||||
|
||||
To enter time spent, write `/spend`, followed by the time. For example, if you need
|
||||
to log 1 month, 2 weeks, 3 days, 4 hours and 5 minutes, you would write `/spend 1mo 2w 3d 4h 5m`.
|
||||
Time units that we support are listed at the bottom of this help page.
|
||||
To enter time spent, type `/spend`, followed by the time.
|
||||
|
||||
For example, if you need
|
||||
to log 1 month, 2 weeks, 3 days, 4 hours, and 5 minutes, type `/spend 1mo 2w 3d 4h 5m`.
|
||||
Check the [time units you can use](#configuration).
|
||||
|
||||
Every new time spent entry is added to the current total time spent for the
|
||||
issue or the merge request.
|
||||
|
||||
You can remove time by entering a negative amount: for example, `/spend -3d` removes three
|
||||
To subtract time, enter a negative value. For example, `/spend -3d` removes three
|
||||
days from the total time spent. You can't go below 0 minutes of time spent,
|
||||
so GitLab automatically resets the time spent if you remove a larger amount
|
||||
of time compared to the time that was entered already.
|
||||
so if you remove more time than already entered, GitLab ignores the subtraction.
|
||||
|
||||
You can log time in the past by providing a date after the time.
|
||||
For example, if you want to log 1 hour of time spent on the 31 January 2021,
|
||||
you would write `/spend 1h 2021-01-31`. If you supply a date in the future, the
|
||||
you would type `/spend 1h 2021-01-31`. If you supply a date in the future, the
|
||||
command fails and no time is logged.
|
||||
|
||||
To remove all the time spent at once, use `/remove_time_spent`.
|
||||
|
@ -95,13 +94,13 @@ The breakdown of spent time is limited to a maximum of 100 entries.
|
|||
|
||||
The following time units are available:
|
||||
|
||||
- Months (mo)
|
||||
- Weeks (w)
|
||||
- Days (d)
|
||||
- Hours (h)
|
||||
- Minutes (m)
|
||||
|
||||
Default conversion rates are 1mo = 4w, 1w = 5d and 1d = 8h.
|
||||
| Time unit | What to type | Default conversion rate |
|
||||
| --------- | ------------ | ----------------------- |
|
||||
| Month | `mo` | 4w |
|
||||
| Week | `w` | 5d |
|
||||
| Day | `d` | 8h |
|
||||
| Hour | `h` | 60m |
|
||||
| Minute | `m` | |
|
||||
|
||||
### Limit displayed units to hours **(FREE SELF)**
|
||||
|
||||
|
@ -119,11 +118,11 @@ To do so:
|
|||
|
||||
With this option enabled, `75h` is displayed instead of `1w 4d 3h`.
|
||||
|
||||
## Other interesting links
|
||||
## Related links
|
||||
|
||||
- [Time Tracking solutions page](https://about.gitlab.com/solutions/time-tracking/)
|
||||
- Time Tracking GraphQL references:
|
||||
- [Time tracking solutions page](https://about.gitlab.com/solutions/time-tracking/)
|
||||
- Time tracking GraphQL references:
|
||||
- [Connection](../../api/graphql/reference/index.md#timelogconnection)
|
||||
- [Edge](../../api/graphql/reference/index.md#timelogedge)
|
||||
- [Fields](../../api/graphql/reference/index.md#timelog)
|
||||
- [Group Timelogs](../../api/graphql/reference/index.md#grouptimelogs)
|
||||
- [Group timelogs](../../api/graphql/reference/index.md#grouptimelogs)
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Sidebars
|
||||
module Groups
|
||||
module Menus
|
||||
class ScopeMenu < ::Sidebars::Menu
|
||||
override :link
|
||||
def link
|
||||
group_path(context.group)
|
||||
end
|
||||
|
||||
override :title
|
||||
def title
|
||||
context.group.name
|
||||
end
|
||||
|
||||
override :active_routes
|
||||
def active_routes
|
||||
{ path: %w[groups#show groups#details] }
|
||||
end
|
||||
|
||||
override :extra_nav_link_html_options
|
||||
def extra_nav_link_html_options
|
||||
{ class: 'context-header' }
|
||||
end
|
||||
|
||||
override :render?
|
||||
def render?
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -3,9 +3,9 @@
|
|||
module Sidebars
|
||||
module Groups
|
||||
class Panel < ::Sidebars::Panel
|
||||
override :render_raw_scope_menu_partial
|
||||
def render_raw_scope_menu_partial
|
||||
'layouts/nav/sidebar/group_scope_menu'
|
||||
override :configure_menus
|
||||
def configure_menus
|
||||
set_scope_menu(Sidebars::Groups::Menus::ScopeMenu.new(context))
|
||||
end
|
||||
|
||||
override :render_raw_menus_partial
|
||||
|
|
|
@ -11324,9 +11324,6 @@ msgstr ""
|
|||
msgid "DevopsAdoption|At least one pipeline successfully run"
|
||||
msgstr ""
|
||||
|
||||
msgid "DevopsAdoption|At least one security scan of any type run in pipeline"
|
||||
msgstr ""
|
||||
|
||||
msgid "DevopsAdoption|Code owners"
|
||||
msgstr ""
|
||||
|
||||
|
@ -11393,9 +11390,6 @@ msgstr ""
|
|||
msgid "DevopsAdoption|SAST enabled for at least one project"
|
||||
msgstr ""
|
||||
|
||||
msgid "DevopsAdoption|Scanning"
|
||||
msgstr ""
|
||||
|
||||
msgid "DevopsAdoption|Sec"
|
||||
msgstr ""
|
||||
|
||||
|
@ -15151,7 +15145,7 @@ msgstr ""
|
|||
msgid "GitLabPages|Removing pages will prevent them from being exposed to the outside world."
|
||||
msgstr ""
|
||||
|
||||
msgid "GitLabPages|Save"
|
||||
msgid "GitLabPages|Save changes"
|
||||
msgstr ""
|
||||
|
||||
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
|
||||
|
@ -15922,6 +15916,9 @@ msgstr ""
|
|||
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
|
||||
msgstr ""
|
||||
|
||||
|
@ -30399,9 +30396,6 @@ msgstr ""
|
|||
msgid "Size limit per repository (MB)"
|
||||
msgstr ""
|
||||
|
||||
msgid "Size settings for static websites"
|
||||
msgstr ""
|
||||
|
||||
msgid "Skip outdated deployment jobs"
|
||||
msgstr ""
|
||||
|
||||
|
|
3
qa/qa.rb
3
qa/qa.rb
|
@ -79,6 +79,7 @@ module QA
|
|||
autoload :GroupLabel, 'qa/resource/group_label'
|
||||
autoload :MergeRequest, 'qa/resource/merge_request'
|
||||
autoload :ProjectImportedFromGithub, 'qa/resource/project_imported_from_github'
|
||||
autoload :ProjectImportedFromURL, 'qa/resource/project_imported_from_url'
|
||||
autoload :MergeRequestFromFork, 'qa/resource/merge_request_from_fork'
|
||||
autoload :DeployKey, 'qa/resource/deploy_key'
|
||||
autoload :DeployToken, 'qa/resource/deploy_token'
|
||||
|
@ -290,6 +291,7 @@ module QA
|
|||
|
||||
module Import
|
||||
autoload :Github, 'qa/page/project/import/github'
|
||||
autoload :RepoByURL, 'qa/page/project/import/repo_by_url'
|
||||
end
|
||||
|
||||
module Pipeline
|
||||
|
@ -337,6 +339,7 @@ module QA
|
|||
autoload :MergeRequest, 'qa/page/project/settings/merge_request'
|
||||
autoload :MirroringRepositories, 'qa/page/project/settings/mirroring_repositories'
|
||||
autoload :ProtectedTags, 'qa/page/project/settings/protected_tags'
|
||||
autoload :DefaultBranch, 'qa/page/project/settings/default_branch'
|
||||
autoload :VisibilityFeaturesPermissions, 'qa/page/project/settings/visibility_features_permissions'
|
||||
autoload :AccessTokens, 'qa/page/project/settings/access_tokens'
|
||||
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
module Page
|
||||
module Project
|
||||
module Import
|
||||
class RepoByURL < Page::Base
|
||||
include Page::Component::Select2
|
||||
|
||||
view 'app/views/projects/_new_project_fields.html.haml' do
|
||||
element :select_namespace_dropdown
|
||||
end
|
||||
|
||||
def import!(gitlab_repo_path, name)
|
||||
fill_git_repository_url_link(gitlab_repo_path)
|
||||
fill_project_name(name)
|
||||
choose_test_namespace
|
||||
click_create_button
|
||||
|
||||
wait_for_success
|
||||
|
||||
go_to_project(name)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fill_git_repository_url_link(gitlab_repo_path)
|
||||
fill_in 'project_import_url', with: gitlab_repo_path
|
||||
end
|
||||
|
||||
def fill_project_name(name)
|
||||
fill_in 'project_name', with: name
|
||||
end
|
||||
|
||||
def choose_test_namespace
|
||||
find('.js-select-namespace').click
|
||||
search_and_select(Runtime::Namespace.path)
|
||||
end
|
||||
|
||||
def click_create_button
|
||||
find('.btn-confirm').click
|
||||
end
|
||||
|
||||
def wait_for_success
|
||||
wait_until(max_duration: 60, sleep_interval: 5.0, reload: true, skip_finished_loading_check_on_refresh: true) do
|
||||
page.has_no_content?('Import in progress', wait: 3.0)
|
||||
end
|
||||
end
|
||||
|
||||
def go_to_project(name)
|
||||
Page::Main::Menu.perform(&:go_to_projects)
|
||||
Page::Dashboard::Projects.perform do |dashboard|
|
||||
dashboard.go_to_project(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -79,6 +79,10 @@ module QA
|
|||
click_link 'GitHub'
|
||||
end
|
||||
|
||||
def click_repo_by_url_link
|
||||
click_button 'Repo by URL'
|
||||
end
|
||||
|
||||
def enable_initialize_with_readme
|
||||
check_element(:initialize_with_readme_checkbox)
|
||||
end
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
module Page
|
||||
module Project
|
||||
module Settings
|
||||
class DefaultBranch < Page::Base
|
||||
include Page::Component::Select2
|
||||
|
||||
view 'app/views/projects/default_branch/_show.html.haml' do
|
||||
element :save_changes_button
|
||||
element :default_branch_dropdown
|
||||
end
|
||||
|
||||
def set_default_branch(branch)
|
||||
find('.select2-chosen').click
|
||||
search_and_select(branch)
|
||||
end
|
||||
|
||||
def click_save_changes_button
|
||||
find('.btn-confirm').click
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
QA::Page::Project::Settings::DefaultBranch.prepend_mod_with('Page::Project::Settings::DefaultBranch', namespace: QA)
|
|
@ -56,6 +56,14 @@ module QA
|
|||
ProtectedTags.perform(&block)
|
||||
end
|
||||
end
|
||||
|
||||
def expand_default_branch(&block)
|
||||
within('#default-branch-settings') do
|
||||
find('.btn-default').click do
|
||||
DefaultBranch.perform(&block)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'securerandom'
|
||||
|
||||
module QA
|
||||
module Resource
|
||||
class ProjectImportedFromURL < Resource::Project
|
||||
def fabricate!
|
||||
self.import = true
|
||||
super
|
||||
|
||||
group.visit!
|
||||
|
||||
Page::Group::Show.perform(&:go_to_new_project)
|
||||
|
||||
Page::Project::New.perform do |project_page|
|
||||
project_page.click_import_project
|
||||
project_page.click_repo_by_url_link
|
||||
end
|
||||
|
||||
Page::Project::Import::RepoByURL.perform do |import_page|
|
||||
import_page.import!(@gitlab_repository_path, @name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -51,7 +51,7 @@ module QA
|
|||
# The following example is excluded from running in `review-qa-smoke` job
|
||||
# as it proved to be flaky when running against Review App
|
||||
# See https://gitlab.com/gitlab-com/www-gitlab-com/-/issues/11568#note_621999351
|
||||
it 'comments on an issue with an attachment', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1742', exclude: { job: 'review-qa-smoke' } do
|
||||
it 'comments on an issue with an attachment', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1742', except: { job: 'review-qa-smoke' } do
|
||||
Page::Project::Issue::Show.perform do |show|
|
||||
show.comment('See attached image for scale', attachment: file_to_attach)
|
||||
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Package' do
|
||||
describe 'Container Registry Online Garbage Collection', :registry_gc, only: { subdomain: %i[pre] } do
|
||||
let(:group) { Resource::Group.fabricate_via_api! }
|
||||
|
||||
let(:imported_project) do
|
||||
Resource::ProjectImportedFromURL.fabricate_via_browser_ui! do |project|
|
||||
project.name = 'container-registry'
|
||||
project.group = group
|
||||
project.gitlab_repository_path = 'https://gitlab.com/gitlab-org/container-registry.git'
|
||||
end
|
||||
end
|
||||
|
||||
let!(:gitlab_ci_yaml) do
|
||||
<<~YAML
|
||||
variables:
|
||||
GOPATH: $CI_PROJECT_DIR/.go
|
||||
BUILD_CACHE: $CI_PROJECT_DIR/.online-gc-tester
|
||||
STAGE_ONE_VALIDATION_DELAY: "6m"
|
||||
STAGE_TWO_VALIDATION_DELAY: "12m"
|
||||
STAGE_THREE_VALIDATION_DELAY: "6m"
|
||||
STAGE_FOUR_VALIDATION_DELAY: "12m"
|
||||
STAGE_FIVE_VALIDATION_DELAY: "12m"
|
||||
|
||||
stages:
|
||||
- generate
|
||||
- build
|
||||
- test
|
||||
|
||||
.base: &base
|
||||
image: docker:19
|
||||
services:
|
||||
- docker:19-dind
|
||||
variables:
|
||||
DOCKER_HOST: tcp://docker:2376
|
||||
DOCKER_TLS_CERTDIR: "/certs"
|
||||
DOCKER_TLS_VERIFY: 1
|
||||
DOCKER_CERT_PATH: "$DOCKER_TLS_CERTDIR/client"
|
||||
before_script:
|
||||
- until docker info; do sleep 1; done
|
||||
- mkdir -p $GOPATH
|
||||
- mkdir -p $BUILD_CACHE
|
||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
|
||||
test:
|
||||
stage: generate
|
||||
extends: .base
|
||||
script:
|
||||
- apk add go make git
|
||||
- make binaries
|
||||
- ./bin/online-gc-tester generate --base-dir=$BUILD_CACHE
|
||||
- ./bin/online-gc-tester build --base-dir=$BUILD_CACHE
|
||||
- ./bin/online-gc-tester push --base-dir=$BUILD_CACHE
|
||||
- ./bin/online-gc-tester pull --base-dir=$BUILD_CACHE
|
||||
- ./bin/online-gc-tester test --base-dir=$BUILD_CACHE --stage=1 --delay=$STAGE_ONE_VALIDATION_DELAY
|
||||
- ./bin/online-gc-tester test --base-dir=$BUILD_CACHE --stage=2 --delay=$STAGE_TWO_VALIDATION_DELAY
|
||||
- ./bin/online-gc-tester test --base-dir=$BUILD_CACHE --stage=3 --delay=$STAGE_THREE_VALIDATION_DELAY
|
||||
- ./bin/online-gc-tester test --base-dir=$BUILD_CACHE --stage=4 --delay=$STAGE_FOUR_VALIDATION_DELAY
|
||||
- ./bin/online-gc-tester test --base-dir=$BUILD_CACHE --stage=5 --delay=$STAGE_FIVE_VALIDATION_DELAY
|
||||
timeout: 1h 30m
|
||||
YAML
|
||||
end
|
||||
|
||||
before do
|
||||
Flow::Login.sign_in
|
||||
|
||||
imported_project
|
||||
|
||||
Page::Project::Menu.perform(&:go_to_repository_settings)
|
||||
|
||||
Page::Project::Settings::Repository.perform do |setting|
|
||||
setting.expand_default_branch
|
||||
end
|
||||
|
||||
Page::Project::Settings::DefaultBranch.perform do |setting|
|
||||
setting.set_default_branch('online-gc-test-builder-poc')
|
||||
setting.click_save_changes_button
|
||||
end
|
||||
|
||||
Resource::Repository::Commit.fabricate_via_api! do |commit|
|
||||
commit.project = imported_project
|
||||
commit.branch = 'online-gc-test-builder-poc'
|
||||
commit.commit_message = 'Update .gitlab-ci.yml'
|
||||
commit.update_files([{
|
||||
file_path: '.gitlab-ci.yml',
|
||||
content: gitlab_ci_yaml
|
||||
}])
|
||||
end
|
||||
end
|
||||
|
||||
it 'runs the online garbage collector tool', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1854' do
|
||||
imported_project.visit!
|
||||
|
||||
Flow::Pipeline.visit_latest_pipeline
|
||||
|
||||
Page::Project::Pipeline::Show.perform do |pipeline|
|
||||
pipeline.click_job('test')
|
||||
end
|
||||
|
||||
Page::Project::Job::Show.perform do |job|
|
||||
expect(job).to be_successful(timeout: 3900)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -13,15 +13,17 @@ module QA
|
|||
config.before do |example|
|
||||
if example.metadata.key?(:only)
|
||||
skip('Test is not compatible with this environment or pipeline') unless ContextSelector.context_matches?(example.metadata[:only])
|
||||
elsif example.metadata.key?(:exclude)
|
||||
skip('Test is excluded in this job') if ContextSelector.exclude?(example.metadata[:exclude])
|
||||
elsif example.metadata.key?(:except)
|
||||
skip('Test is excluded in this job') if ContextSelector.except?(example.metadata[:except])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def exclude?(*options)
|
||||
return false unless Runtime::Env.ci_job_name.present?
|
||||
def except?(*options)
|
||||
return false if Runtime::Env.ci_job_name.blank? && options.any? { |o| o.is_a?(Hash) && o[:job].present? }
|
||||
return false if Runtime::Env.ci_project_name.blank? && options.any? { |o| o.is_a?(Hash) && o[:pipeline].present? }
|
||||
return false if Runtime::Scenario.attributes[:gitlab_address].blank?
|
||||
|
||||
context_matches?(*options)
|
||||
end
|
||||
|
@ -40,10 +42,14 @@ module QA
|
|||
|
||||
next unless option.is_a?(Hash)
|
||||
|
||||
if option[:pipeline].present? && Runtime::Env.ci_project_name.present?
|
||||
if option[:pipeline].present?
|
||||
return true if Runtime::Env.ci_project_name.blank?
|
||||
|
||||
return pipeline_matches?(option[:pipeline])
|
||||
|
||||
elsif option[:job].present?
|
||||
return true if Runtime::Env.ci_job_name.blank?
|
||||
|
||||
return job_matches?(option[:job])
|
||||
|
||||
elsif option[:subdomain].present?
|
||||
|
|
|
@ -49,8 +49,10 @@ RSpec.describe QA::Specs::Helpers::ContextSelector do
|
|||
it 'matches multiple subdomains' do
|
||||
QA::Runtime::Scenario.define(:gitlab_address, "https://staging.gitlab.com")
|
||||
|
||||
expect(described_class.context_matches?(subdomain: [:release, :staging])).to be_truthy
|
||||
expect(described_class.context_matches?(:production, subdomain: [:release, :staging])).to be_truthy
|
||||
aggregate_failures do
|
||||
expect(described_class.context_matches?(subdomain: [:release, :staging])).to be_truthy
|
||||
expect(described_class.context_matches?(:production, subdomain: [:release, :staging])).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
it 'matches :production' do
|
||||
|
@ -87,6 +89,16 @@ RSpec.describe QA::Specs::Helpers::ContextSelector do
|
|||
|
||||
expect(group.examples[0].execution_result.status).to eq(:passed)
|
||||
end
|
||||
|
||||
context 'when excluding contexts' do
|
||||
it 'can apply to contexts or descriptions' do
|
||||
group = describe_successfully 'skips staging', except: { subdomain: :staging } do
|
||||
it('skips staging') {}
|
||||
end
|
||||
|
||||
expect(group.examples[0].execution_result.status).to eq(:pending)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with different environment set' do
|
||||
|
@ -102,6 +114,16 @@ RSpec.describe QA::Specs::Helpers::ContextSelector do
|
|||
|
||||
expect(group.examples[0].execution_result.status).to eq(:pending)
|
||||
end
|
||||
|
||||
context 'when excluding contexts' do
|
||||
it 'runs against production' do
|
||||
group = describe_successfully 'Runs in staging', :something, except: { subdomain: :staging } do
|
||||
it('runs in staging') {}
|
||||
end
|
||||
|
||||
expect(group.examples[0].execution_result.status).to eq(:passed)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -113,10 +135,28 @@ RSpec.describe QA::Specs::Helpers::ContextSelector do
|
|||
it('runs in any env') {}
|
||||
end
|
||||
|
||||
expect(group.examples[0].execution_result.status).to eq(:passed)
|
||||
expect(group.examples[1].execution_result.status).to eq(:pending)
|
||||
expect(group.examples[2].execution_result.status).to eq(:passed)
|
||||
expect(group.examples[3].execution_result.status).to eq(:passed)
|
||||
aggregate_failures do
|
||||
expect(group.examples[0].execution_result.status).to eq(:passed)
|
||||
expect(group.examples[1].execution_result.status).to eq(:pending)
|
||||
expect(group.examples[2].execution_result.status).to eq(:passed)
|
||||
expect(group.examples[3].execution_result.status).to eq(:passed)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when excluding contexts' do
|
||||
it 'skips staging' do
|
||||
group = describe_successfully do
|
||||
it('skips staging', except: { subdomain: :staging }) {}
|
||||
it('runs in staging', except: :production) {}
|
||||
it('skips staging also', except: { subdomain: %i[release staging] }) {}
|
||||
end
|
||||
|
||||
aggregate_failures do
|
||||
expect(group.examples[0].execution_result.status).to eq(:pending)
|
||||
expect(group.examples[1].execution_result.status).to eq(:passed)
|
||||
expect(group.examples[2].execution_result.status).to eq(:pending)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'custom env' do
|
||||
|
@ -130,8 +170,24 @@ RSpec.describe QA::Specs::Helpers::ContextSelector do
|
|||
it('does not run on release', only: :production) {}
|
||||
end
|
||||
|
||||
expect(group.examples.first.execution_result.status).to eq(:passed)
|
||||
expect(group.examples.last.execution_result.status).to eq(:pending)
|
||||
aggregate_failures do
|
||||
expect(group.examples.first.execution_result.status).to eq(:passed)
|
||||
expect(group.examples.last.execution_result.status).to eq(:pending)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when excluding contexts' do
|
||||
it 'skips a custom environment' do
|
||||
group = describe_successfully do
|
||||
it('skips release gitlab net', except: { tld: '.net', subdomain: :release, domain: 'gitlab' }) {}
|
||||
it('runs on release', except: :production) {}
|
||||
end
|
||||
|
||||
aggregate_failures do
|
||||
expect(group.examples.first.execution_result.status).to eq(:pending)
|
||||
expect(group.examples.last.execution_result.status).to eq(:passed)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -147,9 +203,27 @@ RSpec.describe QA::Specs::Helpers::ContextSelector do
|
|||
it('runs in prod and staging', only: { subdomain: /(staging.)?/, domain: 'gitlab' }) {}
|
||||
end
|
||||
|
||||
expect(group.examples[0].execution_result.status).to eq(:passed)
|
||||
expect(group.examples[1].execution_result.status).to eq(:pending)
|
||||
expect(group.examples[2].execution_result.status).to eq(:passed)
|
||||
aggregate_failures do
|
||||
expect(group.examples[0].execution_result.status).to eq(:passed)
|
||||
expect(group.examples[1].execution_result.status).to eq(:pending)
|
||||
expect(group.examples[2].execution_result.status).to eq(:passed)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when excluding contexts' do
|
||||
it 'skips production' do
|
||||
group = describe_successfully do
|
||||
it('skips prod', except: :production) {}
|
||||
it('runs on prod', except: { subdomain: :staging }) {}
|
||||
it('skips prod and staging', except: { subdomain: /(staging.)?/, domain: 'gitlab' }) {}
|
||||
end
|
||||
|
||||
aggregate_failures do
|
||||
expect(group.examples[0].execution_result.status).to eq(:pending)
|
||||
expect(group.examples[1].execution_result.status).to eq(:passed)
|
||||
expect(group.examples[2].execution_result.status).to eq(:pending)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -179,6 +253,21 @@ RSpec.describe QA::Specs::Helpers::ContextSelector do
|
|||
expect(group.examples[1].execution_result.status).to eq(:passed)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when excluding contexts' do
|
||||
it 'runs in any pipeline' do
|
||||
group = describe_successfully do
|
||||
it('runs given a single named pipeline', except: { pipeline: :nightly }) {}
|
||||
it('runs given an array of pipelines', except: { pipeline: [:canary, :not_nightly] }) {}
|
||||
end
|
||||
|
||||
aggregate_failures do
|
||||
group.examples.each do |example|
|
||||
expect(example.execution_result.status).to eq(:passed)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a pipeline triggered from the default branch runs in gitlab-qa' do
|
||||
|
@ -200,6 +289,22 @@ RSpec.describe QA::Specs::Helpers::ContextSelector do
|
|||
expect(group.examples[2].execution_result.status).to eq(:pending)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when excluding contexts' do
|
||||
it 'skips default branch pipelines' do
|
||||
group = describe_successfully do
|
||||
it('skips main pipeline given a single pipeline', except: { pipeline: :main }) {}
|
||||
it('skips main given an array of pipelines', except: { pipeline: [:canary, :main] }) {}
|
||||
it('runs non-default pipelines', except: { pipeline: [:nightly, :not_nightly, :not_main] }) {}
|
||||
end
|
||||
|
||||
aggregate_failures do
|
||||
expect(group.examples[0].execution_result.status).to eq(:pending)
|
||||
expect(group.examples[1].execution_result.status).to eq(:pending)
|
||||
expect(group.examples[2].execution_result.status).to eq(:passed)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with CI_PROJECT_NAME set' do
|
||||
|
@ -223,24 +328,42 @@ RSpec.describe QA::Specs::Helpers::ContextSelector do
|
|||
expect(group.examples[3].execution_result.status).to eq(:pending)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when excluding contexts' do
|
||||
it 'skips designated pipeline' do
|
||||
group = describe_successfully do
|
||||
it('skips nightly', except: { pipeline: :nightly }) {}
|
||||
it('runs in not_nightly', except: { pipeline: :not_nightly }) {}
|
||||
it('skips on nightly given an array', except: { pipeline: [:canary, :nightly] }) {}
|
||||
it('runs in not_nightly given an array', except: { pipeline: [:not_nightly, :canary] }) {}
|
||||
end
|
||||
|
||||
aggregate_failures do
|
||||
expect(group.examples[0].execution_result.status).to eq(:pending)
|
||||
expect(group.examples[1].execution_result.status).to eq(:passed)
|
||||
expect(group.examples[2].execution_result.status).to eq(:pending)
|
||||
expect(group.examples[3].execution_result.status).to eq(:passed)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when excluding contexts' do
|
||||
context 'with job constraints' do
|
||||
context 'without CI_JOB_NAME set' do
|
||||
before do
|
||||
stub_env('CI_JOB_NAME', nil)
|
||||
described_class.configure_rspec
|
||||
end
|
||||
context 'with job constraints' do
|
||||
context 'without CI_JOB_NAME set' do
|
||||
before do
|
||||
stub_env('CI_JOB_NAME', nil)
|
||||
described_class.configure_rspec
|
||||
end
|
||||
|
||||
context 'when excluding contexts' do
|
||||
it 'runs in any job' do
|
||||
group = describe_successfully do
|
||||
it('runs given a single named job', exclude: { job: 'ee:instance-image' }) {}
|
||||
it('runs given a single regex pattern', exclude: { job: '.*:instance-image' }) {}
|
||||
it('runs given an array of jobs', exclude: { job: %w[ee:instance-image qa-schedules-browser_ui-3_create] }) {}
|
||||
it('runs given an array of regex patterns', exclude: { job: %w[ee:.* qa-schedules-browser_ui.*] }) {}
|
||||
it('runs given a mix of strings and regex patterns', exclude: { job: %w[ee:instance-image qa-schedules-browser_ui.*] }) {}
|
||||
it('runs given a single named job', except: { job: 'ee:instance-image' }) {}
|
||||
it('runs given a single regex pattern', except: { job: '.*:instance-image' }) {}
|
||||
it('runs given an array of jobs', except: { job: %w[ee:instance-image qa-schedules-browser_ui-3_create] }) {}
|
||||
it('runs given an array of regex patterns', except: { job: %w[ee:.* qa-schedules-browser_ui.*] }) {}
|
||||
it('runs given a mix of strings and regex patterns', except: { job: %w[ee:instance-image qa-schedules-browser_ui.*] }) {}
|
||||
end
|
||||
|
||||
aggregate_failures do
|
||||
|
@ -251,19 +374,39 @@ RSpec.describe QA::Specs::Helpers::ContextSelector do
|
|||
end
|
||||
end
|
||||
|
||||
context 'with CI_JOB_NAME set' do
|
||||
before do
|
||||
stub_env('CI_JOB_NAME', 'ee:instance-image')
|
||||
described_class.configure_rspec
|
||||
end
|
||||
context 'when including only specific contexts' do
|
||||
it 'runs in any job' do
|
||||
group = describe_successfully do
|
||||
it('runs given a single named job', only: { job: 'ee:instance-image' }) {}
|
||||
it('runs given a single regex pattern', only: { job: '.*:instance-image' }) {}
|
||||
it('runs given an array of jobs', only: { job: %w[ee:instance-image qa-schedules-browser_ui-3_create] }) {}
|
||||
it('runs given an array of regex patterns', only: { job: %w[ee:.* qa-schedules-browser_ui.*] }) {}
|
||||
it('runs given a mix of strings and regex patterns', only: { job: %w[ee:instance-image qa-schedules-browser_ui.*] }) {}
|
||||
end
|
||||
|
||||
aggregate_failures do
|
||||
group.examples.each do |example|
|
||||
expect(example.execution_result.status).to eq(:passed)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with CI_JOB_NAME set' do
|
||||
before do
|
||||
stub_env('CI_JOB_NAME', 'ee:instance-image')
|
||||
described_class.configure_rspec
|
||||
end
|
||||
|
||||
context 'when excluding contexts' do
|
||||
it 'does not run in the specified job' do
|
||||
group = describe_successfully do
|
||||
it('skips given a single named job', exclude: { job: 'ee:instance-image' }) {}
|
||||
it('skips given a single regex pattern', exclude: { job: '.*:instance-image' }) {}
|
||||
it('skips given an array of jobs', exclude: { job: %w[ee:instance-image qa-schedules-browser_ui-3_create] }) {}
|
||||
it('skips given an array of regex patterns', exclude: { job: %w[ee:.* qa-schedules-browser_ui.*] }) {}
|
||||
it('skips given a mix of strings and regex patterns', exclude: { job: %w[ee:instance-image qa-schedules-browser_ui.*] }) {}
|
||||
it('skips given a single named job', except: { job: 'ee:instance-image' }) {}
|
||||
it('skips given a single regex pattern', except: { job: '.*:instance-image' }) {}
|
||||
it('skips given an array of jobs', except: { job: %w[ee:instance-image qa-schedules-browser_ui-3_create] }) {}
|
||||
it('skips given an array of regex patterns', except: { job: %w[ee:.* qa-schedules-browser_ui.*] }) {}
|
||||
it('skips given a mix of strings and regex patterns', except: { job: %w[ee:instance-image qa-schedules-browser_ui.*] }) {}
|
||||
end
|
||||
|
||||
aggregate_failures do
|
||||
|
@ -275,11 +418,11 @@ RSpec.describe QA::Specs::Helpers::ContextSelector do
|
|||
|
||||
it 'runs in jobs that do not match' do
|
||||
group = describe_successfully do
|
||||
it('runs given a single named job', exclude: { job: 'ce:instance-image' }) {}
|
||||
it('runs given a single regex pattern', exclude: { job: '.*:instance-image-quarantine' }) {}
|
||||
it('runs given an array of jobs', exclude: { job: %w[ce:instance-image qa-schedules-browser_ui-3_create] }) {}
|
||||
it('runs given an array of regex patterns', exclude: { job: %w[ce:.* qa-schedules-browser_ui.*] }) {}
|
||||
it('runs given a mix of strings and regex patterns', exclude: { job: %w[ce:instance-image qa-schedules-browser_ui.*] }) {}
|
||||
it('runs given a single named job', except: { job: 'ce:instance-image' }) {}
|
||||
it('runs given a single regex pattern', except: { job: '.*:instance-image-quarantine' }) {}
|
||||
it('runs given an array of jobs', except: { job: %w[ce:instance-image qa-schedules-browser_ui-3_create] }) {}
|
||||
it('runs given an array of regex patterns', except: { job: %w[ce:.* qa-schedules-browser_ui.*] }) {}
|
||||
it('runs given a mix of strings and regex patterns', except: { job: %w[ce:instance-image qa-schedules-browser_ui.*] }) {}
|
||||
end
|
||||
|
||||
aggregate_failures do
|
||||
|
@ -289,6 +432,40 @@ RSpec.describe QA::Specs::Helpers::ContextSelector do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when including only specific contexts' do
|
||||
it 'runs only in the specified jobs' do
|
||||
group = describe_successfully do
|
||||
it('runs given a single named job', only: { job: 'ee:instance-image' }) {}
|
||||
it('runs given a single regex pattern', only: { job: '.*:instance-image' }) {}
|
||||
it('runs given an array of jobs', only: { job: %w[ee:instance-image qa-schedules-browser_ui-3_create] }) {}
|
||||
it('runs given an array of regex patterns', only: { job: %w[ee:.* qa-schedules-browser_ui.*] }) {}
|
||||
it('runs given a mix of strings and regex patterns', only: { job: %w[ee:instance-image qa-schedules-browser_ui.*] }) {}
|
||||
end
|
||||
|
||||
aggregate_failures do
|
||||
group.examples.each do |example|
|
||||
expect(example.execution_result.status).to eq(:passed)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'does not run in jobs that do not match' do
|
||||
group = describe_successfully do
|
||||
it('skips given a single named job', only: { job: 'ce:instance-image' }) {}
|
||||
it('skips given a single regex pattern', only: { job: '.*:instance-image-quarantine' }) {}
|
||||
it('skips given an array of jobs', only: { job: %w[ce:instance-image qa-schedules-browser_ui-3_create] }) {}
|
||||
it('skips given an array of regex patterns', only: { job: %w[ce:.* qa-schedules-browser_ui.*] }) {}
|
||||
it('skips given a mix of strings and regex patterns', only: { job: %w[ce:instance-image qa-schedules-browser_ui.*] }) {}
|
||||
end
|
||||
|
||||
aggregate_failures do
|
||||
group.examples.each do |example|
|
||||
expect(example.execution_result.status).to eq(:pending)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Mutations::Security::CiConfiguration::BaseSecurityAnalyzer do
|
||||
include GraphqlHelpers
|
||||
|
||||
it 'raises a NotImplementedError error if the resolve method is called on the base class' do
|
||||
user = create(:user)
|
||||
project = create(:project, :public, :repository)
|
||||
project.add_developer(user)
|
||||
expect { resolve(described_class, args: { project_path: project.full_path }, ctx: { current_user: user }) }.to raise_error(NotImplementedError)
|
||||
end
|
||||
end
|
|
@ -160,17 +160,17 @@ RSpec.describe Types::BaseField do
|
|||
let(:flag) { :test_flag }
|
||||
|
||||
it 'prepends the description' do
|
||||
expect(field.description). to eq 'Test description. Available only when feature flag `test_flag` is enabled.'
|
||||
expect(field.description).to start_with 'Test description. Available only when feature flag `test_flag` is enabled.'
|
||||
end
|
||||
|
||||
context 'falsey feature_flag values' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
where(:flag, :feature_value) do
|
||||
'' | false
|
||||
'' | true
|
||||
nil | false
|
||||
nil | true
|
||||
where(:flag, :feature_value, :default_enabled) do
|
||||
'' | false | false
|
||||
'' | true | false
|
||||
nil | false | true
|
||||
nil | true | false
|
||||
end
|
||||
|
||||
with_them do
|
||||
|
@ -179,6 +179,33 @@ RSpec.describe Types::BaseField do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with different default_enabled values' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
where(:feature_value, :default_enabled, :expected_description) do
|
||||
disabled_ff_description = "Test description. Available only when feature flag `test_flag` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice."
|
||||
enabled_ff_description = "Test description. Available only when feature flag `test_flag` is enabled. This flag is enabled by default."
|
||||
|
||||
false | false | disabled_ff_description
|
||||
true | false | disabled_ff_description
|
||||
false | true | enabled_ff_description
|
||||
true | true | enabled_ff_description
|
||||
end
|
||||
|
||||
with_them do
|
||||
before do
|
||||
stub_feature_flags("#{flag}": feature_value)
|
||||
|
||||
allow(Feature::Definition).to receive(:has_definition?).with(flag).and_return(true)
|
||||
allow(Feature::Definition).to receive(:default_enabled?).and_return(default_enabled)
|
||||
end
|
||||
|
||||
it 'returns the correct availability in the description' do
|
||||
expect(field.description). to eq expected_description
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -196,9 +223,8 @@ RSpec.describe Types::BaseField do
|
|||
feature_flag: 'foo_flag'
|
||||
)
|
||||
|
||||
expectation = 'Field description. Available only when feature flag `foo_flag` is enabled. Deprecated in 1.10: Deprecation reason.'
|
||||
|
||||
expect(field.description).to eq(expectation)
|
||||
expect(field.description).to start_with('Field description. Available only when feature flag `foo_flag` is enabled.')
|
||||
expect(field.description).to end_with('Deprecated in 1.10: Deprecation reason.')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -771,16 +771,6 @@ RSpec.describe 'project routing' do
|
|||
end
|
||||
|
||||
describe Projects::ServicePingController, 'routing' do
|
||||
describe 'deprecated routing' do
|
||||
it 'routes to service_ping#web_ide_clientside_preview' do
|
||||
expect(post('/gitlab/gitlabhq/usage_ping/web_ide_clientside_preview')).to route_to('projects/service_ping#web_ide_clientside_preview', namespace_id: 'gitlab', project_id: 'gitlabhq')
|
||||
end
|
||||
|
||||
it 'routes to service_ping#web_ide_pipelines_count' do
|
||||
expect(post('/gitlab/gitlabhq/usage_ping/web_ide_pipelines_count')).to route_to('projects/service_ping#web_ide_pipelines_count', namespace_id: 'gitlab', project_id: 'gitlabhq')
|
||||
end
|
||||
end
|
||||
|
||||
it 'routes to service_ping#web_ide_clientside_preview' do
|
||||
expect(post('/gitlab/gitlabhq/service_ping/web_ide_clientside_preview')).to route_to('projects/service_ping#web_ide_clientside_preview', namespace_id: 'gitlab', project_id: 'gitlabhq')
|
||||
end
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue