Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
492f99eac8
commit
b8c4740f87
27 changed files with 348 additions and 219 deletions
|
@ -1,29 +1,29 @@
|
||||||
---
|
---
|
||||||
# Base Markdownlint configuration
|
# Base Markdownlint configuration
|
||||||
# Extended Markdownlint configuration in doc/.markdownlint/
|
# Extended Markdownlint configuration in doc/.markdownlint/
|
||||||
"default": true
|
default: true
|
||||||
"first-header-h1": true
|
first-header-h1: true
|
||||||
"header-style":
|
header-style:
|
||||||
"style": "atx"
|
style: "atx"
|
||||||
"ul-style":
|
ul-style:
|
||||||
"style": "dash"
|
style: "dash"
|
||||||
"no-trailing-spaces": false
|
no-trailing-spaces: false
|
||||||
"line-length": false
|
line-length: false
|
||||||
"no-duplicate-header":
|
no-duplicate-header:
|
||||||
"allow_different_nesting": true
|
allow_different_nesting: true
|
||||||
"no-trailing-punctuation":
|
no-trailing-punctuation:
|
||||||
"punctuation": ".,;:!。,;:!?"
|
punctuation: ".,;:!。,;:!?"
|
||||||
"ol-prefix":
|
ol-prefix:
|
||||||
"style": "one"
|
style: "one"
|
||||||
"no-inline-html": false
|
no-inline-html: false
|
||||||
"hr-style":
|
hr-style:
|
||||||
"style": "---"
|
style: "---"
|
||||||
"no-emphasis-as-heading": false
|
no-emphasis-as-heading: false
|
||||||
"first-line-h1": false
|
first-line-h1: false
|
||||||
"code-block-style":
|
code-block-style:
|
||||||
"style": "fenced"
|
style: "fenced"
|
||||||
"proper-names":
|
proper-names:
|
||||||
"names": [
|
names: [
|
||||||
"Akismet",
|
"Akismet",
|
||||||
"Alertmanager",
|
"Alertmanager",
|
||||||
"API",
|
"API",
|
||||||
|
@ -139,4 +139,4 @@
|
||||||
"YAML",
|
"YAML",
|
||||||
"YouTrack"
|
"YouTrack"
|
||||||
]
|
]
|
||||||
"code_blocks": false
|
code_blocks: false
|
||||||
|
|
|
@ -90,7 +90,7 @@ export default {
|
||||||
<local-storage-sync v-model="isExpanded" :storage-key="$options.localDrawerKey" as-json>
|
<local-storage-sync v-model="isExpanded" :storage-key="$options.localDrawerKey" as-json>
|
||||||
<aside
|
<aside
|
||||||
aria-live="polite"
|
aria-live="polite"
|
||||||
class="gl-fixed gl-right-0 gl-bg-gray-10 gl-shadow-drawer gl-transition-property-width gl-transition-duration-medium gl-border-l-solid gl-border-1 gl-border-gray-100 gl-h-full gl-z-index-3 gl-overflow-y-auto"
|
class="gl-fixed gl-right-0 gl-bg-gray-10 gl-shadow-drawer gl-transition-property-width gl-transition-duration-medium gl-border-l-solid gl-border-1 gl-border-gray-100 gl-h-full gl-z-index-200 gl-overflow-y-auto"
|
||||||
:style="rootStyle"
|
:style="rootStyle"
|
||||||
>
|
>
|
||||||
<gl-button
|
<gl-button
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
import { GlDropdown, GlLoadingIcon, GlTooltipDirective, GlIcon } from '@gitlab/ui';
|
import { GlDropdown, GlLoadingIcon, GlTooltipDirective, GlIcon } from '@gitlab/ui';
|
||||||
import createFlash from '~/flash';
|
import createFlash from '~/flash';
|
||||||
import axios from '~/lib/utils/axios_utils';
|
import axios from '~/lib/utils/axios_utils';
|
||||||
import { __ } from '~/locale';
|
import { __, sprintf } from '~/locale';
|
||||||
import eventHub from '../../event_hub';
|
import eventHub from '../../event_hub';
|
||||||
import JobItem from './job_item.vue';
|
import JobItem from './job_item.vue';
|
||||||
|
|
||||||
|
@ -98,6 +98,9 @@ export default {
|
||||||
// warn the pipelines table to update
|
// warn the pipelines table to update
|
||||||
this.$emit('pipelineActionRequestComplete');
|
this.$emit('pipelineActionRequestComplete');
|
||||||
},
|
},
|
||||||
|
stageAriaLabel(title) {
|
||||||
|
return sprintf(__('View Stage: %{title}'), { title });
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -106,9 +109,10 @@ export default {
|
||||||
<gl-dropdown
|
<gl-dropdown
|
||||||
ref="dropdown"
|
ref="dropdown"
|
||||||
v-gl-tooltip.hover.ds0
|
v-gl-tooltip.hover.ds0
|
||||||
|
v-gl-tooltip="stage.title"
|
||||||
data-testid="mini-pipeline-graph-dropdown"
|
data-testid="mini-pipeline-graph-dropdown"
|
||||||
:title="stage.title"
|
|
||||||
variant="link"
|
variant="link"
|
||||||
|
:aria-label="stageAriaLabel(stage.title)"
|
||||||
:lazy="true"
|
:lazy="true"
|
||||||
:popper-opts="{ placement: 'bottom' }"
|
:popper-opts="{ placement: 'bottom' }"
|
||||||
:toggle-class="['mini-pipeline-graph-dropdown-toggle', triggerButtonClass]"
|
:toggle-class="['mini-pipeline-graph-dropdown-toggle', triggerButtonClass]"
|
||||||
|
|
|
@ -947,19 +947,6 @@ $tabs-holder-z-index: 250;
|
||||||
color: $gray-500;
|
color: $gray-500;
|
||||||
line-height: initial;
|
line-height: initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GlDropdown mini pipeline (Vue)
|
|
||||||
// As the `mini-pipeline-item` mixin specificity is lower
|
|
||||||
// than the toggle of dropdown with 'variant="link"' we add
|
|
||||||
// classes ".gl-button.btn-link" to make it more specific
|
|
||||||
// and avoid having the size overriden
|
|
||||||
//
|
|
||||||
// See https://gitlab.com/gitlab-org/gitlab/-/issues/320737
|
|
||||||
button.gl-button.btn-link.mini-pipeline-graph-dropdown-toggle,
|
|
||||||
.stage-cell button.gl-button.btn-link.mini-pipeline-graph-dropdown-toggle svg {
|
|
||||||
height: $ci-action-icon-size-lg;
|
|
||||||
width: $ci-action-icon-size-lg;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.merge-request-details .file-finder-overlay.diff-file-finder {
|
.merge-request-details .file-finder-overlay.diff-file-finder {
|
||||||
|
|
|
@ -297,3 +297,8 @@ $gl-line-height-42: px-to-rem(42px);
|
||||||
max-width: 50%;
|
max-width: 50%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Will be moved to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/2497
|
||||||
|
.gl-z-index-200 {
|
||||||
|
z-index: 200;
|
||||||
|
}
|
||||||
|
|
|
@ -50,34 +50,6 @@ module Clusters
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def ensure_runner
|
|
||||||
runner || create_and_assign_runner
|
|
||||||
end
|
|
||||||
|
|
||||||
def create_and_assign_runner
|
|
||||||
transaction do
|
|
||||||
Ci::Runner.create!(runner_create_params).tap do |runner|
|
|
||||||
update!(runner_id: runner.id)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def runner_create_params
|
|
||||||
attributes = {
|
|
||||||
name: 'kubernetes-cluster',
|
|
||||||
runner_type: cluster.cluster_type,
|
|
||||||
tag_list: %w[kubernetes cluster]
|
|
||||||
}
|
|
||||||
|
|
||||||
if cluster.group_type?
|
|
||||||
attributes[:runner_namespaces] = [::Ci::RunnerNamespace.new(namespace: group)]
|
|
||||||
elsif cluster.project_type?
|
|
||||||
attributes[:runner_projects] = [::Ci::RunnerProject.new(project: project)]
|
|
||||||
end
|
|
||||||
|
|
||||||
attributes
|
|
||||||
end
|
|
||||||
|
|
||||||
def gitlab_url
|
def gitlab_url
|
||||||
Gitlab::Routing.url_helpers.root_url(only_path: false)
|
Gitlab::Routing.url_helpers.root_url(only_path: false)
|
||||||
end
|
end
|
||||||
|
@ -85,7 +57,6 @@ module Clusters
|
||||||
def specification
|
def specification
|
||||||
{
|
{
|
||||||
"gitlabUrl" => gitlab_url,
|
"gitlabUrl" => gitlab_url,
|
||||||
"runnerToken" => ensure_runner.token,
|
|
||||||
"runners" => { "privileged" => privileged }
|
"runners" => { "privileged" => privileged }
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
%span.light= _('Email:')
|
%span.light= _('Email:')
|
||||||
%strong
|
%strong
|
||||||
= render partial: 'shared/email_with_badge', locals: { email: mail_to(@user.email), verified: @user.confirmed? }
|
= render partial: 'shared/email_with_badge', locals: { email: mail_to(@user.email), verified: @user.confirmed? }
|
||||||
- @user.emails.each do |email|
|
- @user.emails.reject(&:user_primary_email?).each do |email|
|
||||||
%li
|
%li
|
||||||
%span.light= _('Secondary email:')
|
%span.light= _('Secondary email:')
|
||||||
%strong
|
%strong
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
---
|
---
|
||||||
# Extended Markdown configuration to enforce no-trailing-spaces rule
|
# Extended Markdown configuration to enforce no-trailing-spaces rule
|
||||||
"extends": "../../.markdownlint.yml"
|
extends: "../../.markdownlint.yml"
|
||||||
"no-trailing-spaces": true
|
no-trailing-spaces: true
|
||||||
|
|
|
@ -325,14 +325,23 @@ You can [monitor distribution of reads](#monitor-gitaly-cluster) using Prometheu
|
||||||
> - From GitLab 13.6, primary-wins voting strategy and the `gitaly_reference_transactions_primary_wins` feature flag was removed.
|
> - From GitLab 13.6, primary-wins voting strategy and the `gitaly_reference_transactions_primary_wins` feature flag was removed.
|
||||||
> - From GitLab 14.0, [Gitaly Cluster only supports strong consistency](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/3575), and the `gitaly_reference_transactions` feature flag was removed.
|
> - From GitLab 14.0, [Gitaly Cluster only supports strong consistency](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/3575), and the `gitaly_reference_transactions` feature flag was removed.
|
||||||
|
|
||||||
Gitaly Cluster writes changes synchronously to all healthy, up to date replicas.
|
Gitaly Cluster provides strong consistency by writing changes synchronously to all healthy, up-to-date replicas. If a
|
||||||
If a replica is outdated or unhealthy at the time of the transaction, the write is asynchronously replicated to it.
|
replica is outdated or unhealthy at the time of the transaction, the write is asynchronously replicated to it.
|
||||||
|
|
||||||
In GitLab 13.12 and earlier, if Gitaly Cluster wasn't configured to use strong consistency (or didn't support it yet), Gitaly Cluster guaranteed eventual consistency by replicating all writes to secondary Gitaly nodes after the write to the primary Gitaly node has occurred.
|
If strong consistency is unavailable, Gitaly Cluster guarantees eventual consistency. In this case. Gitaly Cluster
|
||||||
|
replicates all writes to secondary Gitaly nodes after the write to the primary Gitaly node has occurred.
|
||||||
|
|
||||||
A subset of operations still use replication jobs (instead of a strong consistency transaction).
|
Strong consistency:
|
||||||
For more information, see the
|
|
||||||
[strong consistency epic](https://gitlab.com/groups/gitlab-org/-/epics/1189).
|
- Is the primary replication method in GitLab 14.0 and later. A subset of operations still use replication jobs
|
||||||
|
(eventual consistency) instead of strong consistency. Refer to the
|
||||||
|
[strong consistency epic](https://gitlab.com/groups/gitlab-org/-/epics/1189) for more information.
|
||||||
|
- Must be configured in GitLab versions 13.1 to 13.12. For configuration information, refer to either:
|
||||||
|
- Documentation on your GitLab instance at `/help`.
|
||||||
|
- The [13.12 documentation](https://docs.gitlab.com/13.12/ee/administration/gitaly/praefect.html#strong-consistency).
|
||||||
|
- Is unavailable in GitLab 13.0 and earlier.
|
||||||
|
|
||||||
|
For more information on monitoring strong consistency, see the Gitaly Cluster [Prometheus metrics documentation](#monitor-gitaly-cluster).
|
||||||
|
|
||||||
#### Replication factor
|
#### Replication factor
|
||||||
|
|
||||||
|
|
|
@ -1105,17 +1105,6 @@ To get started quickly:
|
||||||
Congratulations! You've configured an observable fault-tolerant Praefect
|
Congratulations! You've configured an observable fault-tolerant Praefect
|
||||||
cluster.
|
cluster.
|
||||||
|
|
||||||
## Strong consistency
|
|
||||||
|
|
||||||
[Strong consistency](index.md#strong-consistency) is the default from GitLab 14.0.
|
|
||||||
For configuration information on earlier versions, refer to documentation:
|
|
||||||
|
|
||||||
- On your GitLab instance at `/help`.
|
|
||||||
- The [13.12 documentation](https://docs.gitlab.com/13.12/ee/administration/gitaly/praefect.html#strong-consistency).
|
|
||||||
|
|
||||||
For information on monitoring strong consistency, see the Gitaly Cluster
|
|
||||||
[Prometheus metrics documentation](index.md#monitor-gitaly-cluster).
|
|
||||||
|
|
||||||
## Configure replication factor
|
## Configure replication factor
|
||||||
|
|
||||||
WARNING:
|
WARNING:
|
||||||
|
|
|
@ -437,12 +437,12 @@ Praefect does not require a lot of CPU or memory, and can run on small virtual m
|
||||||
Cloud services may place other limits on the resources that small VMs can use, such as
|
Cloud services may place other limits on the resources that small VMs can use, such as
|
||||||
disk IO and network traffic.
|
disk IO and network traffic.
|
||||||
|
|
||||||
Praefect nodes generate a lot of network traffic. The following symptoms can be observed
|
Praefect nodes generate a lot of network traffic. The following symptoms can be observed if their network bandwidth has
|
||||||
if their network bandwidth has been throttled by the cloud service.
|
been throttled by the cloud service:
|
||||||
|
|
||||||
- Poor performance of Git operations
|
- Poor performance of Git operations.
|
||||||
- High network latency
|
- High network latency.
|
||||||
- High memory use by Praefect
|
- High memory use by Praefect.
|
||||||
|
|
||||||
Possible solutions:
|
Possible solutions:
|
||||||
|
|
||||||
|
|
|
@ -167,7 +167,7 @@ GitLab can display the results of one or more reports in:
|
||||||
The `dotenv` report collects a set of environment variables as artifacts.
|
The `dotenv` report collects a set of environment variables as artifacts.
|
||||||
|
|
||||||
The collected variables are registered as runtime-created variables of the job,
|
The collected variables are registered as runtime-created variables of the job,
|
||||||
which is useful to [set dynamic environment URLs after a job finishes](../environments/index.md#set-dynamic-environment-urls-after-a-job-finishes).
|
which you can use to [set dynamic environment URLs after a job finishes](../environments/index.md#set-dynamic-environment-urls-after-a-job-finishes).
|
||||||
|
|
||||||
The exceptions to the [original dotenv rules](https://github.com/motdotla/dotenv#rules) are:
|
The exceptions to the [original dotenv rules](https://github.com/motdotla/dotenv#rules) are:
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,21 @@ 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
|
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
|
||||||
---
|
---
|
||||||
|
|
||||||
# Resource class in GitLab QA
|
# Resource classes in GitLab QA
|
||||||
|
|
||||||
Resources are primarily created using Browser UI steps, but can also
|
Resources are primarily created using Browser UI steps, but can also be created via the API or the CLI.
|
||||||
be created via the API or the CLI.
|
|
||||||
|
A typical resource class is used to create a new resource that can be used in a single test. However, several tests can
|
||||||
|
end up creating the same kind of resource and use it in ways that mean it could have been
|
||||||
|
used by more than one test. Creating a new resource each time is not efficient. Therefore, we can also create reusable
|
||||||
|
resources that are created once and can then be used by many tests.
|
||||||
|
|
||||||
|
In the following section the content focuses on single-use resources, however it also applies to reusable resources.
|
||||||
|
Information specific to [reusable resources is detailed below](#reusable-resources).
|
||||||
|
|
||||||
## How to properly implement a resource class?
|
## How to properly implement a resource class?
|
||||||
|
|
||||||
All resource classes should inherit from `Resource::Base`.
|
All non-reusable resource classes should inherit from `Resource::Base`.
|
||||||
|
|
||||||
There is only one mandatory method to implement to define a resource class.
|
There is only one mandatory method to implement to define a resource class.
|
||||||
This is the `#fabricate!` method, which is used to build the resource via the
|
This is the `#fabricate!` method, which is used to build the resource via the
|
||||||
|
@ -391,6 +398,96 @@ end
|
||||||
|
|
||||||
In this case, the result is similar to calling `Resource::Shirt.fabricate!`.
|
In this case, the result is similar to calling `Resource::Shirt.fabricate!`.
|
||||||
|
|
||||||
|
## Reusable resources
|
||||||
|
|
||||||
|
Reusable resources are created by the first test that needs a particular kind of resource, and then any test that needs
|
||||||
|
the same kind of resource can reuse it instead of creating a new one.
|
||||||
|
|
||||||
|
The `ReusableProject` resource is an example of this class:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
module QA
|
||||||
|
module Resource
|
||||||
|
class ReusableProject < Project # A reusable resource inherits from the resource class that we want to be able to reuse.
|
||||||
|
prepend Reusable # The Reusable module mixes in some methods that help implement reuse.
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
super # A ReusableProject is a Project so it should be initialized as one.
|
||||||
|
|
||||||
|
# Some Project attributes aren't valid and need to be overridden. For example, a ReusableProject keeps its name once it's created,
|
||||||
|
# so we don't add a random string to the name specified.
|
||||||
|
@add_name_uuid = false
|
||||||
|
|
||||||
|
# It has a default name, and a different name can be specified when a resource is first created. However, the same name must be
|
||||||
|
# provided any time that instance of the resource is used.
|
||||||
|
@name = "reusable_project"
|
||||||
|
|
||||||
|
# Several instances of a ReusableProject can exists as long as each is identified via a unique value for `reuse_as`.
|
||||||
|
@reuse_as = :default_project
|
||||||
|
end
|
||||||
|
|
||||||
|
# All reusable resource classes must validate that an instance meets the conditions that allow reuse. For example,
|
||||||
|
# by confirming that the name specified for the instance is valid and doesn't conflict with other instances.
|
||||||
|
def validate_reuse_preconditions
|
||||||
|
raise ResourceReuseError unless reused_name_valid?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Consider some examples of how a reusable resource is used:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
# This will create a project.
|
||||||
|
default_project = Resource::ReusableProject.fabricate_via_api!
|
||||||
|
default_project.name # => "reusable_project"
|
||||||
|
default_project.reuse_as # => :default_project
|
||||||
|
```
|
||||||
|
|
||||||
|
Then in another test we could reuse the project:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
# This will fetch the project created above rather than creating a new one.
|
||||||
|
default_project_again = Resource::ReusableProject.fabricate_via_api!
|
||||||
|
default_project_again.name # => "reusable_project"
|
||||||
|
default_project_again.reuse_as # => :default_project
|
||||||
|
```
|
||||||
|
|
||||||
|
We can also create another project that we want to change in a way that might not be suitable for tests using the
|
||||||
|
default project:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
project_with_member = Resource::ReusableProject.fabricate_via_api! do |project|
|
||||||
|
project.name = "project-with-member"
|
||||||
|
project.reuse_as = :project_with_member
|
||||||
|
end
|
||||||
|
|
||||||
|
project_with_member.add_member(user)
|
||||||
|
```
|
||||||
|
|
||||||
|
Another test can reuse that project:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
project_still_has_member = Resource::ReusableProject.fabricate_via_api! do |project|
|
||||||
|
project.name = "project-with-member"
|
||||||
|
project.reuse_as = :project_with_member
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(project_still_has_member).to have_member(user)
|
||||||
|
```
|
||||||
|
|
||||||
|
However, if we don't provide the name again an error will be raised:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
Resource::ReusableProject.fabricate_via_api! do |project|
|
||||||
|
project.reuse_as = :project_with_member
|
||||||
|
end
|
||||||
|
|
||||||
|
# => ResourceReuseError will be raised because it will try to use the default name, "reusable_project", which doesn't
|
||||||
|
# match the name specified when the project was first fabricated.
|
||||||
|
```
|
||||||
|
|
||||||
## Where to ask for help?
|
## Where to ask for help?
|
||||||
|
|
||||||
If you need more information, ask for help on `#quality` channel on Slack
|
If you need more information, ask for help on `#quality` channel on Slack
|
||||||
|
|
|
@ -449,17 +449,22 @@ To delete a project:
|
||||||
|
|
||||||
This action deletes a project including all associated resources (issues, merge requests, and so on).
|
This action deletes a project including all associated resources (issues, merge requests, and so on).
|
||||||
|
|
||||||
In [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) and later, on Premium or higher tiers,
|
|
||||||
group Owners can [configure](../../group/index.md#enable-delayed-project-deletion) projects in a group
|
|
||||||
to be deleted after a delayed period.
|
|
||||||
When enabled, actual deletion happens after number of days
|
|
||||||
specified in [instance settings](../../admin_area/settings/visibility_and_access_controls.md#default-deletion-delay).
|
|
||||||
|
|
||||||
WARNING:
|
WARNING:
|
||||||
The default behavior of [delayed project deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/32935) in GitLab 12.6 was changed to
|
The default deletion behavior for projects was changed to [delayed project deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/32935)
|
||||||
[Immediate deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) in GitLab 13.2.
|
in GitLab 12.6, and then to [immediate deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) in GitLab 13.2.
|
||||||
|
|
||||||
#### Delete a project immediately **(PREMIUM)**
|
#### Delayed project deletion **(PREMIUM)**
|
||||||
|
|
||||||
|
Projects in a group (not a personal namespace) can be deleted after a delay period. Multiple settings can affect whether
|
||||||
|
delayed project deletion is enabled for a particular project:
|
||||||
|
|
||||||
|
- Self-managed instance [settings](../../admin_area/settings/visibility_and_access_controls.md#default-delayed-project-deletion).
|
||||||
|
You can enable delayed project deletion as the default setting for new groups, and configure the number of days for the
|
||||||
|
delay. For GitLab.com, see the [GitLab.com settings](../../gitlab_com/index.md#delayed-project-deletion).
|
||||||
|
- Group [settings](../../group/index.md#enable-delayed-project-deletion) to enabled delayed project deletion for all
|
||||||
|
projects in the group.
|
||||||
|
|
||||||
|
##### Delete a project immediately
|
||||||
|
|
||||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/191367) in GitLab 14.1.
|
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/191367) in GitLab 14.1.
|
||||||
|
|
||||||
|
|
|
@ -16,54 +16,51 @@ A GitLab administrator [can then choose](admin_area/review_abuse_reports.md) to:
|
||||||
|
|
||||||
You can report a user through their:
|
You can report a user through their:
|
||||||
|
|
||||||
- [Profile](#reporting-abuse-through-a-users-profile)
|
- [Profile](#report-abuse-from-the-users-profile-page)
|
||||||
- [Comments](#reporting-abuse-through-a-users-comment)
|
- [Comments](#report-abuse-from-a-users-comment)
|
||||||
- [Issues and Merge requests](#reporting-abuse-through-a-users-issue-or-merge-request)
|
- [Issues and Merge requests](#report-abuse-through-a-users-issue-or-merge-request)
|
||||||
- [Snippets](snippets.md#mark-snippet-as-spam)
|
- [Snippets](snippets.md#mark-snippet-as-spam)
|
||||||
|
|
||||||
## Reporting abuse through a user's profile
|
## Report abuse from the user's profile page
|
||||||
|
|
||||||
To report abuse from a user's profile page:
|
To report abuse from a user's profile page:
|
||||||
|
|
||||||
1. Click on the exclamation point report abuse button at the top right of the
|
1. In the top right corner of the user's profile, select the exclamation point report abuse button.
|
||||||
user's profile.
|
|
||||||
1. Complete an abuse report.
|
1. Complete an abuse report.
|
||||||
1. Click the **Send report** button.
|
1. Select **Send report**.
|
||||||
|
|
||||||
## Reporting abuse through a user's comment
|
## Report abuse from a user's comment
|
||||||
|
|
||||||
To report abuse from a user's comment:
|
To report abuse from a user's comment:
|
||||||
|
|
||||||
1. Click on the vertical ellipsis (⋮) more actions button to open the dropdown.
|
1. In the comment, select the vertical ellipsis (**{ellipsis_v}**).
|
||||||
1. Select **Report as abuse**.
|
1. Select **Report abuse to admin**.
|
||||||
1. Complete an abuse report.
|
1. Complete an abuse report.
|
||||||
1. Click the **Send report** button.
|
1. Select **Send report**.
|
||||||
|
|
||||||
NOTE:
|
NOTE:
|
||||||
A URL to the reported user's comment is pre-filled in the abuse report's
|
A URL to the reported user's comment is pre-filled in the abuse report's
|
||||||
**Message** field.
|
**Message** field.
|
||||||
|
|
||||||
## Reporting abuse through a user's issue or merge request
|
## Report abuse through a user's issue or merge request
|
||||||
|
|
||||||
The **Report abuse** button is displayed at the top right of the issue or merge request:
|
The **Report abuse** button is displayed at the top right of the issue or merge request. For users
|
||||||
|
with permission to close the issue or merge request, the button is available when you select
|
||||||
- When **Report abuse** is selected from the menu that appears when the
|
**Close issue** or **Close merge request**. For all other users, it is available when viewing the
|
||||||
**Close issue** or **Close merge request** button is clicked, for users that
|
issue or
|
||||||
have permission to close the issue or merge request.
|
merge request.
|
||||||
- When viewing the issue or merge request, for users that don't have permission
|
|
||||||
to close the issue or merge request.
|
|
||||||
|
|
||||||
With the **Report abuse** button displayed, to submit an abuse report:
|
With the **Report abuse** button displayed, to submit an abuse report:
|
||||||
|
|
||||||
1. Click the **Report abuse** button.
|
1. Select **Report abuse**.
|
||||||
1. Submit an abuse report.
|
1. Submit an abuse report.
|
||||||
1. Click the **Send report** button.
|
1. Select **Send report**.
|
||||||
|
|
||||||
NOTE:
|
NOTE:
|
||||||
A URL to the reported user's issue or merge request is pre-filled
|
A URL to the reported user's issue or merge request is pre-filled
|
||||||
in the abuse report's **Message** field.
|
in the abuse report's **Message** field.
|
||||||
|
|
||||||
## Managing abuse reports
|
## Related topics
|
||||||
|
|
||||||
Administrators are able to view and resolve abuse reports.
|
- Administrators can view and resolve abuse reports.
|
||||||
For more information, see [abuse reports administration documentation](admin_area/review_abuse_reports.md).
|
For more information, see [abuse reports administration documentation](admin_area/review_abuse_reports.md).
|
||||||
|
|
|
@ -38264,6 +38264,9 @@ msgstr ""
|
||||||
msgid "View Documentation"
|
msgid "View Documentation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "View Stage: %{title}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "View alert details at"
|
msgid "View alert details at"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -7,14 +7,7 @@ module QA
|
||||||
module Resource
|
module Resource
|
||||||
module ApiFabricator
|
module ApiFabricator
|
||||||
include Capybara::DSL
|
include Capybara::DSL
|
||||||
|
include Errors
|
||||||
ResourceFabricationFailedError = Class.new(RuntimeError)
|
|
||||||
ResourceNotDeletedError = Class.new(RuntimeError)
|
|
||||||
ResourceNotFoundError = Class.new(RuntimeError)
|
|
||||||
ResourceQueryError = Class.new(RuntimeError)
|
|
||||||
ResourceUpdateFailedError = Class.new(RuntimeError)
|
|
||||||
ResourceURLMissingError = Class.new(RuntimeError)
|
|
||||||
InternalServerError = Class.new(RuntimeError)
|
|
||||||
|
|
||||||
attr_reader :api_resource, :api_response
|
attr_reader :api_resource, :api_response
|
||||||
attr_writer :api_client
|
attr_writer :api_client
|
||||||
|
|
15
qa/qa/resource/errors.rb
Normal file
15
qa/qa/resource/errors.rb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module QA
|
||||||
|
module Resource
|
||||||
|
module Errors
|
||||||
|
ResourceFabricationFailedError = Class.new(RuntimeError)
|
||||||
|
ResourceNotDeletedError = Class.new(RuntimeError)
|
||||||
|
ResourceNotFoundError = Class.new(RuntimeError)
|
||||||
|
ResourceQueryError = Class.new(RuntimeError)
|
||||||
|
ResourceUpdateFailedError = Class.new(RuntimeError)
|
||||||
|
ResourceURLMissingError = Class.new(RuntimeError)
|
||||||
|
InternalServerError = Class.new(RuntimeError)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -7,7 +7,8 @@ module QA
|
||||||
:author_name,
|
:author_name,
|
||||||
:content,
|
:content,
|
||||||
:commit_message,
|
:commit_message,
|
||||||
:name
|
:name,
|
||||||
|
:start_branch
|
||||||
attr_writer :branch
|
attr_writer :branch
|
||||||
|
|
||||||
attribute :project do
|
attribute :project do
|
||||||
|
@ -27,6 +28,7 @@ module QA
|
||||||
@name = 'QA Test - File name'
|
@name = 'QA Test - File name'
|
||||||
@content = 'QA Test - File content'
|
@content = 'QA Test - File content'
|
||||||
@commit_message = 'QA Test - Commit message'
|
@commit_message = 'QA Test - Commit message'
|
||||||
|
@start_branch = project.default_branch
|
||||||
end
|
end
|
||||||
|
|
||||||
def branch
|
def branch
|
||||||
|
@ -57,6 +59,7 @@ module QA
|
||||||
def api_post_body
|
def api_post_body
|
||||||
{
|
{
|
||||||
branch: branch,
|
branch: branch,
|
||||||
|
start_branch: start_branch,
|
||||||
author_email: @author_email || Runtime::User.default_email,
|
author_email: @author_email || Runtime::User.default_email,
|
||||||
author_name: @author_name || Runtime::User.username,
|
author_name: @author_name || Runtime::User.username,
|
||||||
content: content,
|
content: content,
|
||||||
|
|
63
qa/qa/resource/reusable.rb
Normal file
63
qa/qa/resource/reusable.rb
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module QA
|
||||||
|
module Resource
|
||||||
|
#
|
||||||
|
# This module includes methods that allow resource classes to be reused safely. It should be prepended to a new
|
||||||
|
# reusable version of an existing resource class. See Resource::Project and ReusableResource::Project for an example
|
||||||
|
#
|
||||||
|
module Reusable
|
||||||
|
attr_accessor :reuse,
|
||||||
|
:reuse_as
|
||||||
|
|
||||||
|
ResourceReuseError = Class.new(RuntimeError)
|
||||||
|
|
||||||
|
def self.prepended(base)
|
||||||
|
base.extend(ClassMethods)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Gets an existing resource if it exists and the parameters of the new specification of the resource are valid.
|
||||||
|
# Creates a new instance of the resource if it does not exist.
|
||||||
|
#
|
||||||
|
# @return [String] The URL of the resource.
|
||||||
|
def fabricate_via_api!
|
||||||
|
validate_reuse_preconditions
|
||||||
|
|
||||||
|
resource_web_url(api_get)
|
||||||
|
rescue Errors::ResourceNotFoundError
|
||||||
|
super
|
||||||
|
ensure
|
||||||
|
self.class.resources[reuse_as] = self
|
||||||
|
end
|
||||||
|
|
||||||
|
# Including classes must confirm that the resource can be reused as defined. For example, a project can't be
|
||||||
|
# fabricated with a unique name.
|
||||||
|
#
|
||||||
|
# @return [nil]
|
||||||
|
def validate_reuse_preconditions
|
||||||
|
return super if defined?(super)
|
||||||
|
|
||||||
|
raise NotImplementedError
|
||||||
|
end
|
||||||
|
|
||||||
|
module ClassMethods
|
||||||
|
# Removes all created resources of this type.
|
||||||
|
#
|
||||||
|
# @return [Hash<Symbol, QA::Resource>] the resources that were to be removed.
|
||||||
|
def remove_all_via_api!
|
||||||
|
resources.each do |reuse_as, resource|
|
||||||
|
QA::Runtime::Logger.debug("#{self.name} - removing #{reuse_as}")
|
||||||
|
resource.method(:remove_via_api!).super_method.call
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# The resources created by this resource class.
|
||||||
|
#
|
||||||
|
# @return [Hash<Symbol, QA::Resource>] the resources created by this resource class.
|
||||||
|
def resources
|
||||||
|
@resources ||= {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
45
qa/qa/resource/reusable_project.rb
Normal file
45
qa/qa/resource/reusable_project.rb
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module QA
|
||||||
|
module Resource
|
||||||
|
class ReusableProject < Project
|
||||||
|
prepend Reusable
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
super
|
||||||
|
|
||||||
|
@add_name_uuid = false
|
||||||
|
@name = "reusable_project"
|
||||||
|
@reuse_as = :default_project
|
||||||
|
@initialize_with_readme = true
|
||||||
|
end
|
||||||
|
|
||||||
|
# Confirms that the project can be reused
|
||||||
|
#
|
||||||
|
# @return [nil] returns nil unless an error is raised
|
||||||
|
def validate_reuse_preconditions
|
||||||
|
unless reused_name_unique?
|
||||||
|
raise ResourceReuseError,
|
||||||
|
"Reusable projects must have the same name. The project reused as #{reuse_as} has the name '#{name}' but it should be '#{self.class.resources[reuse_as].name}'"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Checks if the project is being reused with the same name.
|
||||||
|
#
|
||||||
|
# @return [Boolean] true if the project's name is different from another project with the same reuse symbol (reuse_as)
|
||||||
|
def reused_name_unique?
|
||||||
|
return true unless self.class.resources.key?(reuse_as)
|
||||||
|
|
||||||
|
self.class.resources[reuse_as].name == name
|
||||||
|
end
|
||||||
|
|
||||||
|
# Overrides QA::Resource::Project#remove_via_api! to log a debug message stating that removal will happen after
|
||||||
|
# the suite completes rather than now.
|
||||||
|
#
|
||||||
|
# @return [nil]
|
||||||
|
def remove_via_api!
|
||||||
|
QA::Runtime::Logger.debug("#{self.class.name} - deferring removal until after suite")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -386,20 +386,15 @@ module QA
|
||||||
def list_untracked_repositories
|
def list_untracked_repositories
|
||||||
untracked_repositories = []
|
untracked_repositories = []
|
||||||
shell "docker exec #{@praefect} bash -c 'gitlab-ctl praefect list-untracked-repositories'" do |line|
|
shell "docker exec #{@praefect} bash -c 'gitlab-ctl praefect list-untracked-repositories'" do |line|
|
||||||
# Results look like this depending on whether untracked items found or not
|
# Results look like this
|
||||||
# Running list-untracked-repositories
|
# The following repositories were found on disk, but missing from the tracking database:
|
||||||
# Done.
|
|
||||||
|
|
||||||
# Running list-untracked-repositories
|
|
||||||
# {"relative_path":"@hashed/aa/bb.git","storage":"gitaly1","virtual_storage":"default"}
|
# {"relative_path":"@hashed/aa/bb.git","storage":"gitaly1","virtual_storage":"default"}
|
||||||
# {"relative_path":"@hashed/bb/cc.git","storage":"gitaly3","virtual_storage":"default"}
|
# {"relative_path":"@hashed/bb/cc.git","storage":"gitaly3","virtual_storage":"default"}
|
||||||
# Done.
|
|
||||||
|
|
||||||
QA::Runtime::Logger.debug(line.chomp)
|
QA::Runtime::Logger.debug(line.chomp)
|
||||||
next if line.start_with?('Running list-untracked-repositories')
|
|
||||||
next if line.start_with?('Done.')
|
|
||||||
|
|
||||||
untracked_repositories.append(JSON.parse(line))
|
untracked_repositories.append(JSON.parse(line))
|
||||||
|
rescue JSON::ParserError
|
||||||
|
# Ignore lines that can't be parsed as JSON
|
||||||
end
|
end
|
||||||
|
|
||||||
QA::Runtime::Logger.debug("list_untracked_repositories --- #{untracked_repositories}")
|
QA::Runtime::Logger.debug("list_untracked_repositories --- #{untracked_repositories}")
|
||||||
|
|
|
@ -4,7 +4,10 @@ module QA
|
||||||
RSpec.describe 'Manage' do
|
RSpec.describe 'Manage' do
|
||||||
describe 'Project access token' do
|
describe 'Project access token' do
|
||||||
before(:all) do
|
before(:all) do
|
||||||
@project_access_token = QA::Resource::ProjectAccessToken.fabricate_via_api!
|
@project_access_token = QA::Resource::ProjectAccessToken.fabricate_via_api! do |pat|
|
||||||
|
pat.project = Resource::ReusableProject.fabricate_via_api!
|
||||||
|
end
|
||||||
|
|
||||||
@user_api_client = Runtime::API::Client.new(:gitlab, personal_access_token: @project_access_token.token)
|
@user_api_client = Runtime::API::Client.new(:gitlab, personal_access_token: @project_access_token.token)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -14,7 +17,7 @@ module QA
|
||||||
Resource::File.fabricate_via_api! do |file|
|
Resource::File.fabricate_via_api! do |file|
|
||||||
file.api_client = @user_api_client
|
file.api_client = @user_api_client
|
||||||
file.project = @project_access_token.project
|
file.project = @project_access_token.project
|
||||||
file.branch = 'new_branch'
|
file.branch = "new_branch_#{SecureRandom.hex(8)}"
|
||||||
file.commit_message = 'Add new file'
|
file.commit_message = 'Add new file'
|
||||||
file.name = "text-#{SecureRandom.hex(8)}.txt"
|
file.name = "text-#{SecureRandom.hex(8)}.txt"
|
||||||
file.content = 'New file'
|
file.content = 'New file'
|
||||||
|
@ -27,7 +30,7 @@ module QA
|
||||||
Resource::Repository::Commit.fabricate_via_api! do |commit|
|
Resource::Repository::Commit.fabricate_via_api! do |commit|
|
||||||
commit.api_client = @user_api_client
|
commit.api_client = @user_api_client
|
||||||
commit.project = @project_access_token.project
|
commit.project = @project_access_token.project
|
||||||
commit.branch = 'new_branch'
|
commit.branch = "new_branch_#{SecureRandom.hex(8)}"
|
||||||
commit.start_branch = @project_access_token.project.default_branch
|
commit.start_branch = @project_access_token.project.default_branch
|
||||||
commit.commit_message = 'Add new file'
|
commit.commit_message = 'Add new file'
|
||||||
commit.add_files([
|
commit.add_files([
|
||||||
|
@ -48,7 +51,7 @@ module QA
|
||||||
Resource::File.fabricate_via_api! do |file|
|
Resource::File.fabricate_via_api! do |file|
|
||||||
file.api_client = @user_api_client
|
file.api_client = @user_api_client
|
||||||
file.project = @different_project
|
file.project = @different_project
|
||||||
file.branch = 'new_branch'
|
file.branch = "new_branch_#{SecureRandom.hex(8)}"
|
||||||
file.commit_message = 'Add new file'
|
file.commit_message = 'Add new file'
|
||||||
file.name = "text-#{SecureRandom.hex(8)}.txt"
|
file.name = "text-#{SecureRandom.hex(8)}.txt"
|
||||||
file.content = 'New file'
|
file.content = 'New file'
|
||||||
|
@ -61,7 +64,7 @@ module QA
|
||||||
Resource::Repository::Commit.fabricate_via_api! do |commit|
|
Resource::Repository::Commit.fabricate_via_api! do |commit|
|
||||||
commit.api_client = @user_api_client
|
commit.api_client = @user_api_client
|
||||||
commit.project = @different_project
|
commit.project = @different_project
|
||||||
commit.branch = 'new_branch'
|
commit.branch = "new_branch_#{SecureRandom.hex(8)}"
|
||||||
commit.start_branch = @different_project.default_branch
|
commit.start_branch = @different_project.default_branch
|
||||||
commit.commit_message = 'Add new file'
|
commit.commit_message = 'Add new file'
|
||||||
commit.add_files([
|
commit.add_files([
|
||||||
|
|
|
@ -71,7 +71,7 @@ module QA
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when recovering from dataloss after failover' do
|
context 'when recovering from dataloss after failover' do
|
||||||
it 'automatically reconciles', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/238187', type: :stale }, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1266' do
|
it 'automatically reconciles', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1266' do
|
||||||
# Start the old primary node again
|
# Start the old primary node again
|
||||||
praefect_manager.start_primary_node
|
praefect_manager.start_primary_node
|
||||||
praefect_manager.wait_for_primary_node_health_check
|
praefect_manager.wait_for_primary_node_health_check
|
||||||
|
|
|
@ -11,12 +11,7 @@ module QA
|
||||||
let(:title) { "MR push options test #{SecureRandom.hex(8)}" }
|
let(:title) { "MR push options test #{SecureRandom.hex(8)}" }
|
||||||
let(:commit_message) { 'Add README.md' }
|
let(:commit_message) { 'Add README.md' }
|
||||||
|
|
||||||
let(:project) do
|
let(:project) { Resource::ReusableProject.fabricate_via_api! }
|
||||||
Resource::Project.fabricate_via_api! do |project|
|
|
||||||
project.name = 'merge-request-push-options'
|
|
||||||
project.initialize_with_readme = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def create_new_mr_via_push
|
def create_new_mr_via_push
|
||||||
Resource::Repository::ProjectPush.fabricate! do |push|
|
Resource::Repository::ProjectPush.fabricate! do |push|
|
||||||
|
|
|
@ -64,6 +64,13 @@ RSpec.configure do |config|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
config.after(:suite) do |suite|
|
||||||
|
# If any tests failed, leave the resources behind to help troubleshoot
|
||||||
|
next if suite.reporter.failed_examples.present?
|
||||||
|
|
||||||
|
QA::Resource::ReusableProject.remove_all_via_api!
|
||||||
|
end
|
||||||
|
|
||||||
config.expect_with :rspec do |expectations|
|
config.expect_with :rspec do |expectations|
|
||||||
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
||||||
end
|
end
|
||||||
|
|
|
@ -69,66 +69,9 @@ RSpec.describe Clusters::Applications::Runner do
|
||||||
expect(values).to include('privileged: true')
|
expect(values).to include('privileged: true')
|
||||||
expect(values).to include('image: ubuntu:16.04')
|
expect(values).to include('image: ubuntu:16.04')
|
||||||
expect(values).to include('resources')
|
expect(values).to include('resources')
|
||||||
expect(values).to match(/runnerToken: ['"]?#{Regexp.escape(ci_runner.token)}/)
|
|
||||||
expect(values).to match(/gitlabUrl: ['"]?#{Regexp.escape(Gitlab::Routing.url_helpers.root_url)}/)
|
expect(values).to match(/gitlabUrl: ['"]?#{Regexp.escape(Gitlab::Routing.url_helpers.root_url)}/)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'without a runner' do
|
|
||||||
let(:application) { create(:clusters_applications_runner, runner: nil, cluster: cluster) }
|
|
||||||
let(:runner) { application.runner }
|
|
||||||
|
|
||||||
shared_examples 'runner creation' do
|
|
||||||
it 'creates a runner' do
|
|
||||||
expect { subject }.to change { Ci::Runner.count }.by(1)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'uses the new runner token' do
|
|
||||||
expect(values).to match(/runnerToken: '?#{Regexp.escape(runner.token)}/)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'project cluster' do
|
|
||||||
let(:project) { create(:project) }
|
|
||||||
let(:cluster) { create(:cluster, :with_installed_helm, projects: [project]) }
|
|
||||||
|
|
||||||
include_examples 'runner creation'
|
|
||||||
|
|
||||||
it 'creates a project runner' do
|
|
||||||
subject
|
|
||||||
|
|
||||||
runner_projects = Project.where(id: runner.runner_projects.pluck(:project_id))
|
|
||||||
expect(runner).to be_project_type
|
|
||||||
expect(runner_projects).to match_array [project]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'group cluster' do
|
|
||||||
let(:group) { create(:group) }
|
|
||||||
let(:cluster) { create(:cluster, :with_installed_helm, cluster_type: :group_type, groups: [group]) }
|
|
||||||
|
|
||||||
include_examples 'runner creation'
|
|
||||||
|
|
||||||
it 'creates a group runner' do
|
|
||||||
subject
|
|
||||||
|
|
||||||
expect(runner).to be_group_type
|
|
||||||
expect(runner.runner_namespaces.pluck(:namespace_id)).to match_array [group.id]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'instance cluster' do
|
|
||||||
let(:cluster) { create(:cluster, :with_installed_helm, :instance) }
|
|
||||||
|
|
||||||
include_examples 'runner creation'
|
|
||||||
|
|
||||||
it 'creates an instance runner' do
|
|
||||||
subject
|
|
||||||
|
|
||||||
expect(runner).to be_instance_type
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with duplicated values on vendor/runner/values.yaml' do
|
context 'with duplicated values on vendor/runner/values.yaml' do
|
||||||
let(:stub_values) do
|
let(:stub_values) do
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue