Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-04-06 12:08:29 +00:00
parent c16b752f86
commit 39c98649d2
42 changed files with 666 additions and 125 deletions

View File

@ -143,25 +143,6 @@ Performance/ConstantRegexp:
Performance/MethodObjectAsBlock:
Enabled: false
# Offense count: 18
# Cop supports --auto-correct.
# Configuration parameters: AutoCorrect.
Performance/StringInclude:
Exclude:
- 'app/models/snippet_repository.rb'
- 'config/initializers/macos.rb'
- 'config/spring.rb'
- 'ee/app/models/ee/container_registry/event.rb'
- 'ee/lib/gitlab/auth/smartcard/certificate.rb'
- 'lib/gitlab/database/migration_helpers.rb'
- 'lib/kramdown/parser/atlassian_document_format.rb'
- 'lib/prometheus/pid_provider.rb'
- 'qa/qa/ee/page/merge_request/show.rb'
- 'qa/qa/specs/runner.rb'
- 'spec/features/projects/jobs_spec.rb'
- 'spec/spec_helper.rb'
- 'spec/support_specs/helpers/active_record/query_recorder_spec.rb'
# Offense count: 15209
# Configuration parameters: Prefixes.
# Prefixes: when, with, without
@ -282,11 +263,6 @@ Rails/HelperInstanceVariable:
Rails/IndexWith:
Enabled: false
# Offense count: 1
Rails/Inquiry:
Exclude:
- 'spec/helpers/labels_helper_spec.rb'
# Offense count: 118
# Configuration parameters: Include.
# Include: app/models/**/*.rb
@ -335,11 +311,6 @@ Rails/RakeEnvironment:
Rails/RedundantForeignKey:
Enabled: false
# Offense count: 1
Rails/RenderInline:
Exclude:
- 'ee/app/controllers/sitemap_controller.rb'
# Offense count: 1144
# Configuration parameters: ForbiddenMethods, AllowedMethods.
# ForbiddenMethods: decrement!, decrement_counter, increment!, increment_counter, insert, insert!, insert_all, insert_all!, toggle!, touch, touch_all, update_all, update_attribute, update_column, update_columns, update_counters, upsert, upsert_all

View File

@ -0,0 +1,15 @@
---
# Cop supports --auto-correct.
Performance/StringInclude:
Exclude:
- 'app/models/snippet_repository.rb'
- 'config/initializers/macos.rb'
- 'config/spring.rb'
- 'ee/app/models/ee/container_registry/event.rb'
- 'ee/lib/gitlab/auth/smartcard/certificate.rb'
- 'lib/gitlab/database/migration_helpers.rb'
- 'lib/kramdown/parser/atlassian_document_format.rb'
- 'lib/prometheus/pid_provider.rb'
- 'qa/qa/specs/runner.rb'
- 'spec/features/projects/jobs_spec.rb'
- 'spec/spec_helper.rb'

View File

@ -0,0 +1,4 @@
---
Rails/Inquiry:
Exclude:
- 'spec/helpers/labels_helper_spec.rb'

View File

@ -0,0 +1,4 @@
---
Rails/RenderInline:
Exclude:
- 'ee/app/controllers/sitemap_controller.rb'

View File

@ -1 +0,0 @@
<svg width="16" height="17" xmlns="http://www.w3.org/2000/svg"><path fill="#fffff" d="M1.53 7.639l-.476.88.476-.88zm0-1.758L1.054 5l.476.88zm2.257 2.982h1v-.596l-.523-.283-.477.879zm8.424 0l-.476-.88-.524.284v.596h1zm2.257-1.224l.477.88-.477-.88zm0-1.758l-.476.879.476-.88zM8.476 2.632l-.477.88.477-.88zm-.953 0l.476.88-.476-.88zM2.007 6.76l-.953-1.758c-1.396.756-1.396 2.76 0 3.516l.953-1.758zm2.257 1.224L2.007 6.76l-.953 1.758L3.31 9.742l.953-1.758zm.523 1.995V8.863h-2v1.116h2zM8 12.5c-1.949 0-3.212-1.289-3.212-2.52h-2c0 2.656 2.51 4.52 5.212 4.52v-2zm3.212-2.52c0 1.231-1.262 2.52-3.212 2.52v2c2.704 0 5.212-1.864 5.212-4.52h-2zm0-1.117v1.116h2V8.863h-2zm2.78-2.103l-2.256 1.223.953 1.759 2.257-1.224-.953-1.758zm0 0l.954 1.758c1.396-.757 1.396-2.76 0-3.516l-.953 1.758zM8 3.51l5.993 3.249.953-1.758-5.993-3.249L8 3.511zm0 0l.953-1.758a2 2 0 00-1.906 0L8 3.511zM2.007 6.76l5.992-3.25-.953-1.758-5.992 3.249.953 1.758z"/><path fill="#fffff" d="M7.228 7.541c-.187-.112-.277-.427-.201-.704.076-.276.288-.41.475-.297L11 8.644v5.316c0 .298-.163.54-.365.54-.2 0-.364-.242-.364-.54V9.37L7.228 7.54z"/></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -3,6 +3,7 @@ import {
GlDropdown,
GlDropdownItem,
GlDropdownDivider,
GlDropdownText,
GlSearchBoxByType,
GlSprintf,
} from '@gitlab/ui';
@ -15,6 +16,7 @@ export default {
GlDropdown,
GlDropdownItem,
GlDropdownDivider,
GlDropdownText,
GlSearchBoxByType,
GlSprintf,
},
@ -73,13 +75,24 @@ export default {
this.clearSearch();
this.focusSearch();
},
onKeyEnter() {
if (!this.searchTerm?.length) {
return;
}
this.$refs.dropdown.hide();
this.selectAgent(this.searchTerm);
},
},
};
</script>
<template>
<gl-dropdown :text="dropdownText" :loading="isRegistering" @shown="handleShow">
<gl-dropdown ref="dropdown" :text="dropdownText" :loading="isRegistering" @shown="handleShow">
<template #header>
<gl-search-box-by-type ref="searchInput" v-model.trim="searchTerm" />
<gl-search-box-by-type
ref="searchInput"
v-model.trim="searchTerm"
@keydown.enter.stop.prevent="onKeyEnter"
/>
</template>
<gl-dropdown-item
v-for="agent in filteredResults"
@ -90,9 +103,9 @@ export default {
>
{{ agent }}
</gl-dropdown-item>
<gl-dropdown-item v-if="!filteredResults.length" ref="noMatchingResults">{{
<gl-dropdown-text v-if="!filteredResults.length" ref="noMatchingResults">{{
$options.i18n.noResults
}}</gl-dropdown-item>
}}</gl-dropdown-text>
<template v-if="shouldRenderCreateButton">
<gl-dropdown-divider />
<gl-dropdown-item data-testid="create-config-button" @click="selectAgent(searchTerm)">

View File

@ -1,5 +1,5 @@
<script>
import { GlButton, GlTable } from '@gitlab/ui';
import { GlButton, GlTableLite } from '@gitlab/ui';
import { __ } from '~/locale';
const DEFAULT_TD_CLASSES = 'gl-w-half gl-font-sm! gl-border-gray-200!';
@ -25,7 +25,7 @@ export default {
],
components: {
GlButton,
GlTable,
GlTableLite,
},
props: {
trigger: {
@ -84,7 +84,7 @@ export default {
>
</p>
<gl-table :items="trigger.variables" :fields="$options.fields" small bordered fixed>
<gl-table-lite :items="trigger.variables" :fields="$options.fields" small bordered fixed>
<template #cell(key)="{ item }">
<span class="gl-overflow-break-word">{{ item.key }}</span>
</template>
@ -92,7 +92,7 @@ export default {
<template #cell(value)="data">
<span class="gl-overflow-break-word">{{ getDisplayValue(data.value) }}</span>
</template>
</gl-table>
</gl-table-lite>
</template>
</div>
</template>

View File

@ -1,3 +1,5 @@
@import '../highlight/hljs';
.file-content.code {
border: 0;
box-shadow: none;

View File

@ -0,0 +1,125 @@
.code.highlight {
.hljs-comment {
color: var(--color-hljs-comment);
}
.hljs-link {
color: var(--color-hljs-link);
}
.hljs-meta {
color: var(--color-hljs-meta);
}
.hljs-keyword {
color: var(--color-hljs-keyword);
}
.hljs-type {
color: var(--color-hljs-type);
}
.hljs-attr,
.hljs-property {
color: var(--color-hljs-attr);
}
.hljs-built_in {
color: var(--color-hljs-builtin);
}
.hljs-literal {
color: var(--color-hljs-literal);
}
.hljs-title {
color: var(--color-hljs-title);
&.class_ {
color: var(--color-hljs-class);
}
&.function_ {
color: var(--color-hljs-function);
}
}
.hljs-tag ,
.hljs-name {
color: var(--color-hljs-tag);
}
.hljs-number {
color: var(--color-hljs-number);
}
.hljs-subst {
color: var(--color-hljs-subst);
}
.hljs-string,
.hljs-section,
.hljs-bullet {
color: var(--color-hljs-string);
}
.hljs-symbol {
color: var(--color-hljs-symbol);
}
.hljs-variable {
color: var(--color-hljs-variable);
&.language_ {
color: var(--color-hljs-language);
}
&.constant_ {
color: var(--color-hljs-constant);
}
}
.hljs-attribute {
color: var(--color-hljs-attribute);
}
.hljs-operator {
color: var(--color-hljs-operator);
}
.hljs-punctuation {
color: var(--color-hljs-punctuation);
}
.hljs-regexp {
color: var(--color-hljs-regexp);
}
.hljs-params {
color: var(--color-hljs-params);
}
.hljs-doctag {
color: var(--color-hljs-doctag);
}
.hljs-selector-tag {
color: var(--color-hljs-selector-tag);
}
.hljs-selector-class {
color: var(--color-hljs-selector-class);
}
.hljs-selector-id {
color: var(--color-hljs-selector-id);
}
.hljs-selector-attr {
color: var(--color-hljs-selector-attr);
}
.hljs-selector-pseudo {
color: var(--color-hljs-selector-pseudo);
}
}

View File

@ -88,6 +88,39 @@ $dark-vg: #c66;
$dark-vi: #c66;
$dark-il: #de935f;
:root {
--color-hljs-comment: #{$dark-c};
--color-hljs-variable: #{$dark-k};
--color-hljs-link: #{$dark-l};
--color-hljs-meta: #{$dark-cp};
--color-hljs-keyword: #{$dark-kd};
--color-hljs-type: #{$dark-kt};
--color-hljs-attr: #{$dark-na};
--color-hljs-builtin: #{$dark-nb};
--color-hljs-title: #{$dark-n};
--color-hljs-class: #{$dark-nc};
--color-hljs-function: #{$dark-nf};
--color-hljs-tag: #{$dark-nt};
--color-hljs-number: #{$dark-mi};
--color-hljs-subst: #{$dark-sc};
--color-hljs-string: #{$dark-s1};
--color-hljs-symbol: #{$dark-ss};
--color-hljs-variable: #{$dark-vi};
--color-hljs-operator: #{$dark-o};
--color-hljs-punctuation: #{$dark-p};
--color-hljs-regexp: #{$dark-sr};
--color-hljs-constant: #{$dark-nx};
--color-hljs-literal: #{$dark-kc};
--color-hljs-language: #{$dark-nx};
--color-hljs-params: #{$dark-nx};
--color-hljs-selector-doctag: #{$dark-cm};
--color-hljs-selector-tag: #{$dark-nt};
--color-hljs-selector-class: #{$dark-nc};
--color-hljs-selector-id: #{$dark-nn};
--color-hljs-selector-attr: #{$dark-nt};
--color-hljs-selector-pseudo: #{$dark-nd};
}
.code.dark {
// Line numbers
.file-line-num {

View File

@ -200,6 +200,18 @@ module Issuable
incident?
end
# When :incident_escalations feature flag is disabled, new
# incidents should not have a status record unless the incident
# is associated with the alert. However, escalation attributes
# are synced with Alert/IssuableEscalationStatus, so we want to
# ensure that parity is kept prior to rollout.
# Remove with https://gitlab.com/gitlab-org/gitlab/-/issues/345769.
def sync_escalation_attributes_from_alert?
incident? &&
::Feature.disabled?(:incident_escalations, project) &&
alert_management_alert.present?
end
def incident?
is_a?(Issue) && super
end

View File

@ -3,13 +3,16 @@
class ProjectMemberPolicy < BasePolicy
delegate { @subject.project }
condition(:target_is_owner, scope: :subject) { @subject.user == @subject.project.owner }
condition(:target_is_holder_of_the_personal_namespace, scope: :subject) do
@subject.project.personal_namespace_holder?(@subject.user)
end
condition(:target_is_self) { @user && @subject.user == @user }
condition(:project_bot) { @subject.user&.project_bot? }
rule { anonymous }.prevent_all
rule { target_is_owner }.policy do
rule { target_is_holder_of_the_personal_namespace }.policy do
prevent :update_project_member
prevent :destroy_project_member
end

View File

@ -151,14 +151,25 @@ module AlertManagement
status_change_reason: " by changing the status of #{alert.to_reference(project)}"
}
}
).execute(alert.issue)
).execute(issue)
end
def issue
strong_memoize(:issue) { alert.issue }
end
def should_sync_to_incident?
alert.issue &&
alert.issue.supports_escalation? &&
alert.issue.escalation_status &&
alert.issue.escalation_status.status != alert.status
return false unless sync_available?
issue.escalation_status&.status != alert.status
end
def sync_available?
return false unless issue.present?
# Remove sync check with https://gitlab.com/gitlab-org/gitlab/-/issues/345769
issue.supports_escalation? ||
issue.sync_escalation_attributes_from_alert?
end
def filter_duplicate

View File

@ -31,7 +31,10 @@ module IncidentManagement
attr_reader :issuable, :param_errors
def available?
issuable.supports_escalation? && user_has_permissions?
(
issuable.supports_escalation? ||
issuable.sync_escalation_attributes_from_alert? # Remove with https://gitlab.com/gitlab-org/gitlab/-/issues/345769
) && user_has_permissions?
end
def user_has_permissions?
@ -60,6 +63,14 @@ module IncidentManagement
status = params.delete(:status)
return unless status
# If we're updating the escalation status because the
# alert was updated & the feature flag is disabled, then
# we should not allow the status to be different from the alert's.
# Remove with https://gitlab.com/gitlab-org/gitlab/-/issues/345769
if issuable.sync_escalation_attributes_from_alert? && status != issuable.alert_management_alert.status_name
add_param_error(:status) && return
end
status_event = escalation_status.status_event_for(status)
add_param_error(:status) && return unless status_event

View File

@ -87,7 +87,10 @@ module Issues
attr_reader :spam_params
def create_escalation_status(issue)
::IncidentManagement::IssuableEscalationStatuses::CreateService.new(issue).execute if issue.supports_escalation?
# Remove sync check with https://gitlab.com/gitlab-org/gitlab/-/issues/345769
return unless issue.supports_escalation? || issue.sync_escalation_attributes_from_alert?
::IncidentManagement::IssuableEscalationStatuses::CreateService.new(issue).execute
end
def user_agent_detail_service

View File

@ -167,7 +167,7 @@ options:
- p_ci_templates_implicit_security_cluster_image_scanning
- p_ci_templates_kaniko
- p_ci_templates_qualys_iac_security
- p_ci_templates_database_liquibase
- p_ci_templates_liquibase
distribution:
- ce
- ee

View File

@ -1,5 +1,5 @@
---
key_path: redis_hll_counters.ci_templates.p_ci_templates_database_liquibase_monthly
key_path: redis_hll_counters.ci_templates.p_ci_templates_liquibase_monthly
description: ""
product_section: ""
product_stage: ""
@ -22,4 +22,4 @@ tier:
- ultimate
options:
events:
- p_ci_templates_database_liquibase
- p_ci_templates_liquibase

View File

@ -167,7 +167,7 @@ options:
- p_ci_templates_implicit_security_cluster_image_scanning
- p_ci_templates_kaniko
- p_ci_templates_qualys_iac_security
- p_ci_templates_database_liquibase
- p_ci_templates_liquibase
distribution:
- ce
- ee

View File

@ -1,5 +1,5 @@
---
key_path: redis_hll_counters.ci_templates.p_ci_templates_database_liquibase_weekly
key_path: redis_hll_counters.ci_templates.p_ci_templates_liquibase_weekly
description: ""
product_section: ""
product_stage: ""
@ -22,4 +22,4 @@ tier:
- ultimate
options:
events:
- p_ci_templates_database_liquibase
- p_ci_templates_liquibase

View File

@ -0,0 +1,25 @@
# frozen_string_literal: true
class BackfillNamespaceStatisticsWithDependencyProxySize < Gitlab::Database::Migration[1.0]
DELAY_INTERVAL = 2.minutes.to_i
BATCH_SIZE = 500
MIGRATION = 'PopulateNamespaceStatistics'
disable_ddl_transaction!
def up
groups = exec_query <<~SQL
SELECT dependency_proxy_manifests.group_id FROM dependency_proxy_manifests
UNION
SELECT dependency_proxy_blobs.group_id from dependency_proxy_blobs
SQL
groups.rows.flatten.in_groups_of(BATCH_SIZE, false).each_with_index do |group_ids, index|
migrate_in(index * DELAY_INTERVAL, MIGRATION, [group_ids, [:dependency_proxy_size]])
end
end
def down
# no-op
end
end

View File

@ -0,0 +1 @@
bce595c1c6587e785bc49d6e5a7181b5cc0164f2201375ad82d4bd19c217cd35

View File

@ -77,7 +77,7 @@ If a test failed in the project's default branch in the last 14 days, a message
To enable the Unit test reports in merge requests, you must add
[`artifacts:reports:junit`](yaml/artifacts_reports.md#artifactsreportsjunit)
in `.gitlab-ci.yml`, and specify the path(s) of the generated test reports.
in `.gitlab-ci.yml`, and specify the paths of the generated test reports.
The reports must be `.xml` files, otherwise [GitLab returns an Error 500](https://gitlab.com/gitlab-org/gitlab/-/issues/216575).
In the following examples, the job in the `test` stage runs and GitLab

View File

@ -365,6 +365,35 @@ file for the [`gitlab`](https://gitlab.com/gitlab-org/gitlab) project.
To set up `lefthook` for documentation linting, see
[Pre-push static analysis](../contributing/style_guides.md#pre-push-static-analysis-with-lefthook).
#### Show Vale warnings on push
By default, `lefthook` shows only Vale errors when pushing changes to a branch. The default branches
have no Vale errors, so any errors listed here are introduced by commits to the branch.
To also see the Vale warnings when pushing to a branch, set a local environment variable: `VALE_WARNINGS=true`.
Enable Vale warnings on push to improve the documentation suite by:
- Detecting warnings you might be introducing with your commits.
- Identifying warnings that already exist in the page, which you can resolve to reduce technical debt.
These warnings:
- Don't stop the push from working.
- Don't result in a broken pipeline.
- Include all warnings for a file, not just warnings that are introduced by the commits.
To enable Vale warnings on push:
- Automatically, add `VALE_WARNINGS=true` to your shell configuration.
- Manually, prepend `VALE_WARNINGS=true` to invocations of `lefthook`. For example:
```shell
VALE_WARNINGS=true bundle exec lefthook run pre-push
```
You can also [configure your editor](#configure-editors) to show Vale warnings.
### Show subset of Vale alerts
You can set Visual Studio Code to display only a subset of Vale alerts when viewing files:

View File

@ -32,7 +32,7 @@ No matter how you use GitLab, we have documentation for you.
| Essential documentation | Essential documentation |
|:------------------------|:------------------------|
| [**User documentation**](user/index.md)<br>Discover features and concepts for GitLab users. | [**Administrator documentation**](administration/index.md)<br/>Everything GitLab self-managed administrators need to know. |
| [**Contributing to GitLab**](#contributing-to-gitlab)<br/>At GitLab, everyone can contribute! | [**New to Git and GitLab?**](#new-to-git-and-gitlab)<br/>We have the resources to get you started. |
| [**Contributing to GitLab**](#contributing-to-gitlab)<br/>At GitLab, everyone can contribute! | [**New to Git and GitLab?**](tutorials/index.md)<br/>We have the resources to get you started. |
| [**Build an integration with GitLab**](#build-an-integration-with-gitlab)<br/>Consult our integration documentation. | [**Coming to GitLab from another platform?**](#coming-to-gitlab-from-another-platform)<br/>Consult our guides. |
| [**Install GitLab**](https://about.gitlab.com/install/)<br/>Installation options for different platforms. | [**Customers**](subscriptions/index.md)<br/>Information for new and existing customers. |
| [**Update GitLab**](update/index.md)<br/>Update your GitLab self-managed instance to the latest version. | [**Reference Architectures**](administration/reference_architectures/index.md)<br/>GitLab reference architectures. |
@ -64,20 +64,6 @@ GitLab makes the software lifecycle faster and radically improves the speed of b
GitLab provides solutions for [each of the stages of the DevOps lifecycle](https://about.gitlab.com/stages-devops-lifecycle/).
## New to Git and GitLab?
Working with new systems can be daunting.
We have the following documentation to rapidly uplift your GitLab knowledge:
| Topic | Description |
|:--------------------------------------------------------------------------------------------------|:------------|
| [GitLab basics guides](gitlab-basics/index.md) | Start working on the command line and with GitLab. |
| [What is GitLab Flow?](https://about.gitlab.com/topics/version-control/what-is-gitlab-flow/) | Enhance your workflow with the best of GitLab Flow. |
| [Get started with GitLab CI/CD](ci/quick_start/index.md) | Quickly implement GitLab CI/CD. |
| [Auto DevOps](topics/autodevops/index.md) | Learn more about Auto DevOps in GitLab. |
| [GitLab Markdown](user/markdown.md) | Advanced formatting system (GitLab Flavored Markdown). |
### User account
Learn more about GitLab account management:
@ -89,16 +75,6 @@ Learn more about GitLab account management:
| [User settings](user/profile/index.md#access-your-user-settings) | Manage your user settings, two factor authentication, and more. |
| [User permissions](user/permissions.md) | Learn what each role in a project can do. |
### Git and GitLab
Learn more about using Git, and using Git with GitLab:
| Topic | Description |
|:-----------------------------------------------------------------------------|:------------|
| [Git](topics/git/index.md) | Getting started with Git, branching strategies, Git LFS, and advanced use. |
| [Git cheat sheet](https://about.gitlab.com/images/press/git-cheat-sheet.pdf) | Download a PDF describing the most used Git operations. |
| [GitLab Flow](topics/gitlab_flow.md) | Explore the best of Git with the GitLab Flow strategy. |
## Coming to GitLab from another platform
If you are coming to GitLab from another platform, the following information is useful:

View File

@ -42,7 +42,7 @@ pre-push:
tags: documentation style
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
glob: 'doc/*.md'
run: 'if command -v vale > /dev/null 2>&1; then if ! vale --config .vale.ini --minAlertLevel error {files}; then echo "ERROR: Fix any linting errors and make sure you are using the latest version of Vale."; exit 1; fi; else echo "ERROR: Vale not found. For more information, see https://docs.errata.ai/vale/install."; exit 1; fi'
run: 'if [ $VALE_WARNINGS ]; then minWarnings=warning; else minWarnings=error; fi; if command -v vale > /dev/null 2>&1; then if ! vale --config .vale.ini --minAlertLevel $minWarnings {files}; then echo "ERROR: Fix any linting errors and make sure you are using the latest version of Vale."; exit 1; fi; else echo "ERROR: Vale not found. For more information, see https://docs.errata.ai/vale/install."; exit 1; fi'
gettext:
skip: true # This is disabled by default. You can enable this check by adding skip: false in lefhook-local.yml https://github.com/evilmartians/lefthook/blob/master/docs/full_guide.md#skipping-commands
tags: backend frontend view haml

View File

@ -5,9 +5,40 @@ module Gitlab
# This class creates/updates those namespace statistics
# that haven't been created nor initialized.
# It also updates the related namespace statistics
# This is only required in EE
class PopulateNamespaceStatistics
def perform(group_ids, statistics)
# Updating group statistics might involve calling Gitaly.
# For example, when calculating `wiki_size`, we will need
# to perform the request to check if the repo exists and
# also the repository size.
#
# The `allow_n_plus_1_calls` method is only intended for
# dev and test. It won't be raised in prod.
::Gitlab::GitalyClient.allow_n_plus_1_calls do
relation(group_ids).each do |group|
upsert_namespace_statistics(group, statistics)
end
end
end
private
def upsert_namespace_statistics(group, statistics)
response = ::Groups::UpdateStatisticsService.new(group, statistics: statistics).execute
error_message("#{response.message} group: #{group.id}") if response.error?
end
def logger
@logger ||= ::Gitlab::BackgroundMigration::Logger.build
end
def error_message(message)
logger.error(message: "Namespace Statistics Migration: #{message}")
end
def relation(group_ids)
Group.includes(:namespace_statistics).where(id: group_ids)
end
end
end

View File

@ -5,21 +5,6 @@
image: golang:latest
variables:
# Please edit to your GitLab project
REPO_NAME: gitlab.com/namespace/project
# The problem is that to be able to use go get, one needs to put
# the repository in the $GOPATH. So for example if your gitlab domain
# is gitlab.com, and that your repository is namespace/project, and
# the default GOPATH being /go, then you'd need to have your
# repository in /go/src/gitlab.com/namespace/project
# Thus, making a symbolic link corrects this.
before_script:
- mkdir -p "$GOPATH/src/$(dirname $REPO_NAME)"
- ln -svf "$CI_PROJECT_DIR" "$GOPATH/src/$REPO_NAME"
- cd "$GOPATH/src/$REPO_NAME"
stages:
- test
- build

View File

@ -5,13 +5,13 @@
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Database/liquibase.gitlab-ci.yml
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/liquibase.gitlab-ci.yml
# This template must be configured with CI/CD variables before it will work.
# See https://www.liquibase.com/blog/secure-database-developer-flow-using-gitlab-pipelines
# to learn how to configure the Liquibase template by using variables.
# Be sure to add the variables before running pipelines with this template.
# You may not want to run all the jobs in this template. You can comment out or delete the jobs you don't wish to use.
# You may not want to run all the jobs in this template. You can comment out or delete the jobs you don't wish to use.
# List of stages for jobs and their order of execution.
stages:
@ -132,7 +132,7 @@ TEST->PROD:
expire_in: 1 week
# This job creates a snapshot of prod database. You can use the snapshot file to run comparisons with the production database to investigate for any potential issues. https://www.liquibase.com/devsecops
# This job creates a snapshot of prod database. You can use the snapshot file to run comparisons with the production database to investigate for any potential issues. https://www.liquibase.com/devsecops
snapshot PROD:
image: liquibase/liquibase:latest # Using the Liquibase Docker Image
stage: .post

View File

@ -12,6 +12,11 @@ module Gitlab
Gitlab::UrlBuilder.build(deployment.deployable)
end
commit_url =
if (commit = deployment.commit)
Gitlab::UrlBuilder.build(commit)
end
{
object_kind: 'deployment',
status: deployment.status,
@ -24,8 +29,8 @@ module Gitlab
short_sha: deployment.short_sha,
user: deployment.deployed_by.hook_attrs,
user_url: Gitlab::UrlBuilder.build(deployment.deployed_by),
commit_url: Gitlab::UrlBuilder.build(deployment.commit),
commit_title: deployment.commit.title,
commit_url: commit_url,
commit_title: deployment.commit&.title,
ref: deployment.ref
}
end

View File

@ -615,7 +615,7 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
- name: p_ci_templates_database_liquibase
- name: p_ci_templates_liquibase
category: ci_templates
redis_slot: ci_templates
aggregation: weekly

View File

@ -45,9 +45,9 @@ module Sidebars
}
end
override :image_path
def image_path
'learn_gitlab/graduation_hat.svg'
override :sprite_icon
def sprite_icon
'bulb'
end
override :render?

View File

@ -1,5 +1,6 @@
import { GlDropdown, GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { ENTER_KEY } from '~/lib/utils/keys';
import AvailableAgentsDropdown from '~/clusters_list/components/available_agents_dropdown.vue';
import { I18N_AVAILABLE_AGENTS_DROPDOWN } from '~/clusters_list/constants';
@ -18,6 +19,7 @@ describe('AvailableAgentsDropdown', () => {
propsData,
stubs: { GlDropdown },
});
wrapper.vm.$refs.dropdown.hide = jest.fn();
};
afterEach(() => {
@ -96,6 +98,25 @@ describe('AvailableAgentsDropdown', () => {
expect(findDropdown().props('text')).toBe('new-agent');
});
});
describe('click enter to register new agent without configuration', () => {
beforeEach(async () => {
await findSearchInput().vm.$emit('input', 'new-agent');
await findSearchInput().vm.$emit('keydown', new KeyboardEvent({ key: ENTER_KEY }));
});
it('emits agentSelected with the name of the clicked agent', () => {
expect(wrapper.emitted('agentSelected')).toEqual([['new-agent']]);
});
it('marks the clicked item as selected', () => {
expect(findDropdown().props('text')).toBe('new-agent');
});
it('closes the dropdown', () => {
expect(wrapper.vm.$refs.dropdown.hide).toHaveBeenCalledTimes(1);
});
});
});
describe('registration in progress', () => {

View File

@ -1,12 +1,12 @@
import { GlButton, GlTable } from '@gitlab/ui';
import { GlButton, GlTableLite } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import TriggerBlock from '~/jobs/components/trigger_block.vue';
describe('Trigger block', () => {
let wrapper;
const findRevealButton = () => wrapper.find(GlButton);
const findVariableTable = () => wrapper.find(GlTable);
const findRevealButton = () => wrapper.findComponent(GlButton);
const findVariableTable = () => wrapper.findComponent(GlTableLite);
const findShortToken = () => wrapper.find('[data-testid="trigger-short-token"]');
const findVariableValue = (index) =>
wrapper.findAll('[data-testid="trigger-build-value"]').at(index);
@ -22,7 +22,6 @@ describe('Trigger block', () => {
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
describe('with short token and no variables', () => {

View File

@ -0,0 +1,71 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::PopulateNamespaceStatistics do
let_it_be(:namespaces) { table(:namespaces) }
let_it_be(:namespace_statistics) { table(:namespace_statistics) }
let_it_be(:dependency_proxy_manifests) { table(:dependency_proxy_manifests) }
let_it_be(:dependency_proxy_blobs) { table(:dependency_proxy_blobs) }
let!(:group1) { namespaces.create!(id: 10, type: 'Group', name: 'group1', path: 'group1') }
let!(:group2) { namespaces.create!(id: 20, type: 'Group', name: 'group2', path: 'group2') }
let!(:group1_manifest) do
dependency_proxy_manifests.create!(group_id: 10, size: 20, file_name: 'test-file', file: 'test', digest: 'abc123')
end
let!(:group2_manifest) do
dependency_proxy_manifests.create!(group_id: 20, size: 20, file_name: 'test-file', file: 'test', digest: 'abc123')
end
let!(:group1_stats) { namespace_statistics.create!(id: 10, namespace_id: 10) }
let(:ids) { namespaces.pluck(:id) }
let(:statistics) { [] }
subject(:perform) { described_class.new.perform(ids, statistics) }
it 'creates/updates all namespace_statistics and updates root storage statistics', :aggregate_failures do
expect(Namespaces::ScheduleAggregationWorker).to receive(:perform_async).with(group1.id)
expect(Namespaces::ScheduleAggregationWorker).to receive(:perform_async).with(group2.id)
expect { perform }.to change(namespace_statistics, :count).from(1).to(2)
namespace_statistics.all.each do |stat|
expect(stat.dependency_proxy_size).to eq 20
expect(stat.storage_size).to eq 20
end
end
context 'when just a stat is passed' do
let(:statistics) { [:dependency_proxy_size] }
it 'calls the statistics update service with just that stat' do
expect(Groups::UpdateStatisticsService)
.to receive(:new)
.with(anything, statistics: [:dependency_proxy_size])
.twice.and_call_original
perform
end
end
context 'when a statistics update fails' do
before do
error_response = instance_double(ServiceResponse, message: 'an error', error?: true)
allow_next_instance_of(Groups::UpdateStatisticsService) do |instance|
allow(instance).to receive(:execute).and_return(error_response)
end
end
it 'logs an error' do
expect_next_instance_of(Gitlab::BackgroundMigration::Logger) do |instance|
expect(instance).to receive(:error).twice
end
perform
end
end
end

View File

@ -46,5 +46,24 @@ RSpec.describe Gitlab::DataBuilder::Deployment do
expect(data[:deployable_url]).to be_nil
end
context 'when commit does not exist in the repository' do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:deployment) { create(:deployment, project: project) }
subject(:data) { described_class.build(deployment, Time.current) }
before(:all) do
project.repository.remove
end
it 'does not include commit_url' do
expect(data[:commit_url]).to be_nil
end
it 'does not include commit_title' do
expect(data[:commit_title]).to be_nil
end
end
end
end

View File

@ -0,0 +1,64 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration!
RSpec.describe BackfillNamespaceStatisticsWithDependencyProxySize do
let_it_be(:groups) { table(:namespaces) }
let_it_be(:group1) { groups.create!(id: 10, name: 'test1', path: 'test1', type: 'Group') }
let_it_be(:group2) { groups.create!(id: 20, name: 'test2', path: 'test2', type: 'Group') }
let_it_be(:group3) { groups.create!(id: 30, name: 'test3', path: 'test3', type: 'Group') }
let_it_be(:group4) { groups.create!(id: 40, name: 'test4', path: 'test4', type: 'Group') }
let_it_be(:dependency_proxy_blobs) { table(:dependency_proxy_blobs) }
let_it_be(:dependency_proxy_manifests) { table(:dependency_proxy_manifests) }
let_it_be(:group1_manifest) { create_manifest(10, 10) }
let_it_be(:group2_manifest) { create_manifest(20, 20) }
let_it_be(:group3_manifest) { create_manifest(30, 30) }
let_it_be(:group1_blob) { create_blob(10, 10) }
let_it_be(:group2_blob) { create_blob(20, 20) }
let_it_be(:group3_blob) { create_blob(30, 30) }
describe '#up' do
it 'correctly schedules background migrations' do
stub_const("#{described_class}::BATCH_SIZE", 2)
Sidekiq::Testing.fake! do
freeze_time do
migrate!
aggregate_failures do
expect(described_class::MIGRATION)
.to be_scheduled_migration([10, 30], ['dependency_proxy_size'])
expect(described_class::MIGRATION)
.to be_scheduled_delayed_migration(2.minutes, [20], ['dependency_proxy_size'])
expect(BackgroundMigrationWorker.jobs.size).to eq(2)
end
end
end
end
end
def create_manifest(group_id, size)
dependency_proxy_manifests.create!(
group_id: group_id,
size: size,
file_name: 'test-file',
file: 'test',
digest: 'abc123'
)
end
def create_blob(group_id, size)
dependency_proxy_blobs.create!(
group_id: group_id,
size: size,
file_name: 'test-file',
file: 'test'
)
end
end

View File

@ -993,6 +993,33 @@ RSpec.describe Issuable do
end
end
describe '#sync_escalation_attributes_from_alert?' do
where(:issuable_type, :args, :sync_escalation_attributes_from_alert) do
:issue | {} | false
:issue | ref(:alert_args) | false
:incident | {} | false
:incident | ref(:alert_args) | true
:merge_request | {} | false
end
with_them do
let(:alert_args) { { alert_management_alert: build_stubbed(:alert_management_alert) } }
let(:issuable) { build_stubbed(issuable_type, **args) }
subject { issuable.sync_escalation_attributes_from_alert? }
it { is_expected.to eq(false) }
context 'with feature disabled' do
before do
stub_feature_flags(incident_escalations: false)
end
it { is_expected.to eq(sync_escalation_attributes_from_alert) }
end
end
end
describe '#incident?' do
where(:issuable_type, :incident) do
:issue | false

View File

@ -23,9 +23,9 @@ RSpec.describe ProjectMemberPolicy do
it { is_expected.not_to be_allowed(:destroy_project_bot_member) }
end
context 'when user is project owner' do
let(:member_user) { project.first_owner }
let(:member) { project.members.find_by!(user: member_user) }
context 'when user is the holder of personal namespace in which the project resides' do
let(:namespace_holder) { project.namespace.owner }
let(:member) { project.members.find_by!(user: namespace_holder) }
it { is_expected.to be_allowed(:read_project) }
it { is_expected.to be_disallowed(:update_project_member) }

View File

@ -253,25 +253,51 @@ RSpec.describe AlertManagement::Alerts::UpdateService do
end
end
shared_examples 'updates the incident escalation status with the new alert status' do
specify do
expect(::Issues::UpdateService).to receive(:new).once.and_call_original
expect(described_class).to receive(:new).once.and_call_original
expect { response }.to change { escalation_status&.reload&.acknowledged? }.to(true)
.and change { alert.reload.acknowledged? }.to(true)
end
end
it_behaves_like 'does not sync with the incident status'
context 'when feature flag is disabled' do
before do
stub_feature_flags(incident_escalations: false)
end
it_behaves_like 'does not sync with the incident status'
end
context 'when the issue is an incident' do
before do
issue.update!(issue_type: Issue.issue_types[:incident])
end
it_behaves_like 'does not sync with the incident status'
context 'when the incident does not have an escalation status' do
it_behaves_like 'updates the incident escalation status with the new alert status'
context 'when feature flag is disabled' do
before do
stub_feature_flags(incident_escalations: false)
end
it_behaves_like 'updates the incident escalation status with the new alert status'
end
def escalation_status
issue.reload.escalation_status
end
end
context 'when the incident has an escalation status' do
let_it_be(:escalation_status, reload: true) { create(:incident_management_issuable_escalation_status, issue: issue) }
it 'updates the incident escalation status with the new alert status' do
expect(::Issues::UpdateService).to receive(:new).once.and_call_original
expect(described_class).to receive(:new).once.and_call_original
expect { response }.to change { escalation_status.reload.acknowledged? }.to(true)
.and change { alert.reload.acknowledged? }.to(true)
end
it_behaves_like 'updates the incident escalation status with the new alert status'
context 'when the statuses match' do
before do
@ -286,7 +312,7 @@ RSpec.describe AlertManagement::Alerts::UpdateService do
stub_feature_flags(incident_escalations: false)
end
it_behaves_like 'does not sync with the incident status'
it_behaves_like 'updates the incident escalation status with the new alert status'
end
end
end

View File

@ -48,6 +48,29 @@ RSpec.describe IncidentManagement::IssuableEscalationStatuses::PrepareUpdateServ
end
it_behaves_like 'availability error response'
context 'with incident associated with alert' do
let(:alert_status) { :acknowledged }
before do
create(:alert_management_alert, alert_status, project: issue.project, issue: issue)
issue.reload
end
it_behaves_like 'successful response', { status_event: :acknowledge }
context 'when alert status does not match incident status' do
let(:alert_status) { :triggered }
include_examples 'error response', 'Invalid value was provided for parameters: status'
end
context 'with a standard issue' do
let(:issue) { create(:issue) }
it_behaves_like 'availability error response'
end
end
end
context 'when user is anonymous' do

View File

@ -98,6 +98,7 @@ RSpec.describe Issues::CreateService do
end
it_behaves_like 'not an incident issue'
include_examples 'does not call the escalation status CreateService'
context 'when issue is incident type' do
before do
@ -118,12 +119,22 @@ RSpec.describe Issues::CreateService do
end
it_behaves_like 'incident issue'
include_examples 'calls the escalation status CreateService'
it 'calls IncidentManagement::Incidents::CreateEscalationStatusService' do
expect_next(::IncidentManagement::IssuableEscalationStatuses::CreateService, a_kind_of(Issue))
.to receive(:execute)
context 'when :incident_escalations feature flag is disabled' do
before do
stub_feature_flags(incident_escalations: false)
end
issue
include_examples 'does not call the escalation status CreateService'
context 'with associated alert' do
before do
opts.merge!(alert_management_alert: build(:alert_management_alert, project: project))
end
include_examples 'calls the escalation status CreateService'
end
end
context 'when invalid' do

View File

@ -0,0 +1,22 @@
# frozen_string_literal: true
# This shared_example requires the following variables:
# - issue (required)
RSpec.shared_examples 'calls the escalation status CreateService' do
it 'calls IncidentManagement::Incidents::CreateEscalationStatusService' do
expect_next(::IncidentManagement::IssuableEscalationStatuses::CreateService, a_kind_of(Issue))
.to receive(:execute)
issue
end
end
# This shared_example requires the following variables:
# - issue (required)
RSpec.shared_examples 'does not call the escalation status CreateService' do
it 'does not call the ::IncidentManagement::IssuableEscalationStatuses::CreateService' do
expect(::IncidentManagement::IssuableEscalationStatuses::CreateService).not_to receive(:new)
issue
end
end