Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-07-19 15:09:40 +00:00
parent 1072f96e34
commit 4a72126942
40 changed files with 815 additions and 302 deletions

View File

@ -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).

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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'

View File

@ -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

View File

@ -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) + '/' }

View File

@ -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' }

View File

@ -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'

View File

@ -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

View File

@ -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

View File

@ -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. |

View File

@ -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 -->

View File

@ -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`.

View File

@ -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?

View File

@ -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. |

View File

@ -22436,7 +22436,7 @@ Group: `group::monitor`
Data Category: `Optional`
Status: `data_available`
Status: `deprecated`
Tiers: `premium`, `ultimate`

View File

@ -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

View File

@ -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.

View File

@ -27,7 +27,6 @@ Group DevOps Adoption shows you how individual groups and sub-groups within your
- Sec
- DAST
- SAST
- Scans
- Ops
- Deployments
- Pipelines

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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 ""

View File

@ -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'

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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?

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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