Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-07-08 15:10:06 +00:00
parent dd18ae74af
commit 66a3180a3b
76 changed files with 1085 additions and 445 deletions

View File

@ -54,7 +54,6 @@ review-deploy:
extends:
- .review-workflow-base
- .review:rules:review-deploy
retry: 2
stage: review
needs: ["review-build-cng"]
resource_group: "review/${CI_COMMIT_REF_NAME}"

View File

@ -1200,19 +1200,31 @@
changes: *code-qa-patterns
allow_failure: true
# The rule needs to be duplicated between `on_success` and `on_failure`
# because the jobs `needs` the previous job to complete.
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63844#note_599012559
.review:rules:review-qa-smoke-report:
rules:
- <<: *if-not-ee
when: never
- <<: *if-dot-com-gitlab-org-merge-request
changes: *ci-review-patterns
when: always
when: on_success
- <<: *if-dot-com-gitlab-org-merge-request
changes: *ci-review-patterns
when: on_failure
- <<: *if-dot-com-gitlab-org-merge-request
changes: *frontend-patterns
when: always
when: on_success
- <<: *if-dot-com-gitlab-org-merge-request
changes: *frontend-patterns
when: on_failure
- <<: *if-dot-com-gitlab-org-merge-request
changes: *code-qa-patterns
when: always
when: on_success
- <<: *if-dot-com-gitlab-org-merge-request
changes: *code-qa-patterns
when: on_failure
.review:rules:review-qa-all:
rules:
@ -1226,6 +1238,9 @@
changes: *qa-patterns
allow_failure: true
# The rule needs to be duplicated between `on_success` and `on_failure`
# because the jobs `needs` the previous job to complete.
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63844#note_599012559
.review:rules:review-qa-all-report:
rules:
- <<: *if-not-ee
@ -1237,7 +1252,11 @@
- <<: *if-dot-com-gitlab-org-merge-request
changes: *qa-patterns
allow_failure: true
when: always
when: on_success
- <<: *if-dot-com-gitlab-org-merge-request
changes: *qa-patterns
allow_failure: true
when: on_failure
.review:rules:review-cleanup:
rules:

View File

@ -513,19 +513,59 @@ That's all of the required database changes.
end
```
##### If you added verification state fields to a separate table (option 2 above), then you need to make additional model changes
- [ ] Add the following to `spec/factories/cool_widgets.rb`:
```ruby
trait(:verification_succeeded) do
with_file
verification_checksum { 'abc' }
verification_state { CoolWidget.verification_state_value(:verification_succeeded) }
end
trait(:verification_failed) do
with_file
verification_failure { 'Could not calculate the checksum' }
verification_state { CoolWidget.verification_state_value(:verification_failed) }
end
```
- [ ] Make sure the factory also allows setting a `project` attribute. If the model does not have a direct relation to a project, you can use a `transient` attribute. Check out `spec/factories/merge_request_diffs.rb` for an example.
##### If you added verification state fields to a separate table (option 2 above), then you need to make additional model and factory changes
If you did not add verification state fields to a separate table, `cool_widget_states`, then skip to [Step 2. Implement metrics gathering](#step-2-implement-metrics-gathering).
Otherwise, you can follow [the example of Merge Request Diffs](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63309).
- [ ] Add the following lines to the `cool_widget_state.rb` model:
- [ ] Add a `Geo::CoolWidgetState` model in `ee/app/models/ee/geo/cool_widget_state.rb`:
``` ruby
class CoolWidgetState < ApplicationRecord
self.primary_key = :cool_widget_id
module Geo
class CoolWidgetState < ApplicationRecord
self.primary_key = :cool_widget_id
belongs_to :cool_widget, inverse_of: :cool_widget_state
belongs_to :cool_widget, inverse_of: :cool_widget_state
end
end
```
- [ ] Add a `factory` for `cool_widget_state`, in `ee/spec/factories/geo/cool_widget_states.rb`:
``` ruby
# frozen_string_literal: true
FactoryBot.define do
factory :geo_cool_widget_state, class: 'Geo::CoolWidgetState' do
cool_widget
trait(:checksummed) do
verification_checksum { 'abc' }
end
trait(:checksum_failure) do
verification_failure { 'Could not calculate the checksum' }
end
end
end
```
@ -540,7 +580,7 @@ Otherwise, you can follow [the example of Merge Request Diffs](https://gitlab.co
...
include ::Gitlab::Geo::VerificationState
has_one :cool_widget_state, autosave: true, inverse_of: :cool_widget
has_one :cool_widget_state, autosave: true, inverse_of: :cool_widget, class_name: 'Geo::CoolWidgetState'
delegate :verification_retry_at, :verification_retry_at=,
:verified_at, :verified_at=,
@ -577,6 +617,12 @@ Otherwise, you can follow [the example of Merge Request Diffs](https://gitlab.co
end
end
...
def cool_widget_state
super || build_cool_widget_state
end
...
end
```
@ -616,24 +662,6 @@ Metrics are gathered by `Geo::MetricsUpdateWorker`, persisted in `GeoNodeStatus`
Geo::CoolWidgetReplicator | :cool_widget | :geo_cool_widget_registry
```
- [ ] Add the following to `spec/factories/cool_widgets.rb`:
```ruby
trait(:verification_succeeded) do
with_file
verification_checksum { 'abc' }
verification_state { CoolWidget.verification_state_value(:verification_succeeded) }
end
trait(:verification_failed) do
with_file
verification_failure { 'Could not calculate the checksum' }
verification_state { CoolWidget.verification_state_value(:verification_failed) }
end
```
- [ ] Make sure the factory also allows setting a `project` attribute. If the model does not have a direct relation to a project, you can use a `transient` attribute. Check out `spec/factories/merge_request_diffs.rb` for an example.
Cool Widget replication and verification metrics should now be available in the API, the `Admin > Geo > Nodes` view, and Prometheus.
#### Step 3. Implement the GraphQL API

View File

@ -480,19 +480,59 @@ That's all of the required database changes.
end
```
##### If you added verification state fields to a separate table (option 2 above), then you need to make additional model changes
- [ ] Add the following to `spec/factories/cool_widgets.rb`:
```ruby
trait(:verification_succeeded) do
with_file
verification_checksum { 'abc' }
verification_state { CoolWidget.verification_state_value(:verification_succeeded) }
end
trait(:verification_failed) do
with_file
verification_failure { 'Could not calculate the checksum' }
verification_state { CoolWidget.verification_state_value(:verification_failed) }
end
```
- [ ] Make sure the factory also allows setting a `project` attribute. If the model does not have a direct relation to a project, you can use a `transient` attribute. Check out `spec/factories/merge_request_diffs.rb` for an example.
##### If you added verification state fields to a separate table (option 2 above), then you need to make additional model and factory changes
If you did not add verification state fields to a separate table, `cool_widget_states`, then skip to [Step 2. Implement metrics gathering](#step-2-implement-metrics-gathering).
Otherwise, you can follow [the example of Merge Request Diffs](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63309).
- [ ] Add the following lines to the `cool_widget_state.rb` model:
- [ ] Add a `Geo::CoolWidgetState` model in `ee/app/models/ee/geo/cool_widget_state.rb`:
``` ruby
class CoolWidgetState < ApplicationRecord
self.primary_key = :cool_widget_id
module Geo
class CoolWidgetState < ApplicationRecord
self.primary_key = :cool_widget_id
belongs_to :cool_widget, inverse_of: :cool_widget_state
belongs_to :cool_widget, inverse_of: :cool_widget_state
end
end
```
- [ ] Add a `factory` for `cool_widget_state`, in `ee/spec/factories/geo/cool_widget_states.rb`:
``` ruby
# frozen_string_literal: true
FactoryBot.define do
factory :geo_cool_widget_state, class: 'Geo::CoolWidgetState' do
cool_widget
trait(:checksummed) do
verification_checksum { 'abc' }
end
trait(:checksum_failure) do
verification_failure { 'Could not calculate the checksum' }
end
end
end
```
@ -507,7 +547,7 @@ Otherwise, you can follow [the example of Merge Request Diffs](https://gitlab.co
...
include ::Gitlab::Geo::VerificationState
has_one :cool_widget_state, autosave: true, inverse_of: :cool_widget
has_one :cool_widget_state, autosave: true, inverse_of: :cool_widget, class_name: 'Geo::CoolWidgetState'
delegate :verification_retry_at, :verification_retry_at=,
:verified_at, :verified_at=,
@ -544,6 +584,12 @@ Otherwise, you can follow [the example of Merge Request Diffs](https://gitlab.co
end
end
...
def cool_widget_state
super || build_cool_widget_state
end
...
end
```
@ -583,24 +629,6 @@ Metrics are gathered by `Geo::MetricsUpdateWorker`, persisted in `GeoNodeStatus`
Geo::CoolWidgetReplicator | :cool_widget | :geo_cool_widget_registry
```
- [ ] Add the following to `spec/factories/cool_widgets.rb`:
```ruby
trait(:verification_succeeded) do
with_file
verification_checksum { 'abc' }
verification_state { CoolWidget.verification_state_value(:verification_succeeded) }
end
trait(:verification_failed) do
with_file
verification_failure { 'Could not calculate the checksum' }
verification_state { CoolWidget.verification_state_value(:verification_failed) }
end
```
- [ ] Make sure the factory also allows setting a `project` attribute. If the model does not have a direct relation to a project, you can use a `transient` attribute. Check out `spec/factories/merge_request_diffs.rb` for an example.
Cool Widget replication and verification metrics should now be available in the API, the `Admin > Geo > Nodes` view, and Prometheus.
#### Step 3. Implement the GraphQL API

View File

@ -2,6 +2,19 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
## 14.0.5 (2021-07-08)
### Fixed (4 changes)
- [Return empty strings for Jira links when URL is not set](gitlab-org/gitlab@6da7890d8137b1879297ad81c6737312d6f672b3) ([merge request](gitlab-org/gitlab!65728))
- [Add prefix to autocomplete path](gitlab-org/gitlab@5256ab7db346610a816ebb975ae9a6ce0d853435) ([merge request](gitlab-org/gitlab!65728))
- [Do not create audit event for failed logins on read-only DB](gitlab-org/gitlab@30c7944ddddfe92566b3f66a7f549bef3ffd8d82) ([merge request](gitlab-org/gitlab!65728)) **GitLab Enterprise Edition**
- [Fix git clone for projects with a trailing dot over HTTP](gitlab-org/gitlab@a91be9412a09b069390cc33c14d1bc72216cdbf0) ([merge request](gitlab-org/gitlab!65728))
### Other (1 change)
- [Initialize conversion of ci_builds_metadata.id for bigint migration](gitlab-org/gitlab@34522b102be43118063aa3245d23af313173700d) ([merge request](gitlab-org/gitlab!65728))
## 14.0.4 (2021-07-07)
### Security (1 change)

View File

@ -88,12 +88,12 @@ export const moveSubItemsToPosition = (el, subItems) => {
const boundingRect = el.getBoundingClientRect();
const left = sidebar ? sidebar.offsetWidth : COLLAPSED_PANEL_WIDTH;
let top = calculateTop(boundingRect, subItems.offsetHeight);
const isAbove = top < boundingRect.top;
if (hasSubItems) {
top -= header.offsetHeight;
top = isAbove ? top : top - header.offsetHeight;
} else {
top = boundingRect.top;
}
const isAbove = top <= boundingRect.top;
subItems.classList.add('fly-out-list');
subItems.style.transform = `translate3d(${left}px, ${Math.floor(top) - getHeaderHeight()}px, 0)`; // eslint-disable-line no-param-reassign

View File

@ -90,6 +90,10 @@ export const PACKAGE_TYPES = [
title: s__('PackageRegistry|Debian'),
type: PackageType.DEBIAN,
},
{
title: s__('PackageRegistry|Helm'),
type: PackageType.HELM,
},
];
export const LIST_TITLE_TEXT = s__('PackageRegistry|Package Registry');

View File

@ -10,6 +10,7 @@ export const PackageType = {
RUBYGEMS: 'rubygems',
GENERIC: 'generic',
DEBIAN: 'debian',
HELM: 'helm',
};
// we want this separated from the main dictionary to avoid it being pulled in the search of package

View File

@ -27,6 +27,8 @@ export const getPackageTypeLabel = (packageType) => {
return s__('PackageRegistry|Generic');
case PackageType.DEBIAN:
return s__('PackageRegistry|Debian');
case PackageType.HELM:
return s__('PackageRegistry|Helm');
default:
return null;
}

View File

@ -88,8 +88,6 @@ export default {
return {
...this.value,
cadence: this.findDefaultOption('cadence'),
keepN: this.findDefaultOption('keepN'),
olderThan: this.findDefaultOption('olderThan'),
};
},
showLoadingIcon() {

View File

@ -11,11 +11,14 @@ export const olderThanTranslationGenerator = (variable) => n__('%d day', '%d day
export const keepNTranslationGenerator = (variable) =>
n__('%d tag per image name', '%d tags per image name', variable);
export const optionLabelGenerator = (collection, translationFn) =>
collection.map((option) => ({
export const optionLabelGenerator = (collection, translationFn) => {
const result = collection.map((option) => ({
...option,
label: translationFn(option.variable),
}));
result.unshift({ key: null, label: '' });
return result;
};
export const formOptionsGenerator = () => {
return {

View File

@ -30,7 +30,7 @@ export default {
};
</script>
<template>
<div class="container">
<div class="container gl-display-flex gl-flex-direction-column">
<h2 class="gl-my-7 gl-font-size-h1 gl-text-center">
{{ title }}
</h2>

View File

@ -316,6 +316,10 @@
a.has-sub-items + .sidebar-sub-level-items.fly-out-list {
@include gl-mt-n2;
&.is-above {
@include gl-mt-2;
}
}
@media (min-width: map-get($grid-breakpoints, md)) and (max-width: map-get($grid-breakpoints, xl) - 1px) {

View File

@ -15,6 +15,7 @@ module Resolvers
type Types::IssueType.connection_type, null: true
NON_STABLE_CURSOR_SORTS = %i[priority_asc priority_desc
popularity_asc popularity_desc
label_priority_asc label_priority_desc
milestone_due_asc milestone_due_desc].freeze

View File

@ -10,6 +10,8 @@ module Types
value 'RELATIVE_POSITION_ASC', 'Relative position by ascending order.', value: :relative_position_asc
value 'SEVERITY_ASC', 'Severity from less critical to more critical.', value: :severity_asc
value 'SEVERITY_DESC', 'Severity from more critical to less critical.', value: :severity_desc
value 'POPULARITY_ASC', 'Number of upvotes (awarded "thumbs up" emoji) by ascending order.', value: :popularity_asc
value 'POPULARITY_DESC', 'Number of upvotes (awarded "thumbs up" emoji) by descending order.', value: :popularity_desc
end
end

View File

@ -76,18 +76,22 @@ module Integrations
'buildkite'
end
def help
s_('ProjectService|Run CI/CD pipelines with Buildkite.')
end
def fields
[
{ type: 'text',
name: 'token',
title: 'Integration Token',
help: 'This token will be provided when you create a Buildkite pipeline with a GitLab repository',
title: _('Token'),
help: s_('ProjectService|The token you get after you create a Buildkite pipeline with a GitLab repository.'),
required: true },
{ type: 'text',
name: 'project_url',
title: 'Pipeline URL',
placeholder: "#{ENDPOINT}/acme-inc/test-pipeline",
title: _('Pipeline URL'),
placeholder: "#{ENDPOINT}/example-org/test-pipeline",
required: true }
]
end

View File

@ -0,0 +1,37 @@
# frozen_string_literal: true
module Ci
module Pipelines
class AddJobService
attr_reader :pipeline
def initialize(pipeline)
@pipeline = pipeline
raise ArgumentError, "Pipeline must be persisted for this service to be used" unless @pipeline.persisted?
end
def execute!(job, &block)
assign_pipeline_attributes(job)
Ci::Pipeline.transaction do
yield(job)
job.update_older_statuses_retried! if Feature.enabled?(:ci_fix_commit_status_retried, @pipeline.project, default_enabled: :yaml)
end
ServiceResponse.success(payload: { job: job })
rescue StandardError => e
ServiceResponse.error(message: e.message, payload: { job: job })
end
private
def assign_pipeline_attributes(job)
job.pipeline = @pipeline
job.project = @pipeline.project
job.ref = @pipeline.ref
end
end
end
end

View File

@ -34,18 +34,15 @@ module Ci
def reprocess!(build)
check_access!(build)
attributes = self.class.clone_accessors.to_h do |attribute|
[attribute, build.public_send(attribute)] # rubocop:disable GitlabSecurity/PublicSend
end
attributes[:user] = current_user
Ci::Build.transaction do
create_build!(attributes).tap do |new_build|
new_build.update_older_statuses_retried!
build.reset # refresh the data to get new values of `retried` and `processed`.
new_build = clone_build(build)
::Ci::Pipelines::AddJobService.new(build.pipeline).execute!(new_build) do |job|
BulkInsertableAssociations.with_bulk_insert do
job.save!
end
end
build.reset # refresh the data to get new values of `retried` and `processed`.
new_build
end
# rubocop: enable CodeReuse/ActiveRecord
@ -59,13 +56,19 @@ module Ci
def check_assignable_runners!(build); end
def create_build!(attributes)
build = project.builds.new(attributes)
build.assign_attributes(::Gitlab::Ci::Pipeline::Seed::Build.environment_attributes_for(build))
BulkInsertableAssociations.with_bulk_insert do
build.save!
def clone_build(build)
project.builds.new(build_attributes(build)).tap do |new_build|
new_build.assign_attributes(::Gitlab::Ci::Pipeline::Seed::Build.environment_attributes_for(new_build))
end
build
end
def build_attributes(build)
attributes = self.class.clone_accessors.to_h do |attribute|
[attribute, build.public_send(attribute)] # rubocop:disable GitlabSecurity/PublicSend
end
attributes[:user] = current_user
attributes
end
end
end

View File

@ -31,10 +31,11 @@ module Projects
register_attempt
# Create status notifying the deployment of pages
@status = create_status
@status.update_older_statuses_retried! if Feature.enabled?(:ci_fix_commit_status_retried, project, default_enabled: :yaml)
@status.enqueue!
@status.run!
@status = build_commit_status
::Ci::Pipelines::AddJobService.new(@build.pipeline).execute!(@status) do |job|
job.enqueue!
job.run!
end
raise InvalidStateError, 'missing pages artifacts' unless build.artifacts?
raise InvalidStateError, 'build SHA is outdated for this ref' unless latest?
@ -70,12 +71,9 @@ module Projects
super
end
def create_status
def build_commit_status
GenericCommitStatus.new(
project: project,
pipeline: build.pipeline,
user: build.user,
ref: build.ref,
stage: 'deploy',
name: 'pages:deploy'
)

View File

@ -64,6 +64,6 @@
= f.text_field :default_ci_config_path, class: 'form-control gl-form-input', placeholder: '.gitlab-ci.yml'
%p.form-text.text-muted
= _("The default CI/CD configuration file and path for new projects.").html_safe
= link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'custom-cicd-configuration-file'), target: '_blank'
= link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'specify-a-custom-cicd-configuration-file'), target: '_blank'
= f.submit _('Save changes'), class: "gl-button btn btn-confirm"

View File

@ -10,7 +10,7 @@
%strong= _("Public pipelines")
.form-text.text-muted
= _("Allow public access to pipelines and job details, including output logs and artifacts.")
= link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'visibility-of-pipelines'), target: '_blank'
= link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'change-which-users-can-view-your-pipelines'), target: '_blank'
.form-group
.form-check
@ -36,7 +36,7 @@
= f.text_field :ci_config_path, class: 'form-control', placeholder: '.gitlab-ci.yml'
%p.form-text.text-muted
= html_escape(_("The name of the CI/CD configuration file. A path relative to the root directory is optional (for example %{code_open}my/path/.myfile.yml%{code_close}).")) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
= link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'custom-cicd-configuration-file'), target: '_blank'
= link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'specify-a-custom-cicd-configuration-file'), target: '_blank'
%hr
.form-group
@ -44,7 +44,7 @@
= _("Git strategy")
%p
= _("Choose which Git strategy to use when fetching the project.")
= link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'git-strategy'), target: '_blank'
= link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'choose-the-default-git-strategy'), target: '_blank'
.form-check
= f.radio_button :build_allow_git_fetch, 'false', { class: 'form-check-input' }
= f.label :build_allow_git_fetch_false, class: 'form-check-label' do
@ -66,7 +66,7 @@
= form.number_field :default_git_depth, { class: 'form-control gl-form-input', min: 0, max: 1000 }
%p.form-text.text-muted
= html_escape(_('The number of changes to fetch from GitLab when cloning a repository. Lower values can speed up pipeline execution. Set to %{code_open}0%{code_close} or blank to fetch all branches and tags for each job')) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
= link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'git-shallow-clone'), target: '_blank'
= link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'limit-the-number-of-changes-fetched-during-clone'), target: '_blank'
%hr
.form-group

View File

@ -1,8 +0,0 @@
---
name: load_balancing_improved_caught_up_hosts_check
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65248
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/334989
milestone: '14.1'
type: development
group: group::memory
default_enabled: false

View File

@ -27,7 +27,7 @@ relevant compliance standards.
|**[Audit events](audit_events.md)**<br>To maintain the integrity of your code, GitLab Enterprise Edition Premium gives administrators the ability to view any modifications made within the GitLab server in an advanced audit events system, so you can control, analyze, and track every change. | Premium+ | **{check-circle}** Yes | Instance, Group, Project |
|**[Auditor users](auditor_users.md)**<br>Auditor users are users who are given read-only access to all projects, groups, and other resources on the GitLab instance. | Premium+ | **{dotted-circle}** No | Instance |
|**[Credentials inventory](../user/admin_area/credentials_inventory.md)**<br>With a credentials inventory, GitLab administrators can keep track of the credentials used by all of the users in their GitLab instance. | Ultimate | **{dotted-circle}** No | Instance |
|**Separation of Duties using [Protected branches](../user/project/protected_branches.md#require-code-owner-approval-on-a-protected-branch) and [custom CI Configuration Paths](../ci/pipelines/settings.md#custom-cicd-configuration-file)**<br> GitLab Premium users can leverage the GitLab cross-project YAML configurations to define deployers of code and developers of code. View the [Separation of Duties Deploy Project](https://gitlab.com/guided-explorations/separation-of-duties-deploy/blob/master/README.md) and [Separation of Duties Project](https://gitlab.com/guided-explorations/separation-of-duties/blob/master/README.md) to see how to use this set up to define these roles. | Premium+ | **{check-circle}** Yes | Project |
|**Separation of Duties using [Protected branches](../user/project/protected_branches.md#require-code-owner-approval-on-a-protected-branch) and [custom CI Configuration Paths](../ci/pipelines/settings.md#specify-a-custom-cicd-configuration-file)**<br> GitLab Premium users can leverage the GitLab cross-project YAML configurations to define deployers of code and developers of code. View the [Separation of Duties Deploy Project](https://gitlab.com/guided-explorations/separation-of-duties-deploy/blob/master/README.md) and [Separation of Duties Project](https://gitlab.com/guided-explorations/separation-of-duties/blob/master/README.md) to see how to use this set up to define these roles. | Premium+ | **{check-circle}** Yes | Project |
|**[Compliance frameworks](../user/project/settings/index.md#compliance-frameworks)**<br>Create a custom compliance framework at the group level to describe the type of compliance requirements any child project needs to follow. | Premium+ | **{check-circle}** Yes | Group |
|**[Compliance pipelines](../user/project/settings/index.md#compliance-pipeline-configuration)**<br>Define a pipeline configuration to run for any projects with a given compliance framework. | Ultimate | **{check-circle}** Yes | Group |
|**[Compliance dashboard](../user/compliance/compliance_dashboard/index.md)**<br>Quickly get visibility into the compliance posture of your organization. | Ultimate | **{check-circle}** Yes | Group |

View File

@ -9,24 +9,24 @@ type: howto
These instructions assume you have a working instance of GitLab. They guide you through:
1. Making your existing instance the **primary** node.
1. Adding **secondary** nodes.
1. Making your existing instance the **primary** site.
1. Adding **secondary** site(s).
WARNING:
The steps below should be followed in the order they appear. **Make sure the GitLab version is the same on all nodes.**
The steps below should be followed in the order they appear. **Make sure the GitLab version is the same on all sites.**
## Using Omnibus GitLab
If you installed GitLab using the Omnibus packages (highly recommended):
1. [Install GitLab Enterprise Edition](https://about.gitlab.com/install/) on the server that will serve as the **secondary** node. Do not create an account or log in to the new **secondary** node.
1. [Upload the GitLab License](../../../user/admin_area/license.md) on the **primary** node to unlock Geo. The license must be for [GitLab Premium](https://about.gitlab.com/pricing/) or higher.
1. [Install GitLab Enterprise Edition](https://about.gitlab.com/install/) on the node(s) that will serve as the **secondary** site. Do not create an account or log in to the new **secondary** site.
1. [Upload the GitLab License](../../../user/admin_area/license.md) on the **primary** site to unlock Geo. The license must be for [GitLab Premium](https://about.gitlab.com/pricing/) or higher.
1. [Set up the database replication](database.md) (`primary (read-write) <-> secondary (read-only)` topology).
1. [Configure fast lookup of authorized SSH keys in the database](../../operations/fast_ssh_key_lookup.md). This step is required and needs to be done on **both** the **primary** and **secondary** nodes.
1. [Configure GitLab](../replication/configuration.md) to set the **primary** and **secondary** nodes.
1. Optional: [Configure a secondary LDAP server](../../auth/ldap/index.md) for the **secondary** node. See [notes on LDAP](../index.md#ldap).
1. [Configure fast lookup of authorized SSH keys in the database](../../operations/fast_ssh_key_lookup.md). This step is required and needs to be done on **both** the **primary** and **secondary** site(s).
1. [Configure GitLab](../replication/configuration.md) to set the **primary** and **secondary** site(s).
1. Optional: [Configure a secondary LDAP server](../../auth/ldap/index.md) for the **secondary** site(s). See [notes on LDAP](../index.md#ldap).
1. Follow the [Using a Geo Site](../replication/usage.md) guide.
## Post-installation documentation
After installing GitLab on the **secondary** nodes and performing the initial configuration, see the [following documentation for post-installation information](../index.md#post-installation-documentation).
After installing GitLab on the **secondary** site(s) and performing the initial configuration, see the [following documentation for post-installation information](../index.md#post-installation-documentation).

View File

@ -8891,6 +8891,7 @@ Relationship between an epic and an issue.
| <a id="epicissueblocked"></a>`blocked` | [`Boolean!`](#boolean) | Indicates the issue is blocked. |
| <a id="epicissueblockedbycount"></a>`blockedByCount` | [`Int`](#int) | Count of issues blocking this issue. |
| <a id="epicissueblockedbyissues"></a>`blockedByIssues` | [`IssueConnection`](#issueconnection) | Issues blocking this issue. (see [Connections](#connections)) |
| <a id="epicissueblockingcount"></a>`blockingCount` | [`Int!`](#int) | Count of issues this issue is blocking. |
| <a id="epicissueclosedat"></a>`closedAt` | [`Time`](#time) | Timestamp of when the issue was closed. |
| <a id="epicissueconfidential"></a>`confidential` | [`Boolean!`](#boolean) | Indicates the issue is confidential. |
| <a id="epicissuecreatenoteemail"></a>`createNoteEmail` | [`String`](#string) | User specific email address for the issue. |
@ -9945,6 +9946,7 @@ Returns [`VulnerabilitySeveritiesCount`](#vulnerabilityseveritiescount).
| <a id="issueblocked"></a>`blocked` | [`Boolean!`](#boolean) | Indicates the issue is blocked. |
| <a id="issueblockedbycount"></a>`blockedByCount` | [`Int`](#int) | Count of issues blocking this issue. |
| <a id="issueblockedbyissues"></a>`blockedByIssues` | [`IssueConnection`](#issueconnection) | Issues blocking this issue. (see [Connections](#connections)) |
| <a id="issueblockingcount"></a>`blockingCount` | [`Int!`](#int) | Count of issues this issue is blocking. |
| <a id="issueclosedat"></a>`closedAt` | [`Time`](#time) | Timestamp of when the issue was closed. |
| <a id="issueconfidential"></a>`confidential` | [`Boolean!`](#boolean) | Indicates the issue is confidential. |
| <a id="issuecreatenoteemail"></a>`createNoteEmail` | [`String`](#string) | User specific email address for the issue. |
@ -10957,6 +10959,7 @@ Represents the network policy.
| <a id="networkpolicyenabled"></a>`enabled` | [`Boolean!`](#boolean) | Indicates whether this policy is enabled. |
| <a id="networkpolicyenvironments"></a>`environments` | [`EnvironmentConnection`](#environmentconnection) | Environments where this policy is applied. (see [Connections](#connections)) |
| <a id="networkpolicyfromautodevops"></a>`fromAutoDevops` | [`Boolean!`](#boolean) | Indicates whether this policy is created from AutoDevops. |
| <a id="networkpolicykind"></a>`kind` | [`NetworkPolicyKind!`](#networkpolicykind) | Kind of the policy. |
| <a id="networkpolicyname"></a>`name` | [`String!`](#string) | Name of the policy. |
| <a id="networkpolicynamespace"></a>`namespace` | [`String!`](#string) | Namespace of the policy. |
| <a id="networkpolicyupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp of when the policy YAML was last updated. |
@ -14610,6 +14613,8 @@ Values for sorting issues.
| Value | Description |
| ----- | ----------- |
| <a id="issuesortblocking_issues_asc"></a>`BLOCKING_ISSUES_ASC` | Blocking issues count by ascending order. |
| <a id="issuesortblocking_issues_desc"></a>`BLOCKING_ISSUES_DESC` | Blocking issues count by descending order. |
| <a id="issuesortcreated_asc"></a>`CREATED_ASC` | Created at ascending order. |
| <a id="issuesortcreated_desc"></a>`CREATED_DESC` | Created at descending order. |
| <a id="issuesortdue_date_asc"></a>`DUE_DATE_ASC` | Due date by ascending order. |
@ -14618,6 +14623,8 @@ Values for sorting issues.
| <a id="issuesortlabel_priority_desc"></a>`LABEL_PRIORITY_DESC` | Label priority by descending order. |
| <a id="issuesortmilestone_due_asc"></a>`MILESTONE_DUE_ASC` | Milestone due date by ascending order. |
| <a id="issuesortmilestone_due_desc"></a>`MILESTONE_DUE_DESC` | Milestone due date by descending order. |
| <a id="issuesortpopularity_asc"></a>`POPULARITY_ASC` | Number of upvotes (awarded "thumbs up" emoji) by ascending order. |
| <a id="issuesortpopularity_desc"></a>`POPULARITY_DESC` | Number of upvotes (awarded "thumbs up" emoji) by descending order. |
| <a id="issuesortpriority_asc"></a>`PRIORITY_ASC` | Priority by ascending order. |
| <a id="issuesortpriority_desc"></a>`PRIORITY_DESC` | Priority by descending order. |
| <a id="issuesortpublished_asc"></a>`PUBLISHED_ASC` | Published issues shown last. |
@ -14886,6 +14893,15 @@ Negated Iteration ID wildcard values.
| ----- | ----------- |
| <a id="negatediterationwildcardidcurrent"></a>`CURRENT` | Current iteration. |
### `NetworkPolicyKind`
Kind of the network policy.
| Value | Description |
| ----- | ----------- |
| <a id="networkpolicykindciliumnetworkpolicy"></a>`CiliumNetworkPolicy` | The policy kind of Cilium Network Policy. |
| <a id="networkpolicykindnetworkpolicy"></a>`NetworkPolicy` | The policy kind of Network Policy. |
### `OncallRotationUnitEnum`
Rotation length unit of an on-call rotation.

View File

@ -1326,7 +1326,7 @@ PUT /projects/:id
| `build_timeout` | integer | **{dotted-circle}** No | The maximum amount of time, in seconds, that a job can run. |
| `builds_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `ci_config_path` | string | **{dotted-circle}** No | The path to CI configuration file. |
| `ci_default_git_depth` | integer | **{dotted-circle}** No | Default number of revisions for [shallow cloning](../ci/pipelines/settings.md#git-shallow-clone). |
| `ci_default_git_depth` | integer | **{dotted-circle}** No | Default number of revisions for [shallow cloning](../ci/pipelines/settings.md#limit-the-number-of-changes-fetched-during-clone). |
| `ci_forward_deployment_enabled` | boolean | **{dotted-circle}** No | When a new deployment job starts, [skip older deployment jobs](../ci/pipelines/settings.md#skip-outdated-deployment-jobs) that are still pending |
| `container_expiration_policy_attributes` | hash | **{dotted-circle}** No | Update the image cleanup policy for this project. Accepts: `cadence` (string), `keep_n` (integer), `older_than` (string), `name_regex` (string), `name_regex_delete` (string), `name_regex_keep` (string), `enabled` (boolean). |
| `container_registry_enabled` | boolean | **{dotted-circle}** No | Enable container registry for this project. |

View File

@ -141,7 +141,7 @@ reference a file in another project with a completely different set of permissio
In this scenario, the `gitlab-ci.yml` is publicly accessible, but can only be edited by users with
appropriate permissions in the other project.
For more information, see [Custom CI/CD configuration path](../pipelines/settings.md#custom-cicd-configuration-file).
For more information, see [Custom CI/CD configuration path](../pipelines/settings.md#specify-a-custom-cicd-configuration-file).
## Troubleshooting

View File

@ -70,14 +70,14 @@ GitLab CI/CD supports numerous configuration options:
| Configuration | Description |
|:----------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------|
| [Schedule pipelines](pipelines/schedules.md) | Schedule pipelines to run as often as you need. |
| [Custom path for `.gitlab-ci.yml`](pipelines/settings.md#custom-cicd-configuration-file) | Define a custom path for the CI/CD configuration file. |
| [Custom path for `.gitlab-ci.yml`](pipelines/settings.md#specify-a-custom-cicd-configuration-file) | Define a custom path for the CI/CD configuration file. |
| [Git submodules for CI/CD](git_submodules.md) | Configure jobs for using Git submodules. |
| [SSH keys for CI/CD](ssh_keys/index.md) | Using SSH keys in your CI pipelines. |
| [Pipeline triggers](triggers/index.md) | Trigger pipelines through the API. |
| [Pipelines for Merge Requests](pipelines/merge_request_pipelines.md) | Design a pipeline structure for running a pipeline in merge requests. |
| [SSH keys for CI/CD](ssh_keys/index.md) | Using SSH keys in your CI pipelines. |
| [Pipeline triggers](triggers/index.md) | Trigger pipelines through the API. |
| [Pipelines for Merge Requests](pipelines/merge_request_pipelines.md) | Design a pipeline structure for running a pipeline in merge requests. |
| [Integrate with Kubernetes clusters](../user/project/clusters/index.md) | Connect your project to Google Kubernetes Engine (GKE) or an existing Kubernetes cluster. |
| [Optimize GitLab and GitLab Runner for large repositories](large_repositories/index.md) | Recommended strategies for handling large repositories. |
| [`.gitlab-ci.yml` full reference](yaml/index.md) | All the attributes you can use with GitLab CI/CD. |
| [`.gitlab-ci.yml` full reference](yaml/index.md) | All the attributes you can use with GitLab CI/CD. |
Note that certain operations can only be performed according to the
[user](../user/permissions.md#gitlab-cicd-permissions) and [job](../user/permissions.md#job-permissions) permissions.

View File

@ -28,7 +28,7 @@ Each guideline is described in more detail in the sections below:
> Introduced in GitLab Runner 8.9.
GitLab and GitLab Runner perform a [shallow clone](../pipelines/settings.md#git-shallow-clone)
GitLab and GitLab Runner perform a [shallow clone](../pipelines/settings.md#limit-the-number-of-changes-fetched-during-clone)
by default.
Ideally, you should always use `GIT_DEPTH` with a small number

View File

@ -14,49 +14,48 @@ You can customize how pipelines run for your project.
For an overview of pipelines, watch the video [GitLab CI Pipeline, Artifacts, and Environments](https://www.youtube.com/watch?v=PCKDICEe10s).
Watch also [GitLab CI pipeline tutorial for beginners](https://www.youtube.com/watch?v=Jav4vbUrqII).
## Visibility of pipelines
## Change which users can view your pipelines
Pipeline visibility is determined by:
- Your current [user access level](../../user/permissions.md).
- The **Public pipelines** project setting under your project's **Settings > CI/CD > General pipelines**.
NOTE:
If the project visibility is set to **Private**, the [**Public pipelines** setting has no effect](../enable_or_disable_ci.md#per-project-user-setting).
This also determines the visibility of these related features:
For public and internal projects, you can change who can see your:
- Pipelines
- Job output logs
- Job artifacts
- The [pipeline security dashboard](../../user/application_security/security_dashboard/index.md#pipeline-security) **(ULTIMATE)**
- [Pipeline security dashboard](../../user/application_security/security_dashboard/index.md#pipeline-security)
Job logs and artifacts are [not visible for guest users and non-project members](https://gitlab.com/gitlab-org/gitlab/-/issues/25649).
However:
If **Public pipelines** is enabled (default):
- Job output logs and artifacts are [never visible for Guest users and non-project members](https://gitlab.com/gitlab-org/gitlab/-/issues/25649).
- For **public** projects, anyone can view the pipelines and related features.
- For **internal** projects, any logged in user except [external users](../../user/permissions.md#external-users) can view the pipelines
and related features.
- For **private** projects, any project member (Guest or higher) can view the pipelines
and related features.
To change the visibility of your pipelines and related features:
If **Public pipelines** is disabled:
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Settings > CI/CD**.
1. Expand **General pipelines**.
1. Select or clear the **Public pipelines** checkbox.
When it is selected, pipelines and related features are visible:
- For **public** projects, anyone can view the pipelines, but only members
(Reporter or higher) can access the related features.
- For **internal** projects, any logged in user except [external users](../../user/permissions.md#external-users) can view the pipelines.
However, only members (reporter or higher) can access the job related features.
- For **private** projects, only project members (reporter or higher)
can view the pipelines or access the related features.
- For **public** projects, to everyone.
- For **internal** projects, to all logged-in users except [external users](../../user/permissions.md#external-users).
- For **private** projects, to all project members (Guest or higher).
When it is cleared:
- For **public** projects, pipelines are visible to everyone. Related features are visible
only to project members (Reporter or higher).
- For **internal** projects, pipelines are visible to all logged in users except [external users](../../user/permissions.md#external-users).
Related features are visible only to project members (Reporter or higher).
- For **private** projects, pipelines and related features are visible to project members (Reporter or higher) only.
## Auto-cancel redundant pipelines
You can set pending or running pipelines to cancel automatically when a new pipeline runs on the same branch. You can enable this in the project settings:
1. Go to **Settings > CI/CD**.
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Settings > CI/CD**.
1. Expand **General Pipelines**.
1. Check the **Auto-cancel redundant pipelines** checkbox.
1. Click **Save changes**.
1. Select the **Auto-cancel redundant pipelines** checkbox.
1. Select **Save changes**.
Use the [`interruptible`](../yaml/index.md#interruptible) keyword to indicate if a
running job can be cancelled before it completes.
@ -73,12 +72,13 @@ newer one, which may not be what you want.
To avoid this scenario:
1. Go to **Settings > CI/CD**.
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Settings > CI/CD**.
1. Expand **General pipelines**.
1. Check the **Skip outdated deployment jobs** checkbox.
1. Click **Save changes**.
1. Select the **Skip outdated deployment jobs** checkbox.
1. Select **Save changes**.
When enabled, any older deployments job are skipped when a new deployment starts.
Older deployment job are skipped when a new deployment starts.
For more information, see [Deployment safety](../environments/deployment_safety.md).
@ -92,78 +92,86 @@ about this and asks for confirmation.
For more information, see [Deployment safety](../environments/deployment_safety.md).
## Custom CI/CD configuration file
## Specify a custom CI/CD configuration file
> [Support for external `.gitlab-ci.yml` locations](https://gitlab.com/gitlab-org/gitlab/-/issues/14376) introduced in GitLab 12.6.
By default we look for the `.gitlab-ci.yml` file in the project's root
directory. If needed, you can specify an alternate path and filename, including locations outside the project.
GitLab expects to find the CI/CD configuration file (`.gitlab-ci.yml`) in the project's root
directory. However, you can specify an alternate filename path, including locations outside the project.
To customize the path:
1. Go to the project's **Settings > CI/CD**.
1. Expand the **General pipelines** section.
1. Provide a value in the **CI/CD configuration file** field.
1. Click **Save changes**.
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Settings > CI/CD**.
1. Expand **General pipelines**.
1. In the **CI/CD configuration file** field, enter the file name, and if:
- The file is not in the root directory, include the path.
- The file is in a different project, include the group and project name.
- The file is on an external site, enter the full URL.
1. Select **Save changes**.
If the CI/CD configuration file is stored in the repository in a non-default
location, the path must be relative to the root directory. Examples of valid
paths and file names include:
### Custom CI/CD configuration file examples
If the CI/CD configuration file is not in the root directory, the path must be relative to it.
For example:
- `.gitlab-ci.yml` (default)
- `.my-custom-file.yml`
- `my/path/.gitlab-ci.yml`
- `my/path/.my-custom-file.yml`
If hosting the CI/CD configuration file on an external site, the URL link must end with `.yml`:
If the CI/CD configuration file is on an external site, the URL must end with `.yml`:
- `http://example.com/generate/ci/config.yml`
If hosting the CI/CD configuration file in a different project in GitLab, the path must be relative
If the CI/CD configuration file is in a different project in GitLab, the path must be relative
to the root directory in the other project. Include the group and project name at the end:
- `.gitlab-ci.yml@mygroup/another-project`
- `my/path/.my-custom-file.yml@mygroup/another-project`
Hosting the configuration file in a separate project allows stricter control of the
configuration file. For example:
If the configuration file is in a separate project, you can more set more granular permissions. For example:
- Create a public project to host the configuration file.
- Give write permissions on the project only to users who are allowed to edit the file.
Other users and projects can access the configuration file without being
Then other users and projects can access the configuration file without being
able to edit it.
## Git strategy
## Choose the default Git strategy
With Git strategy, you can choose the default way your repository is fetched
from GitLab in a job.
You can choose how your repository is fetched from GitLab when a job runs.
There are two options. Using:
- `git clone`, which is slower because it clones the repository from scratch
for every job, ensuring that the local working copy is always pristine.
- `git fetch`, which is default in GitLab and faster as it re-uses the local working copy (falling
back to clone if it doesn't exist).
This is recommended, especially for [large repositories](../large_repositories/index.md#git-strategy).
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Settings > CI/CD**.
1. Expand **General pipelines**.
1. Under **Git strategy**, select an option:
- `git clone` is slower because it clones the repository from scratch
for every job. However, the local working copy is always pristine.
- `git fetch` is faster because it re-uses the local working copy (and falls
back to clone if it doesn't exist). This is recommended, especially for
[large repositories](../large_repositories/index.md#git-strategy).
The configured Git strategy can be overridden by the [`GIT_STRATEGY` variable](../runners/configure_runners.md#git-strategy)
in `.gitlab-ci.yml`.
in the `.gitlab-ci.yml` file.
## Git shallow clone
## Limit the number of changes fetched during clone
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/28919) in GitLab 12.0.
It is possible to limit the number of changes that GitLab CI/CD fetches when cloning
a repository. Setting a limit to `git depth` can speed up Pipelines execution.
You can limit the number of changes that GitLab CI/CD fetches when it clones
a repository.
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Settings > CI/CD**.
1. Expand **General pipelines**.
1. Under **Git strategy**, under **Git shallow clone**, enter a value.
The maximum value is `1000`. To disable shallow clone and make GitLab CI/CD
fetch all branches and tags each time, keep the value empty or set to `0`.
In GitLab 12.0 and later, newly created projects automatically have a default
`git depth` value of `50`. The maximum allowed value is `1000`.
`git depth` value of `50`.
To disable shallow clone and make GitLab CI/CD fetch all branches and tags each time,
keep the value empty or set to `0`.
This value can also be [overridden by `GIT_DEPTH`](../large_repositories/index.md#shallow-cloning) variable in `.gitlab-ci.yml` file.
This value can be overridden by the [`GIT_DEPTH` variable](../large_repositories/index.md#shallow-cloning)
in the `.gitlab-ci.yml` file.
## Timeout
@ -218,7 +226,7 @@ averaged.
<!-- vale gitlab.Spelling = YES -->
### Code Coverage history
### Code coverage history
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/209121) the ability to download a `.csv` in GitLab 12.10.
> - [Graph introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33743) in GitLab 13.1.
@ -249,7 +257,7 @@ For example:
lein cloverage | perl -pe 's/\e\[?.*?[\@-~]//g'
```
## Pipeline Badges
## Pipeline badges
In the pipelines settings page you can find pipeline status and test coverage
badges for your project. The latest successful pipeline is used to read
@ -340,10 +348,6 @@ https://gitlab.com/gitlab-org/gitlab/badges/main/coverage.svg?job=karma&key_text
![Badge with custom text and width](https://gitlab.com/gitlab-org/gitlab/badges/main/coverage.svg?job=karma&key_text=Frontend+Coverage&key_width=130)
## Related topics
- [Maximum artifacts size](../../user/admin_area/settings/continuous_integration.md#maximum-artifacts-size).
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues

View File

@ -258,7 +258,7 @@ variables:
```
There are three possible values: `clone`, `fetch`, and `none`. If left unspecified,
jobs use the [project's pipeline setting](../pipelines/settings.md#git-strategy).
jobs use the [project's pipeline setting](../pipelines/settings.md#choose-the-default-git-strategy).
`clone` is the slowest option. It clones the repository from scratch for every
job, ensuring that the local working copy is always pristine.
@ -428,7 +428,7 @@ It can be helpful for repositories with a large number of commits or old, large
passed to `git fetch` and `git clone`.
In GitLab 12.0 and later, newly-created projects automatically have a
[default `git depth` value of `50`](../pipelines/settings.md#git-shallow-clone).
[default `git depth` value of `50`](../pipelines/settings.md#limit-the-number-of-changes-fetched-during-clone).
If you use a depth of `1` and have a queue of jobs or retry
jobs, jobs may fail.

View File

@ -39,7 +39,7 @@ with any type of [executor](https://docs.gitlab.com/runner/executors/)
In the following example, the `ssh-add -` command does not display the value of
`$SSH_PRIVATE_KEY` in the job log, though it could be exposed if you enable
[debug logging](../variables/index.md#debug-logging). You might also want to
check the [visibility of your pipelines](../pipelines/settings.md#visibility-of-pipelines).
check the [visibility of your pipelines](../pipelines/settings.md#change-which-users-can-view-your-pipelines).
## SSH keys when using the Docker executor

View File

@ -611,7 +611,7 @@ You can grant permission to override variables to [maintainers](../../user/permi
with overridden variables, they receive the `Insufficient permissions to set pipeline variables`
error message.
If you [store your CI/CD configurations in a different repository](../../ci/pipelines/settings.md#custom-cicd-configuration-file),
If you [store your CI/CD configurations in a different repository](../../ci/pipelines/settings.md#specify-a-custom-cicd-configuration-file),
use this setting for control over the environment the pipeline runs in.
You can enable this feature by using [the projects API](../../api/projects.md#edit-project)

View File

@ -159,63 +159,96 @@ the [reviewer values](https://about.gitlab.com/handbook/engineering/workflow/rev
## Backend guides
### General
- [Directory structure](directory_structure.md)
- [GitLab utilities](utilities.md)
- [Issuable-like Rails models](issuable-like-models.md)
- [Newlines style guide](newlines_styleguide.md)
- [Logging](logging.md)
- [API style guide](api_styleguide.md) for contributing to the API
- [GraphQL API style guide](api_graphql_styleguide.md) for contributing to the
[GraphQL API](../api/graphql/index.md)
- [Sidekiq guidelines](sidekiq_style_guide.md) for working with Sidekiq workers
- [Working with Gitaly](gitaly.md)
- [Manage feature flags](feature_flags/index.md)
- [Licensed feature availability](licensed_feature_availability.md)
- [Dealing with email/mailers](emails.md)
- [Shell commands](shell_commands.md) in the GitLab codebase
- [Kubernetes integration guidelines](kubernetes.md)
- [Permissions](permissions.md)
- [Code comments](code_comments.md)
- [Windows Development on GCP](windows.md)
- [FIPS compliance](fips_compliance.md)
- [`Gemfile` guidelines](gemfile.md)
- [Pry debugging](pry_debugging.md)
- [Sidekiq debugging](../administration/troubleshooting/sidekiq.md)
- [Accessing session data](session.md)
### Things to be aware of
- [Gotchas](gotchas.md) to avoid
- [Avoid modules with instance variables](module_with_instance_variables.md), if
possible
- [Guidelines for reusing abstractions](reusing_abstractions.md)
### Rails Framework related
- [Routing](routing.md)
- [Rails initializers](rails_initializers.md)
- [Mass Inserting Models](mass_insert.md)
- [Issuable-like Rails models](issuable-like-models.md)
- [Issue types vs first-class types](issue_types.md)
- [DeclarativePolicy framework](policies.md)
### Debugging
- [Pry debugging](pry_debugging.md)
- [Sidekiq debugging](../administration/troubleshooting/sidekiq.md)
### Git specifics
- [How Git object deduplication works in GitLab](git_object_deduplication.md)
- [Git LFS](lfs.md)
### API
- [API style guide](api_styleguide.md) for contributing to the API
- [GraphQL API style guide](api_graphql_styleguide.md) for contributing to the
[GraphQL API](../api/graphql/index.md)
### GitLab components and features
- [Developing against interacting components or features](interacting_components.md)
- [Manage feature flags](feature_flags/index.md)
- [Licensed feature availability](licensed_feature_availability.md)
- [Accessing session data](session.md)
- [How to dump production data to staging](db_dump.md)
- [Geo development](geo.md)
- [Redis guidelines](redis.md)
- [Sidekiq guidelines](sidekiq_style_guide.md) for working with Sidekiq workers
- [Working with Gitaly](gitaly.md)
- [Elasticsearch integration docs](elasticsearch.md)
- [Working with Merge Request diffs](diffs.md)
- [Approval Rules](approval_rules.md)
- [Repository mirroring](repository_mirroring.md)
- [File uploads](uploads.md)
- [Auto DevOps development guide](auto_devops.md)
- [Renaming features](renaming_features.md)
- [Code Intelligence](code_intelligence/index.md)
- [Feature categorization](feature_categorization/index.md)
- [Wikis development guide](wikis.md)
- [Image scaling guide](image_scaling.md)
- [Cascading Settings](cascading_settings.md)
- [Shell commands](shell_commands.md) in the GitLab codebase
- [Value Stream Analytics development guide](value_stream_analytics.md)
- [Application limits](application_limits.md)
### Import/Export
- [Working with the GitHub importer](github_importer.md)
- [Import/Export development documentation](import_export.md)
- [Test Import Project](import_project.md)
- [Group migration](bulk_import.md)
- [Elasticsearch integration docs](elasticsearch.md)
- [Working with Merge Request diffs](diffs.md)
- [Kubernetes integration guidelines](kubernetes.md)
- [Permissions](permissions.md)
- [Guidelines for reusing abstractions](reusing_abstractions.md)
- [DeclarativePolicy framework](policies.md)
- [How Git object deduplication works in GitLab](git_object_deduplication.md)
- [Geo development](geo.md)
- [Routing](routing.md)
- [Repository mirroring](repository_mirroring.md)
- [Git LFS](lfs.md)
- [Developing against interacting components or features](interacting_components.md)
- [File uploads](uploads.md)
- [Auto DevOps development guide](auto_devops.md)
- [Mass Inserting Models](mass_insert.md)
- [Value Stream Analytics development guide](value_stream_analytics.md)
- [Issue types vs first-class types](issue_types.md)
- [Application limits](application_limits.md)
- [Redis guidelines](redis.md)
- [Rails initializers](rails_initializers.md)
- [Code comments](code_comments.md)
- [Renaming features](renaming_features.md)
- [Windows Development on GCP](windows.md)
- [Code Intelligence](code_intelligence/index.md)
- [Approval Rules](approval_rules.md)
- [Feature categorization](feature_categorization/index.md)
- [Wikis development guide](wikis.md)
- [Newlines style guide](newlines_styleguide.md)
- [Image scaling guide](image_scaling.md)
- [Export to CSV](export_csv.md)
- [Cascading Settings](cascading_settings.md)
- [FIPS compliance](fips_compliance.md)
## Language-specific guides
### Go guides
- [Go Guidelines](go_guide/index.md)
### Shell Scripting guides
- [Shell scripting standards and style guidelines](shell_scripting_guide/index.md)
## Performance guides
@ -286,14 +319,6 @@ See [database guidelines](database/index.md).
- [Licensing](licensing.md) for ensuring license compliance
## Go guides
- [Go Guidelines](go_guide/index.md)
## Shell Scripting guides
- [Shell scripting standards and style guidelines](shell_scripting_guide/index.md)
## Domain-specific guides
- [CI/CD development documentation](cicd/index.md)

View File

@ -29,7 +29,13 @@ in the [CI documentation](../../ci/yaml/index.md#image).
For consistency, scanning jobs should be named after the scanner, in lower case.
The job name is suffixed after the type of scanning:
`_dependency_scanning`, `_container_scanning`, `_dast`, and `_sast`.
- `_dependency_scanning`
- `_cluster_image_scanning`
- `_container_scanning`
- `_dast`
- `_sast`
For instance, the dependency scanning job based on the "MySec" scanner would be named `mysec_dependency_scanning`.
### Image
@ -69,7 +75,15 @@ so the [`allow_failure`](../../ci/yaml/index.md#allow_failure) parameter should
Scanning jobs must declare a report that corresponds to the type of scanning they perform,
using the [`artifacts:reports`](../../ci/yaml/index.md#artifactsreports) keyword.
Valid reports are: `dependency_scanning`, `container_scanning`, `dast`, `api_fuzzing`, `coverage_fuzzing`, and `sast`.
Valid reports are:
- `dependency_scanning`
- `container_scanning`
- `cluster_image_scanning`
- `dast`
- `api_fuzzing`
- `coverage_fuzzing`
- `sast`
For example, here is the definition of a SAST job that generates a file named `gl-sast-report.json`,
and uploads it as a SAST report:
@ -90,9 +104,15 @@ it's declared under the `reports:sast` key in the job definition, not because of
Certain GitLab workflows, such as [AutoDevOps](../../topics/autodevops/customize.md#disable-jobs),
define CI/CD variables to indicate that given scans should be disabled. You can check for this by looking
for variables such as `DEPENDENCY_SCANNING_DISABLED`, `CONTAINER_SCANNING_DISABLED`,
`SAST_DISABLED`, and `DAST_DISABLED`. If appropriate based on the scanner type, you should then
disable running the custom scanner.
for variables such as:
- `DEPENDENCY_SCANNING_DISABLED`
- `CONTAINER_SCANNING_DISABLED`
- `CLUSTER_IMAGE_SCANNING_DISABLED`
- `SAST_DISABLED`
- `DAST_DISABLED`
If appropriate based on the scanner type, you should then disable running the custom scanner.
GitLab also defines a `CI_PROJECT_REPOSITORY_LANGUAGES` variable, which provides the list of
languages in the repository. Depending on this value, your scanner may or may not do something different.
@ -194,6 +214,19 @@ using the variables `DOCKER_USER` and `DOCKER_PASSWORD`.
If these are not defined, then the scanner should use
`CI_REGISTRY_USER` and `CI_REGISTRY_PASSWORD` as default values.
#### Cluster Image Scanning
To be consistent with the official `cluster_image_scanning` for GitLab, scanners must scan the
Kubernetes cluster whose configuration is given by `KUBECONFIG`.
If you use the `CIS_KUBECONFIG` CI/CD variable, then the
`KUBECONFIG` variable is ignored and the cluster specified in the
`CIS_KUBECONFIG` variable is scanned instead. If you don't provide
the `CIS_KUBECONFIG` CI/CD variable, the value defaults to the value of
`$KUBECONFIG`. `$KUBECONFIG` is a predefined CI/CD variable configured when the project is assigned to a
Kubernetes cluster. When multiple contexts are provided in the `KUBECONFIG` variable, the context
selected as `current-context` will be used to fetch vulnerabilities.
#### Configuration files
While scanners may use `CI_PROJECT_DIR` to load specific configuration files,
@ -282,7 +315,8 @@ The format is extensively described in the documentation of
[SAST](../../user/application_security/sast/index.md#reports-json-format),
[DAST](../../user/application_security/dast/#reports),
[Dependency Scanning](../../user/application_security/dependency_scanning/index.md#reports-json-format),
and [Container Scanning](../../user/application_security/container_scanning/index.md#reports-json-format).
[Container Scanning](../../user/application_security/container_scanning/index.md#reports-json-format),
and [Cluster Image Scanning](../../user/application_security/cluster_image_scanning/index.md#reports-json-format).
You can find the schemas for these scanners here:
@ -310,7 +344,12 @@ We recommend that you generate a UUID and use it as the `id` field's value.
#### Category
The value of the `category` field matches the report type:
`dependency_scanning`, `container_scanning`, `sast`, and `dast`.
- `dependency_scanning`
- `cluster_image_scanning`
- `container_scanning`
- `sast`
- `dast`
#### Scanner
@ -480,6 +519,31 @@ so these attributes are mandatory.
The `image` is also mandatory.
All other attributes are optional.
#### Cluster Image Scanning
The `location` of a `cluster_image_scanning` vulnerability has a `dependency` field. It also has
an `operating_system` field. For example, here is the `location` object for a vulnerability
affecting version `2.50.3-2+deb9u1` of Debian package `glib2.0`:
```json
{
"dependency": {
"package": {
"name": "glib2.0"
},
},
"version": "2.50.3-2+deb9u1",
"operating_system": "debian:9",
"image": "index.docker.io/library/nginx:1.18"
}
```
The affected package is found when scanning the image of the pod `index.docker.io/library/nginx:1.18`.
The location fingerprint of a Cluster Image Scanning vulnerability combines the
`operating_system` and the package `name`, so these attributes are mandatory. The `image` is also
mandatory. All other attributes are optional.
#### SAST
The `location` of a SAST vulnerability must have a `file` and a `start_line` field,

View File

@ -90,6 +90,7 @@ and complete an integration with the Secure stage.
- Documentation for [SAST reports](../../user/application_security/sast/index.md#reports-json-format).
- Documentation for [Dependency Scanning reports](../../user/application_security/dependency_scanning/index.md#reports-json-format).
- Documentation for [Container Scanning reports](../../user/application_security/container_scanning/index.md#reports-json-format).
- Documentation for [`cluster_image_scanning` reports](../../user/application_security/cluster_image_scanning/index.md#reports-json-format).
- See this [example secure job definition that also defines the artifact created](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml).
- If you need a new kind of scan or report, [create an issue](https://gitlab.com/gitlab-org/gitlab/-/issues/new#)
and add the label `devops::secure`.

View File

@ -39,12 +39,6 @@ Now when a user tries to push a commit with a message `Bugfix`, their push is
declined. Only pushing commits with messages like `Bugfix according to JIRA-123`
is accepted.
The error message includes the rejected commit's SHA.
To resolve such errors, commit again with a matching message,
[rebase and reword](../topics/git/numerous_undo_possibilities_in_git/index.md#how-to-change-history),
or [amend](https://git-scm.com/docs/git-commit#Documentation/git-commit.txt---amend)
that commit's message locally.
### Restrict branch names
If your company has a strict policy for branch names, you may want the branches to start

View File

@ -214,7 +214,7 @@ of your GitLab instance (`.gitlab-ci.yml` if not set):
1. Input the new file and path in the **Default CI/CD configuration file** field.
1. Hit **Save changes** for the changes to take effect.
It is also possible to specify a [custom CI/CD configuration file for a specific project](../../../ci/pipelines/settings.md#custom-cicd-configuration-file).
It is also possible to specify a [custom CI/CD configuration file for a specific project](../../../ci/pipelines/settings.md#specify-a-custom-cicd-configuration-file).
## Required pipeline configuration **(PREMIUM SELF)**

View File

@ -0,0 +1,281 @@
---
type: reference, howto
stage: Protect
group: Container Security
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
---
# Cluster Image Scanning **(ULTIMATE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 14.1.
WARNING:
This analyzer is in [Alpha](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha)
and is unstable. The JSON report and CI/CD configuration may be subject to change or breakage
across GitLab releases.
Your Kubernetes cluster may run workloads based on images that the Container Security analyzer
didn't scan. These images may therefore contain known vulnerabilities. By including an extra job in
your pipeline that scans for those security risks and displays them in the vulnerability report, you
can use GitLab to audit your Kubernetes workloads and environments.
GitLab provides integration with open-source tools for vulnerability analysis in Kubernetes clusters:
- [Starboard](https://github.com/aquasecurity/starboard)
To integrate GitLab with security scanners other than those listed here, see
[Security scanner integration](../../../development/integrations/secure.md).
You can enable cluster image scanning by [including the CI job](#configuration)
in your existing `.gitlab-ci.yml` file.
## Prerequisites
To enable cluster image scanning in your pipeline, you need the following:
- [GitLab Runner](https://docs.gitlab.com/runner/)
with the [`docker`](https://docs.gitlab.com/runner/executors/docker.html)
or [`kubernetes`](https://docs.gitlab.com/runner/install/kubernetes.html)
executor.
- Docker `18.09.03` or later installed on the same computer as the runner. If you're using the
shared runners on GitLab.com, then this is already the case.
- [Starboard Operator](https://aquasecurity.github.io/starboard/v0.10.3/operator/installation/kubectl/)
installed and configured in your cluster.
- The configuration for accessing your Kubernetes cluster stored in the `CIS_KUBECONFIG`
[configuration variable](#cicd-variables-for-cluster-image-scanning)
with the type set to `File` (see [Configuring the cluster](#configuring-the-cluster)).
## Configuring the cluster
1. Create a new service account.
To properly fetch vulnerabilities from the cluster and to limit analyzer access to the workload,
you must create a new service account with the cluster role limited to `get`, `list`, and `watch`
`vulnerabilityreports` in the Kubernetes cluster:
```shell
kubectl apply -f https://gitlab.com/gitlab-org/security-products/analyzers/cluster-image-scanning/-/raw/main/gitlab-vulnerability-viewer-service-account.yaml
```
1. Obtain the Kubernetes API URL.
Get the API URL by running this command:
```shell
API_URL=$(kubectl cluster-info | grep -E 'Kubernetes master|Kubernetes control plane' | awk '/http/ {print $NF}')
```
1. Obtain the CA certificate:
1. List the secrets with `kubectl get secrets`. One should have a name similar to
`default-token-xxxxx`. Copy that token name for use below.
1. Run this command to get the certificate:
```shell
CA_CERTIFICATE=$(kubectl get secret <secret name> -o jsonpath="{['data']['ca\.crt']}")
```
1. Obtain the service account token:
```shell
TOKEN=$(kubectl -n kube-system get secret $(kubectl -n kube-system get secret | grep gitlab-vulnerability-viewer | awk '{print $1}') -o jsonpath="{.data.token}" | base64 --decode)
```
1. Generate the value for the `CIS_KUBECONFIG` variable. Copy the printed value from the output:
```shell
echo "
---
apiVersion: v1
kind: Config
clusters:
- name: gitlab-vulnerabilities-viewer
cluster:
server: $API_URL
certificate-authority-data: $CA_CERTIFICATE
contexts:
- name: gitlab-vulnerabilities-viewer
context:
cluster: gitlab-vulnerabilities-viewer
namespace: default
user: gitlab-vulnerabilities-viewer
current-context: gitlab-vulnerabilities-viewer
users:
- name: gitlab-vulnerabilities-viewer
user:
token: $TOKEN
"
```
1. Set the CI/CD variable:
1. Navigate to your project's **Settings > CI/CD**.
1. Expand the **Variables** section.
1. Select **Add variable** and fill in the details:
- **Key**: `CIS_KUBECONFIG`.
- **Value**: `generated value`
- **Type**: `File`
WARNING:
The `CIS_KUBECONFIG` variable is accessible by all jobs executed for your project. Mark the
`Protect variable` flag to export this variable to pipelines running on protected branches and tags
only. You can apply additional protection to your cluster by
[restricting service account access to a single namespace](https://kubernetes.io/docs/reference/access-authn-authz/rbac/),
and [configuring Starboard Operator](https://aquasecurity.github.io/starboard/v0.10.3/operator/configuration/#install-modes)
to install in restricted mode.
## Configuration
To include the `Cluster-Image-Scanning.gitlab-ci.yml` template (GitLab 14.1 and later), add the
following to your `.gitlab-ci.yml` file:
```yaml
include:
- template: Security/Cluster-Image-Scanning.gitlab-ci.yml
```
The included template:
- Creates a `cluster_image_scanning` job in your CI/CD pipeline.
- Connects to your Kubernetes cluster with credentials provided in the `CIS_KUBECONFIG` variable and
fetches vulnerabilities found by [Starboard Operator](https://aquasecurity.github.io/starboard/v0.10.3/operator/).
GitLab saves the results as a
[Cluster Image Scanning report artifact](../../../ci/yaml/index.md#artifactsreportscluster_image_scanning)
that you can download and analyze later. When downloading, you always receive the most recent
artifact.
### Customize the cluster image scanning settings
You can customize how GitLab scans your cluster. For example, to restrict the analyzer to get
results for only a certain workload, use the [`variables`](../../../ci/yaml/index.md#variables)
parameter in your `.gitlab-ci.yml` to set [CI/CD variables](#cicd-variables-for-cluster-image-scanning).
The variables you set in your `.gitlab-ci.yml` overwrite those in
`Cluster-Image-Scanning.gitlab-ci.yml`.
#### CI/CD variables for cluster image scanning
You can [configure](#customize-the-cluster-image-scanning-settings) analyzers by using the following CI/CD variables:
| CI/CD Variable | Default | Description |
| ------------------------------ | ------------- | ----------- |
| `CIS_KUBECONFIG` | `""` | File used to configure access to the Kubernetes cluster. See the [Kubernetes documentation](https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/) for more details. |
| `CIS_CONTAINER_NAME` | `""` | Name of the container used in the Kubernetes resource you want to filter vulnerabilities for. For example, `alpine`. |
| `CIS_RESOURCE_NAME` | `""` | Name of the Kubernetes resource you want to filter vulnerabilities for. For example, `nginx`. |
| `CIS_RESOURCE_NAMESPACE` | `""` | Namespace of the Kubernetes resource you want to filter vulnerabilities for. For example, `production`. |
| `CIS_RESOURCE_KIND` | `""` | Kind of the Kubernetes resource you want to filter vulnerabilities for. For example, `deployment`. |
### Override the cluster image scanning template
If you want to override the job definition (for example, to change properties like `variables`), you
must declare and override a job after the template inclusion, and then
specify any additional keys.
This example sets `CIS_RESOURCE_NAME` to `nginx`:
```yaml
include:
- template: Security/Cluster-Image-Scanning.gitlab-ci.yml
cluster_image_scanning:
variables:
CIS_RESOURCE_NAME: nginx
```
### Connect with Kubernetes cluster associated to the project
If you want to connect to the Kubernetes cluster associated with the project and run Cluster Image Scanning jobs without
configuring the `CIS_KUBECONFIG` variable, you must extend `cluster_image_scanning` and specify the environment you want to scan.
This example configures the `cluster_image_scanning` job to scan the Kubernetes cluster connected with the `staging` environment:
```yaml
cluster_image_scanning:
environment:
name: staging
action: prepare
```
## Reports JSON format
The cluster image scanning tool emits a JSON report file. For more information, see the
[schema for this report](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/container-scanning-report-format.json).
Here's an example cluster image scanning report:
```json-doc
{{
"version": "14.0.2",
"scan": {
"scanner": {
"id": "starboard_trivy",
"name": "Trivy (using Starboard Operator)",
"url": "https://github.com/aquasecurity/starboard",
"vendor": {
"name": "GitLab"
},
"version": "0.16.0"
},
"start_time": "2021-04-28T12:47:00Z",
"end_time": "2021-04-28T12:47:00Z",
"type": "cluster_image_scanning",
"status": "success"
},
"vulnerabilities": [
{
"id": "c15f22205ee842184c2d55f1a207b3708283353f85083d66c34379c709b0ac9d",
"category": "cluster_image_scanning",
"message": "CVE-2011-3374 in apt",
"description": "",
"cve": "library/nginx:1.18:apt:CVE-2011-3374",
"severity": "Low",
"confidence": "Unknown",
"solution": "Upgrade apt from 1.8.2.2",
"scanner": {
"id": "starboard_trivy",
"name": "Trivy (using Starboard Operator)"
},
"location": {
"dependency": {
"package": {
"name": "apt"
},
"version": "1.8.2.2"
},
"operating_system": "library/nginx:1.18",
"image": "index.docker.io/library/nginx:1.18"
},
"identifiers": [
{
"type": "cve",
"name": "CVE-2011-3374",
"value": "CVE-2011-3374",
"url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-3374"
}
],
"links": [
"https://avd.aquasec.com/nvd/cve-2011-3374"
]
}
]
}
```
## Security Dashboard
The [Security Dashboard](../security_dashboard/index.md) shows you an overview of all
the security vulnerabilities in your groups, projects, and pipelines.
## Interacting with the vulnerabilities
After a vulnerability is found, you can [address it](../vulnerabilities/index.md).
## Troubleshooting
### Getting warning message `gl-cluster-image-scanning-report.json: no matching files`
For information on this error, see the [general Application Security troubleshooting section](../../../ci/pipelines/job_artifacts.md#error-message-no-files-to-upload).

View File

@ -189,11 +189,6 @@ container_scanning:
GIT_STRATEGY: fetch
```
WARNING:
GitLab 13.0 and later doesn't support [`only` and `except`](../../../ci/yaml/index.md#only--except).
When overriding the template, you must use [`rules`](../../../ci/yaml/index.md#rules)
instead.
### Change scanners
The container-scanning analyzer can use different scanners, depending on the value of the

View File

@ -33,16 +33,17 @@ GitLab uses the following tools to scan and report known vulnerabilities found i
| Secure scanning tool | Description |
|:-----------------------------------------------------------------------------|:-----------------------------------------------------------------------|
| [Container Scanning](container_scanning/index.md) **(ULTIMATE)** | Scan Docker containers for known vulnerabilities. |
| [Dependency List](dependency_list/index.md) **(ULTIMATE)** | View your project's dependencies and their known vulnerabilities. |
| [Dependency Scanning](dependency_scanning/index.md) **(ULTIMATE)** | Analyze your dependencies for known vulnerabilities. |
| [Dynamic Application Security Testing (DAST)](dast/index.md) **(ULTIMATE)** | Analyze running web applications for known vulnerabilities. |
| [DAST API](dast_api/index.md) **(ULTIMATE)** | Analyze running web APIs for known vulnerabilities. |
| [API fuzzing](api_fuzzing/index.md) **(ULTIMATE)** | Find unknown bugs and vulnerabilities in web APIs with fuzzing. |
| [Secret Detection](secret_detection/index.md) | Analyze Git history for leaked secrets. |
| [Security Dashboard](security_dashboard/index.md) **(ULTIMATE)** | View vulnerabilities in all your projects and groups. |
| [Static Application Security Testing (SAST)](sast/index.md) | Analyze source code for known vulnerabilities. |
| [Coverage fuzzing](coverage_fuzzing/index.md) **(ULTIMATE)** | Find unknown bugs and vulnerabilities with coverage-guided fuzzing. |
| [Container Scanning](container_scanning/index.md) **(ULTIMATE)** | Scan Docker containers for known vulnerabilities. |
| [Dependency List](dependency_list/index.md) **(ULTIMATE)** | View your project's dependencies and their known vulnerabilities. |
| [Dependency Scanning](dependency_scanning/index.md) **(ULTIMATE)** | Analyze your dependencies for known vulnerabilities. |
| [Dynamic Application Security Testing (DAST)](dast/index.md) **(ULTIMATE)** | Analyze running web applications for known vulnerabilities. |
| [DAST API](dast_api/index.md) **(ULTIMATE)** | Analyze running web APIs for known vulnerabilities. |
| [API fuzzing](api_fuzzing/index.md) **(ULTIMATE)** | Find unknown bugs and vulnerabilities in web APIs with fuzzing. |
| [Secret Detection](secret_detection/index.md) | Analyze Git history for leaked secrets. |
| [Security Dashboard](security_dashboard/index.md) **(ULTIMATE)** | View vulnerabilities in all your projects and groups. |
| [Static Application Security Testing (SAST)](sast/index.md) | Analyze source code for known vulnerabilities. |
| [Coverage fuzzing](coverage_fuzzing/index.md) **(ULTIMATE)** | Find unknown bugs and vulnerabilities with coverage-guided fuzzing. |
| [Cluster Image Scanning](cluster_image_scanning/index.md) **(ULTIMATE)** | Scan Kubernetes clusters for known vulnerabilities. |
## Security scanning with Auto DevOps

View File

@ -390,7 +390,7 @@ For information on this, see the [general Application Security troubleshooting s
### Error: `Couldn't run the gitleaks command: exit status 2`
If a pipeline is triggered from a Merge Request containing 60 commits while the `GIT_DEPTH` variable
is set to 50 (a [project default](../../../ci/pipelines/settings.md#git-shallow-clone)),
is set to 50 (a [project default](../../../ci/pipelines/settings.md#limit-the-number-of-changes-fetched-during-clone)),
the Secret Detection job fails as the clone is not deep enough to contain all of the
relevant commits.

View File

@ -33,6 +33,7 @@ The security dashboard and vulnerability report displays information about vulne
- [Dynamic Application Security Testing](../dast/index.md)
- [Dependency Scanning](../dependency_scanning/index.md)
- [Static Application Security Testing](../sast/index.md)
- [Cluster Image Scanning](../cluster_image_scanning/index.md)
- And [others](../index.md#security-scanning-tools)!
## Prerequisites

View File

@ -118,6 +118,7 @@ The type of scan. This must be one of the following:
- `dependency_scanning`
- `dast`
- `sast`
- `cluster_image_scanning`
### Scanner

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

View File

@ -220,75 +220,36 @@ WARNING:
Threads created this way are lost if the commit ID changes after a
force push.
## Image threads
## Add a comment to an image
Sometimes a thread is revolved around an image. With image threads,
you can easily target a specific coordinate of an image and start a thread
around it. Image threads are available in merge requests and commit detail views.
In merge requests and commit detail views, you can add a comment to an image.
This comment can also be a thread.
To start an image thread, hover your mouse over the image. Your mouse pointer
should convert into an icon, indicating that the image is available for commenting.
Simply click anywhere on the image to create a new thread.
1. Hover your mouse over the image.
1. Select the location where you want to comment.
An icon is displayed on the image and a comment field is displayed.
![Start image thread](img/start_image_discussion.gif)
After you select the image, a comment form is displayed that would be the start
of your thread. After you save your comment, a new badge is displayed on
top of your image. This badge represents your thread.
## Prevent comments by locking an issue
NOTE:
This thread badge is typically associated with a number that is only used as a visual
reference for each thread. In the merge request thread tab,
this badge is indicated with a comment icon, because each thread renders a new
image section.
You can prevent public comments in an issue or merge request.
When you do, only project members can add and edit comments.
Image threads also work on diffs that replace an existing image. In this diff view
mode, you can toggle the different view modes and still see the thread point badges.
Prerequisite:
| 2-up | Swipe | Onion Skin |
|:-----------:|:----------:|:----------:|
| ![2-up view](img/two_up_view.png) | ![swipe view](img/swipe_view.png) | ![onion skin view](img/onion_skin_view.png) |
- In merge requests, you must have the Developer role or higher.
- In issues, you must have the Reporter role or higher.
Image threads also work well with resolvable threads. Resolved threads
on diffs (not on the merge request discussion tab) appear collapsed on page
load and have a corresponding badge counter to match the counter on the image.
1. On the right sidebar, next to **Lock issue** or **Lock merge request**, select **Edit**.
1. On the confirmation dialog, select **Lock**.
![Image resolved thread](img/image_resolved_discussion.png)
Notes are added to the page details.
## Lock discussions
If an issue or merge request is locked and closed, you cannot reopen it.
For large projects with many contributors, it may be useful to stop threads
in issues or merge requests in these scenarios:
- The project maintainer has already resolved the thread and it is not helpful
for continued feedback.
- The project maintainer has already directed new conversation
to newer issues or merge requests.
- The people participating in the thread are trolling, abusive, or otherwise
being unproductive.
In these cases, a user with Developer permissions or higher in the project can lock (and unlock)
an issue or a merge request, using the "Lock" section in the sidebar. For issues,
a user with Reporter permissions can lock (and unlock).
| Unlock | Lock |
| :-----------: | :----------: |
| ![Turn off discussion lock](img/turn_off_lock.png) | ![Turn on discussion lock](img/turn_on_lock.png) |
System notes indicate locking and unlocking.
![Discussion lock system notes](img/discussion_lock_system_notes.png)
In a locked issue or merge request, only team members can add new comments and
edit existing comments. Non-team members are restricted from adding or editing comments.
| Team member | Non-team member |
| :-----------: | :----------: |
| ![Comment form member](img/lock_form_member.png) | ![Comment form non-member](img/lock_form_non_member.png) |
Additionally, locked issues and merge requests can't be reopened.
## Confidential Comments
## Mark a comment as confidential
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207473) in GitLab 13.9.
> - [Deployed behind a feature flag](../feature_flags.md), disabled by default.
@ -299,30 +260,30 @@ Additionally, locked issues and merge requests can't be reopened.
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
When creating a comment, you can make it visible only to the project members (users with Reporter and higher permissions).
You can make a comment confidential, so that it is visible only to project members
who have the Reporter role or higher.
To create a confidential comment, select the **Make this comment confidential** check box before you submit it.
1. Below the comment, select the **Make this comment confidential** checkbox.
1. Select **Comment**.
![Confidential comments](img/confidential_comments_v13_9.png)
## Filtering notes
## Show only comments
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/26723) in GitLab 11.5.
For issues with many comments like activity notes and user comments, sometimes
finding useful information can be hard. There is a way to filter comments from single notes and threads for merge requests and issues.
For issues and merge requests with many comments, you can filter the page to show comments only.
From a merge request's **Discussion** tab, or from an epic/issue overview, find the filter's dropdown menu on the right side of the page, from which you can choose one of the following options:
- **Show all activity**: displays all user comments and system notes
(issue updates, mentions from other issues, changes to the description, etc).
- **Show comments only**: only displays user comments in the list.
- **Show history only**: only displays activity notes.
1. Open a merge request's **Discussion** tab, or epic or issue's **Overview** tab.
1. On the right side of the page, select from the filter:
- **Show all activity**: Display all user comments and system notes
(issue updates, mentions from other issues, changes to the description, and so on).
- **Show comments only**: Display only user comments.
- **Show history only**: Display only activity notes.
![Notes filters dropdown options](img/index_notes_filters.png)
After you select one of the filters in a given issue or merge request, GitLab saves
your preference, so that it persists when you visit the same page again
GitLab saves your preference, so it persists when you visit the same page again
from any device you're logged into.
## Assign an issue to the commenting user
@ -331,15 +292,16 @@ from any device you're logged into.
You can assign an issue to a user who made a comment.
In the comment, select the **More Actions** menu, and then select **Assign to commenting user**.
Select the button again to unassign the commenter.
1. In the comment, select the **More Actions** menu.
1. Select **Assign to commenting user**.
![Assign to commenting user](img/quickly_assign_commenter_v13_1.png)
## Enable or disable Confidential Comments **(FREE SELF)**
Select the button again to unassign the commenter.
Confidential Comments is under development and not ready for production use. It is
## Enable or disable confidential comments **(FREE SELF)**
Confidential comments are under development and not ready for production use. The feature is
deployed behind a feature flag that is **disabled by default**.
[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
can enable it.

View File

@ -426,7 +426,7 @@ To set a WIP limit for a list:
1. Enter the maximum number of issues.
1. Press <kbd>Enter</kbd> to save.
## Blocked issues
## Blocked issues **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34723) in GitLab 12.8.
> - [View blocking issues when hovering over blocked icon](https://gitlab.com/gitlab-org/gitlab/-/issues/210452) in GitLab 13.10.

View File

@ -151,7 +151,7 @@ cannot access the issue, and it is not listed in the project's issue boards nor
### Lock issue
You can [lock the threads](../../discussions/index.md#lock-discussions) in the issue,
You can [lock the issue](../../discussions/index.md#prevent-comments-by-locking-an-issue)
to prevent further comments from being added.
### Participants

View File

@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
You can sort a list of issues several ways, including by:
- Blocking
- Blocking **(PREMIUM)**
- Created date
- Due date
- Label priority
@ -51,7 +51,7 @@ This ordering also affects [issue boards](../issue_board.md#how-gitlab-orders-is
Changing the order in an issue list changes the ordering in an issue board,
and vice versa.
## Sorting by blocking issues
## Sorting by blocking issues **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34247/) in GitLab 13.7.

View File

@ -99,40 +99,26 @@ module API
updatable_optional_attributes = %w[target_url description coverage]
status.assign_attributes(attributes_for_keys(updatable_optional_attributes))
if status.valid?
status.update_older_statuses_retried! if Feature.enabled?(:ci_fix_commit_status_retried, user_project, default_enabled: :yaml)
else
render_validation_error!(status)
end
render_validation_error!(status) unless status.valid?
begin
case params[:state]
when 'pending'
status.enqueue!
when 'running'
status.enqueue
status.run!
when 'success'
status.success!
when 'failed'
status.drop!(:api_failure)
when 'canceled'
status.cancel!
else
render_api_error!('invalid state', 400)
end
if pipeline.latest?
MergeRequest.where(source_project: user_project, source_branch: ref)
.update_all(head_pipeline_id: pipeline.id)
end
present status, with: Entities::CommitStatus
rescue StateMachines::InvalidTransition => e
response = ::Ci::Pipelines::AddJobService.new(pipeline).execute!(status) do |job|
apply_job_state!(job)
rescue ::StateMachines::InvalidTransition => e
render_api_error!(e.message, 400)
end
render_validation_error!(response.payload[:job]) unless response.success?
if pipeline.latest?
MergeRequest
.where(source_project: user_project, source_branch: ref)
.update_all(head_pipeline_id: pipeline.id)
end
present response.payload[:job], with: Entities::CommitStatus
end
# rubocop: enable CodeReuse/ActiveRecord
helpers do
def commit
strong_memoize(:commit) do
@ -146,6 +132,24 @@ module API
pipelines = pipelines.for_id(params[:pipeline_id]) if params[:pipeline_id]
pipelines
end
def apply_job_state!(job)
case params[:state]
when 'pending'
job.enqueue!
when 'running'
job.enqueue
job.run!
when 'success'
job.success!
when 'failed'
job.drop!(:api_failure)
when 'canceled'
job.cancel!
else
render_api_error!('invalid state', 400)
end
end
end
end
end

View File

@ -0,0 +1,34 @@
# Use this template to enable cluster image scanning in your project.
# You should add this template to an existing `.gitlab-ci.yml` file by using the `include:`
# keyword.
# The template should work without modifications but you can customize the template settings if
# needed: https://docs.gitlab.com/ee/user/application_security/cluster_image_scanning/#customize-the-container-scanning-settings
#
# Requirements:
# - A `test` stage to be present in the pipeline.
# - You must define the `CIS_KUBECONFIG` variable to allow analyzer to connect to your Kubernetes cluster and fetch found vulnerabilities.
#
# Configure container scanning with CI/CD variables (https://docs.gitlab.com/ee/ci/variables/README.html).
# List of available variables: https://docs.gitlab.com/ee/user/application_security/cluster_image_scanning/#available-variables
variables:
CIS_ANALYZER_IMAGE: registry.gitlab.com/gitlab-org/security-products/analyzers/cluster-image-scanning:0
cluster_image_scanning:
image: "$CIS_ANALYZER_IMAGE"
stage: test
allow_failure: true
artifacts:
reports:
cluster_image_scanning: gl-cluster-image-scanning-report.json
paths: [gl-cluster-image-scanning-report.json]
dependencies: []
script:
- /analyzer run
rules:
- if: $CLUSTER_IMAGE_SCANNING_DISABLED
when: never
- if: '($KUBECONFIG == null || $KUBECONFIG == "") && ($CIS_KUBECONFIG == null || $CIS_KUBECONFIG == "")'
when: never
- if: $CI_COMMIT_BRANCH &&
$GITLAB_FEATURES =~ /\bcluster_image_scanning\b/

View File

@ -147,16 +147,6 @@ module Gitlab
raise 'Failed to determine the write location of the primary database'
end
# FF disabled: Returns true if all hosts have caught up to the given transaction write location.
# FF enabled: Returns true if there was at least one host that has caught up with the given transaction and sets it.
def all_caught_up?(location)
if ::Feature.enabled?(:load_balancing_improved_caught_up_hosts_check)
select_up_to_date_host(location)
else
@host_list.hosts.all? { |host| host.caught_up?(location) }
end
end
# Returns true if there was at least one host that has caught up with the given transaction.
#
# In case of a retry, this method also stores the set of hosts that have caught up.

View File

@ -33,10 +33,10 @@ module Gitlab
return true unless location
load_balancer.all_caught_up?(location).tap do |caught_up|
ActiveSupport::Notifications.instrument('caught_up_replica_pick.load_balancing', { result: caught_up } )
load_balancer.select_up_to_date_host(location).tap do |found|
ActiveSupport::Notifications.instrument('caught_up_replica_pick.load_balancing', { result: found } )
unstick(namespace, id) if caught_up
unstick(namespace, id) if found
end
end

View File

@ -120,7 +120,7 @@ module Gitlab
AREL_ORDER_CLASSES = { Arel::Nodes::Ascending => :asc, Arel::Nodes::Descending => :desc }.freeze
ALLOWED_NULLABLE_VALUES = [:not_nullable, :nulls_first, :nulls_last].freeze
attr_reader :attribute_name, :column_expression, :order_expression, :add_to_projections
attr_reader :attribute_name, :column_expression, :order_expression, :add_to_projections, :order_direction
def initialize(attribute_name:, order_expression:, column_expression: nil, reversed_order_expression: nil, nullable: :not_nullable, distinct: true, order_direction: nil, add_to_projections: false)
@attribute_name = attribute_name
@ -175,7 +175,7 @@ module Gitlab
private
attr_reader :reversed_order_expression, :nullable, :distinct, :order_direction
attr_reader :reversed_order_expression, :nullable, :distinct
def calculate_reversed_order(order_expression)
unless AREL_ORDER_CLASSES.has_key?(order_expression.class) # Arel can reverse simple orders

View File

@ -139,6 +139,8 @@ module Gitlab
verify_incoming_values!(values)
return use_composite_row_comparison(values) if composite_row_comparison_possible?
where_values = []
reversed_column_definitions = column_definitions.reverse
@ -187,6 +189,28 @@ module Gitlab
private
def composite_row_comparison_possible?
!column_definitions.one? &&
column_definitions.all?(&:not_nullable?) &&
column_definitions.map(&:order_direction).uniq.one? # all columns uses the same order direction
end
# composite row comparison works with NOT NULL columns and may use only one index scan given a proper index setup
# Example: (created_at, id) > ('2012-09-18 01:40:01+00', 15)
def use_composite_row_comparison(values)
columns = Arel::Nodes::Grouping.new(column_definitions.map(&:column_expression))
values = Arel::Nodes::Grouping.new(column_definitions.map do |column_definition|
value = values[column_definition.attribute_name]
Arel::Nodes.build_quoted(value, column_definition.column_expression)
end)
if column_definitions.first.ascending_order?
[columns.gt(values)]
else
[columns.lt(values)]
end
end
# Adds extra columns to the SELECT clause
def apply_custom_projections(scope)
additional_projections = column_definitions.select(&:add_to_projections).map do |column_definition|

View File

@ -21667,6 +21667,9 @@ msgstr ""
msgid "NetworkPolicies|Invalid or empty policy"
msgstr ""
msgid "NetworkPolicies|Invalid or unsupported policy kind"
msgstr ""
msgid "NetworkPolicies|Kubernetes error: %{error}"
msgstr ""
@ -23383,6 +23386,9 @@ msgstr ""
msgid "PackageRegistry|Gradle Kotlin DSL install command"
msgstr ""
msgid "PackageRegistry|Helm"
msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
msgstr ""
@ -23872,6 +23878,9 @@ msgstr ""
msgid "Pipeline Schedules"
msgstr ""
msgid "Pipeline URL"
msgstr ""
msgid "Pipeline durations for the last 30 commits"
msgstr ""
@ -25567,6 +25576,9 @@ msgstr ""
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
msgstr ""
msgid "ProjectService|Run CI/CD pipelines with Buildkite."
msgstr ""
msgid "ProjectService|Run CI/CD pipelines with Drone."
msgstr ""
@ -25579,6 +25591,9 @@ msgstr ""
msgid "ProjectService|The build configuration ID of the TeamCity project."
msgstr ""
msgid "ProjectService|The token you get after you create a Buildkite pipeline with a GitLab repository."
msgstr ""
msgid "ProjectService|To configure this integration, you should:"
msgstr ""

View File

@ -41,6 +41,7 @@ describe('Packages shared utils', () => {
${'rubygems'} | ${'RubyGems'}
${'composer'} | ${'Composer'}
${'debian'} | ${'Debian'}
${'helm'} | ${'Helm'}
${'foo'} | ${null}
`(`package type`, ({ packageType, expectedResult }) => {
it(`${packageType} should show as ${expectedResult}`, () => {

View File

@ -32,6 +32,10 @@ Array [
exports[`Utils formOptionsGenerator returns an object containing keepN 1`] = `
Array [
Object {
"key": null,
"label": "",
},
Object {
"default": false,
"key": "ONE_TAG",
@ -73,6 +77,10 @@ Array [
exports[`Utils formOptionsGenerator returns an object containing olderThan 1`] = `
Array [
Object {
"key": null,
"label": "",
},
Object {
"default": false,
"key": "SEVEN_DAYS",

View File

@ -22,7 +22,7 @@ exports[`Settings Form Enable matches snapshot 1`] = `
exports[`Settings Form Keep N matches snapshot 1`] = `
<expiration-dropdown-stub
data-testid="keep-n-dropdown"
formoptions="[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]"
formoptions="[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]"
label="Keep the most recent:"
name="keep-n"
value="TEN_TAGS"
@ -44,7 +44,7 @@ exports[`Settings Form Keep Regex matches snapshot 1`] = `
exports[`Settings Form OlderThan matches snapshot 1`] = `
<expiration-dropdown-stub
data-testid="older-than-dropdown"
formoptions="[object Object],[object Object],[object Object],[object Object]"
formoptions="[object Object],[object Object],[object Object],[object Object],[object Object]"
label="Remove tags older than:"
name="older-than"
value="FOURTEEN_DAYS"

View File

@ -132,9 +132,9 @@ describe('Settings Form', () => {
model | finder | fieldName | type | defaultValue
${'enabled'} | ${findEnableToggle} | ${'Enable'} | ${'toggle'} | ${false}
${'cadence'} | ${findCadenceDropdown} | ${'Cadence'} | ${'dropdown'} | ${'EVERY_DAY'}
${'keepN'} | ${findKeepNDropdown} | ${'Keep N'} | ${'dropdown'} | ${'TEN_TAGS'}
${'keepN'} | ${findKeepNDropdown} | ${'Keep N'} | ${'dropdown'} | ${''}
${'nameRegexKeep'} | ${findKeepRegexInput} | ${'Keep Regex'} | ${'textarea'} | ${''}
${'olderThan'} | ${findOlderThanDropdown} | ${'OlderThan'} | ${'dropdown'} | ${'NINETY_DAYS'}
${'olderThan'} | ${findOlderThanDropdown} | ${'OlderThan'} | ${'dropdown'} | ${''}
${'nameRegex'} | ${findRemoveRegexInput} | ${'Remove regex'} | ${'textarea'} | ${''}
`('$fieldName', ({ model, finder, type, defaultValue }) => {
it('matches snapshot', () => {
@ -293,10 +293,10 @@ describe('Settings Form', () => {
input: {
cadence: 'EVERY_DAY',
enabled: true,
keepN: 'TEN_TAGS',
keepN: null,
nameRegex: 'asdasdssssdfdf',
nameRegexKeep: 'sss',
olderThan: 'NINETY_DAYS',
olderThan: null,
projectPath: 'path',
},
});

View File

@ -12,6 +12,7 @@ describe('Utils', () => {
olderThanTranslationGenerator,
);
expect(result).toEqual([
{ key: null, label: '' },
{ variable: 1, label: '1 day' },
{ variable: 2, label: '2 days' },
]);

View File

@ -290,6 +290,42 @@ RSpec.describe Resolvers::IssuesResolver do
expect(resolve_issues(sort: :severity_desc).to_a).to eq([issue_high_severity, issue_low_severity, issue_no_severity])
end
end
context 'when sorting by popularity' do
let_it_be(:project) { create(:project, :public) }
let_it_be(:issue1) { create(:issue, project: project) } # has one upvote
let_it_be(:issue2) { create(:issue, project: project) } # has two upvote
let_it_be(:issue3) { create(:issue, project: project) }
let_it_be(:issue4) { create(:issue, project: project) } # has one upvote
before do
create(:award_emoji, :upvote, awardable: issue1)
create(:award_emoji, :upvote, awardable: issue2)
create(:award_emoji, :upvote, awardable: issue2)
create(:award_emoji, :upvote, awardable: issue4)
end
it 'sorts issues ascending (ties broken by id in desc order)' do
expect(resolve_issues(sort: :popularity_asc).to_a).to eq([issue3, issue4, issue1, issue2])
end
it 'sorts issues descending (ties broken by id in desc order)' do
expect(resolve_issues(sort: :popularity_desc).to_a).to eq([issue2, issue4, issue1, issue3])
end
end
context 'when sorting with non-stable cursors' do
%i[priority_asc priority_desc
popularity_asc popularity_desc
label_priority_asc label_priority_desc
milestone_due_asc milestone_due_desc].each do |sort_by|
it "uses offset-pagination when sorting by #{sort_by}" do
resolved = resolve_issues(sort: sort_by)
expect(resolved).to be_a(::Gitlab::Graphql::Pagination::OffsetActiveRecordRelationConnection)
end
end
end
end
it 'returns issues user can see' do

View File

@ -306,38 +306,6 @@ RSpec.describe Gitlab::Database::LoadBalancing::LoadBalancer, :request_store do
end
end
describe '#all_caught_up?' do
it 'delegates execution to #select_up_to_date_host' do
expect(lb).to receive(:select_up_to_date_host).with('foo').and_return(true)
expect(lb.all_caught_up?('foo')).to eq(true)
end
context 'when :load_balancing_improved_caught_up_hosts_check FF is disabled' do
before do
stub_feature_flags(load_balancing_improved_caught_up_hosts_check: false)
end
it 'returns true if all hosts caught up to the write location' do
expect(lb.host_list.hosts).to all(receive(:caught_up?).with('foo').and_return(true))
expect(lb.all_caught_up?('foo')).to eq(true)
end
it 'returns false if a host has not yet caught up' do
expect(lb.host_list.hosts[0]).to receive(:caught_up?)
.with('foo')
.and_return(true)
expect(lb.host_list.hosts[1]).to receive(:caught_up?)
.with('foo')
.and_return(false)
expect(lb.all_caught_up?('foo')).to eq(false)
end
end
end
describe '#retry_with_backoff' do
it 'returns the value returned by the block' do
value = lb.retry_with_backoff { 10 }

View File

@ -64,7 +64,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
.with(:user, 42)
.and_return(nil)
expect(lb).not_to receive(:all_caught_up?)
expect(lb).not_to receive(:select_up_to_date_host)
expect(described_class.all_caught_up?(:user, 42)).to eq(true)
end
@ -72,7 +72,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
context 'when all secondaries have caught up' do
before do
allow(lb).to receive(:all_caught_up?).with('foo').and_return(true)
allow(lb).to receive(:select_up_to_date_host).with('foo').and_return(true)
end
it 'returns true, and unsticks' do
@ -93,7 +93,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
context 'when the secondaries have not yet caught up' do
before do
allow(lb).to receive(:all_caught_up?).with('foo').and_return(false)
allow(lb).to receive(:select_up_to_date_host).with('foo').and_return(false)
end
it 'returns false' do
@ -123,7 +123,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
.with(:user, 42)
.and_return(nil)
expect(lb).not_to receive(:all_caught_up?)
expect(lb).not_to receive(:select_up_to_date_host)
described_class.unstick_or_continue_sticking(:user, 42)
end
@ -133,7 +133,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
.with(:user, 42)
.and_return('foo')
allow(lb).to receive(:all_caught_up?).with('foo').and_return(true)
allow(lb).to receive(:select_up_to_date_host).with('foo').and_return(true)
expect(described_class).to receive(:unstick).with(:user, 42)
@ -145,7 +145,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
.with(:user, 42)
.and_return('foo')
allow(lb).to receive(:all_caught_up?).with('foo').and_return(false)
allow(lb).to receive(:select_up_to_date_host).with('foo').and_return(false)
expect(Gitlab::Database::LoadBalancing::Session.current)
.to receive(:use_primary!)

View File

@ -171,6 +171,12 @@ RSpec.describe Gitlab::Pagination::Keyset::Order do
end
it_behaves_like 'order examples'
it 'uses the row comparison method' do
sql = order.where_values_with_or_query({ year: 2010, month: 5, id: 1 }).to_sql
expect(sql).to eq('(("my_table"."year", "my_table"."month", "my_table"."id") > (2010, 5, 1))')
end
end
context 'when ordering by nullable columns and a distinct column' do

View File

@ -0,0 +1,72 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Ci::Pipelines::AddJobService do
let_it_be(:pipeline) { create(:ci_pipeline) }
let(:job) { build(:ci_build) }
subject(:service) { described_class.new(pipeline) }
context 'when the pipeline is not persisted' do
let(:pipeline) { build(:ci_pipeline) }
it 'raises error' do
expect { service }.to raise_error('Pipeline must be persisted for this service to be used')
end
end
describe '#execute!' do
subject(:execute) do
service.execute!(job) do |job|
job.save!
end
end
it 'assigns pipeline attributes to the job' do
expect do
execute
end.to change { job.slice(:pipeline, :project, :ref) }.to(
pipeline: pipeline, project: pipeline.project, ref: pipeline.ref
)
end
it 'returns a service response with the job as payload' do
expect(execute).to be_success
expect(execute.payload[:job]).to eq(job)
end
it 'calls update_older_statuses_retried!' do
expect(job).to receive(:update_older_statuses_retried!)
execute
end
context 'when the block raises an error' do
subject(:execute) do
service.execute!(job) do |job|
raise "this is an error"
end
end
it 'returns a service response with the error and the job as payload' do
expect(execute).to be_error
expect(execute.payload[:job]).to eq(job)
expect(execute.message).to eq('this is an error')
end
end
context 'when the FF ci_fix_commit_status_retried is disabled' do
before do
stub_feature_flags(ci_fix_commit_status_retried: false)
end
it 'does not call update_older_statuses_retried!' do
expect(job).not_to receive(:update_older_statuses_retried!)
execute
end
end
end
end