summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-04-06 12:08:29 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-04-06 12:08:29 +0000
commit39c98649d20e08428f507e0728b0bd87a299e5cf (patch)
tree6ca0ae12d9498f9158b7f8da9bad97f1517b0d83
parentc16b752f86f78442349b7b2cd9106109de10763b (diff)
downloadgitlab-ce-39c98649d20e08428f507e0728b0bd87a299e5cf.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.rubocop_todo.yml29
-rw-r--r--.rubocop_todo/performance/string_include.yml15
-rw-r--r--.rubocop_todo/rails/inquiry.yml4
-rw-r--r--.rubocop_todo/rails/render_inline.yml4
-rw-r--r--app/assets/images/learn_gitlab/graduation_hat.svg1
-rw-r--r--app/assets/javascripts/clusters_list/components/available_agents_dropdown.vue21
-rw-r--r--app/assets/javascripts/jobs/components/trigger_block.vue8
-rw-r--r--app/assets/stylesheets/framework/highlight.scss2
-rw-r--r--app/assets/stylesheets/highlight/hljs.scss125
-rw-r--r--app/assets/stylesheets/highlight/themes/dark.scss33
-rw-r--r--app/models/concerns/issuable.rb12
-rw-r--r--app/policies/project_member_policy.rb7
-rw-r--r--app/services/alert_management/alerts/update_service.rb21
-rw-r--r--app/services/incident_management/issuable_escalation_statuses/prepare_update_service.rb13
-rw-r--r--app/services/issues/create_service.rb5
-rw-r--r--config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20220307150912_p_ci_templates_database_liquibase_monthly.yml4
-rw-r--r--config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20220307150854_p_ci_templates_database_liquibase_weekly.yml4
-rw-r--r--db/post_migrate/20220204095121_backfill_namespace_statistics_with_dependency_proxy_size.rb25
-rw-r--r--db/schema_migrations/202202040951211
-rw-r--r--doc/ci/unit_test_reports.md2
-rw-r--r--doc/development/documentation/testing.md29
-rw-r--r--doc/index.md26
-rw-r--r--lefthook.yml2
-rw-r--r--lib/gitlab/background_migration/populate_namespace_statistics.rb33
-rw-r--r--lib/gitlab/ci/templates/Go.gitlab-ci.yml15
-rw-r--r--lib/gitlab/ci/templates/liquibase.gitlab-ci.yml (renamed from lib/gitlab/ci/templates/Database/liquibase.gitlab-ci.yml)6
-rw-r--r--lib/gitlab/data_builder/deployment.rb9
-rw-r--r--lib/gitlab/usage_data_counters/known_events/ci_templates.yml2
-rw-r--r--lib/sidebars/projects/menus/learn_gitlab_menu.rb6
-rw-r--r--spec/frontend/clusters_list/components/available_agents_dropwdown_spec.js21
-rw-r--r--spec/frontend/jobs/components/trigger_block_spec.js7
-rw-r--r--spec/lib/gitlab/background_migration/populate_namespace_statistics_spec.rb71
-rw-r--r--spec/lib/gitlab/data_builder/deployment_spec.rb19
-rw-r--r--spec/migrations/20220204095121_backfill_namespace_statistics_with_dependency_proxy_size_spec.rb64
-rw-r--r--spec/models/concerns/issuable_spec.rb27
-rw-r--r--spec/policies/project_member_policy_spec.rb6
-rw-r--r--spec/services/alert_management/alerts/update_service_spec.rb44
-rw-r--r--spec/services/incident_management/issuable_escalation_statuses/prepare_update_service_spec.rb23
-rw-r--r--spec/services/issues/create_service_spec.rb19
-rw-r--r--spec/support/shared_examples/services/incident_management/escalation_status_shared_examples.rb22
42 files changed, 666 insertions, 125 deletions
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index 21671ba56ae..534861d90b2 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -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
diff --git a/.rubocop_todo/performance/string_include.yml b/.rubocop_todo/performance/string_include.yml
new file mode 100644
index 00000000000..cb6e566094e
--- /dev/null
+++ b/.rubocop_todo/performance/string_include.yml
@@ -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'
diff --git a/.rubocop_todo/rails/inquiry.yml b/.rubocop_todo/rails/inquiry.yml
new file mode 100644
index 00000000000..3c999dfbc47
--- /dev/null
+++ b/.rubocop_todo/rails/inquiry.yml
@@ -0,0 +1,4 @@
+---
+Rails/Inquiry:
+ Exclude:
+ - 'spec/helpers/labels_helper_spec.rb'
diff --git a/.rubocop_todo/rails/render_inline.yml b/.rubocop_todo/rails/render_inline.yml
new file mode 100644
index 00000000000..fbebec72cd7
--- /dev/null
+++ b/.rubocop_todo/rails/render_inline.yml
@@ -0,0 +1,4 @@
+---
+Rails/RenderInline:
+ Exclude:
+ - 'ee/app/controllers/sitemap_controller.rb'
diff --git a/app/assets/images/learn_gitlab/graduation_hat.svg b/app/assets/images/learn_gitlab/graduation_hat.svg
deleted file mode 100644
index 998d8d9b935..00000000000
--- a/app/assets/images/learn_gitlab/graduation_hat.svg
+++ /dev/null
@@ -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> \ No newline at end of file
diff --git a/app/assets/javascripts/clusters_list/components/available_agents_dropdown.vue b/app/assets/javascripts/clusters_list/components/available_agents_dropdown.vue
index 662cf2a7e36..bde76c46b4b 100644
--- a/app/assets/javascripts/clusters_list/components/available_agents_dropdown.vue
+++ b/app/assets/javascripts/clusters_list/components/available_agents_dropdown.vue
@@ -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)">
diff --git a/app/assets/javascripts/jobs/components/trigger_block.vue b/app/assets/javascripts/jobs/components/trigger_block.vue
index b1ddede8fe8..1afc1c9a595 100644
--- a/app/assets/javascripts/jobs/components/trigger_block.vue
+++ b/app/assets/javascripts/jobs/components/trigger_block.vue
@@ -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>
diff --git a/app/assets/stylesheets/framework/highlight.scss b/app/assets/stylesheets/framework/highlight.scss
index a80643e695b..d3de284a2d6 100644
--- a/app/assets/stylesheets/framework/highlight.scss
+++ b/app/assets/stylesheets/framework/highlight.scss
@@ -1,3 +1,5 @@
+@import '../highlight/hljs';
+
.file-content.code {
border: 0;
box-shadow: none;
diff --git a/app/assets/stylesheets/highlight/hljs.scss b/app/assets/stylesheets/highlight/hljs.scss
new file mode 100644
index 00000000000..2e31e7c1f6d
--- /dev/null
+++ b/app/assets/stylesheets/highlight/hljs.scss
@@ -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);
+ }
+}
diff --git a/app/assets/stylesheets/highlight/themes/dark.scss b/app/assets/stylesheets/highlight/themes/dark.scss
index 28878280d24..fa2415bcb5e 100644
--- a/app/assets/stylesheets/highlight/themes/dark.scss
+++ b/app/assets/stylesheets/highlight/themes/dark.scss
@@ -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 {
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index 729170da242..f8ac180d3d7 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -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
diff --git a/app/policies/project_member_policy.rb b/app/policies/project_member_policy.rb
index 91f1eb35506..40ba30fce5e 100644
--- a/app/policies/project_member_policy.rb
+++ b/app/policies/project_member_policy.rb
@@ -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
diff --git a/app/services/alert_management/alerts/update_service.rb b/app/services/alert_management/alerts/update_service.rb
index 0769adc862e..7ca0fb4c6fb 100644
--- a/app/services/alert_management/alerts/update_service.rb
+++ b/app/services/alert_management/alerts/update_service.rb
@@ -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
diff --git a/app/services/incident_management/issuable_escalation_statuses/prepare_update_service.rb b/app/services/incident_management/issuable_escalation_statuses/prepare_update_service.rb
index 1d0504a6e80..d755cf61207 100644
--- a/app/services/incident_management/issuable_escalation_statuses/prepare_update_service.rb
+++ b/app/services/incident_management/issuable_escalation_statuses/prepare_update_service.rb
@@ -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
diff --git a/app/services/issues/create_service.rb b/app/services/issues/create_service.rb
index 7ab663718db..e7d7b3a70eb 100644
--- a/app/services/issues/create_service.rb
+++ b/app/services/issues/create_service.rb
@@ -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
diff --git a/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml
index 03a16b98a9b..217c20e574f 100644
--- a/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml
@@ -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
diff --git a/config/metrics/counts_28d/20220307150912_p_ci_templates_database_liquibase_monthly.yml b/config/metrics/counts_28d/20220307150912_p_ci_templates_database_liquibase_monthly.yml
index 07a5548474a..214c6504051 100644
--- a/config/metrics/counts_28d/20220307150912_p_ci_templates_database_liquibase_monthly.yml
+++ b/config/metrics/counts_28d/20220307150912_p_ci_templates_database_liquibase_monthly.yml
@@ -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
diff --git a/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml
index 062ed14d649..9368500ab13 100644
--- a/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml
+++ b/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml
@@ -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
diff --git a/config/metrics/counts_7d/20220307150854_p_ci_templates_database_liquibase_weekly.yml b/config/metrics/counts_7d/20220307150854_p_ci_templates_database_liquibase_weekly.yml
index de9757b9f17..c47c1fb51d5 100644
--- a/config/metrics/counts_7d/20220307150854_p_ci_templates_database_liquibase_weekly.yml
+++ b/config/metrics/counts_7d/20220307150854_p_ci_templates_database_liquibase_weekly.yml
@@ -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
diff --git a/db/post_migrate/20220204095121_backfill_namespace_statistics_with_dependency_proxy_size.rb b/db/post_migrate/20220204095121_backfill_namespace_statistics_with_dependency_proxy_size.rb
new file mode 100644
index 00000000000..49c9efc497c
--- /dev/null
+++ b/db/post_migrate/20220204095121_backfill_namespace_statistics_with_dependency_proxy_size.rb
@@ -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
diff --git a/db/schema_migrations/20220204095121 b/db/schema_migrations/20220204095121
new file mode 100644
index 00000000000..bf12ca08f5a
--- /dev/null
+++ b/db/schema_migrations/20220204095121
@@ -0,0 +1 @@
+bce595c1c6587e785bc49d6e5a7181b5cc0164f2201375ad82d4bd19c217cd35 \ No newline at end of file
diff --git a/doc/ci/unit_test_reports.md b/doc/ci/unit_test_reports.md
index 14350ac884f..029bd20c553 100644
--- a/doc/ci/unit_test_reports.md
+++ b/doc/ci/unit_test_reports.md
@@ -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
diff --git a/doc/development/documentation/testing.md b/doc/development/documentation/testing.md
index bb8f6a4b4a9..9facb22669b 100644
--- a/doc/development/documentation/testing.md
+++ b/doc/development/documentation/testing.md
@@ -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:
diff --git a/doc/index.md b/doc/index.md
index 57eb9e195ff..2f3bfefe819 100644
--- a/doc/index.md
+++ b/doc/index.md
@@ -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:
diff --git a/lefthook.yml b/lefthook.yml
index 086e70fcbb9..e79df94c708 100644
--- a/lefthook.yml
+++ b/lefthook.yml
@@ -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
diff --git a/lib/gitlab/background_migration/populate_namespace_statistics.rb b/lib/gitlab/background_migration/populate_namespace_statistics.rb
index e873ad412f2..97927ef48c2 100644
--- a/lib/gitlab/background_migration/populate_namespace_statistics.rb
+++ b/lib/gitlab/background_migration/populate_namespace_statistics.rb
@@ -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
diff --git a/lib/gitlab/ci/templates/Go.gitlab-ci.yml b/lib/gitlab/ci/templates/Go.gitlab-ci.yml
index 8514e50b256..bd8e1020c4e 100644
--- a/lib/gitlab/ci/templates/Go.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Go.gitlab-ci.yml
@@ -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
diff --git a/lib/gitlab/ci/templates/Database/liquibase.gitlab-ci.yml b/lib/gitlab/ci/templates/liquibase.gitlab-ci.yml
index 49bafca9952..18d59035b78 100644
--- a/lib/gitlab/ci/templates/Database/liquibase.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/liquibase.gitlab-ci.yml
@@ -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
diff --git a/lib/gitlab/data_builder/deployment.rb b/lib/gitlab/data_builder/deployment.rb
index a4508bc93c5..92c99d99210 100644
--- a/lib/gitlab/data_builder/deployment.rb
+++ b/lib/gitlab/data_builder/deployment.rb
@@ -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
diff --git a/lib/gitlab/usage_data_counters/known_events/ci_templates.yml b/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
index a5ec72fe8c9..917a7b5caec 100644
--- a/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
+++ b/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
@@ -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
diff --git a/lib/sidebars/projects/menus/learn_gitlab_menu.rb b/lib/sidebars/projects/menus/learn_gitlab_menu.rb
index 16335f5b076..5de70ea7d7f 100644
--- a/lib/sidebars/projects/menus/learn_gitlab_menu.rb
+++ b/lib/sidebars/projects/menus/learn_gitlab_menu.rb
@@ -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?
diff --git a/spec/frontend/clusters_list/components/available_agents_dropwdown_spec.js b/spec/frontend/clusters_list/components/available_agents_dropwdown_spec.js
index eca2b1f5cb1..197735d3c77 100644
--- a/spec/frontend/clusters_list/components/available_agents_dropwdown_spec.js
+++ b/spec/frontend/clusters_list/components/available_agents_dropwdown_spec.js
@@ -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', () => {
diff --git a/spec/frontend/jobs/components/trigger_block_spec.js b/spec/frontend/jobs/components/trigger_block_spec.js
index e0eb873dc2f..78596612d23 100644
--- a/spec/frontend/jobs/components/trigger_block_spec.js
+++ b/spec/frontend/jobs/components/trigger_block_spec.js
@@ -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', () => {
diff --git a/spec/lib/gitlab/background_migration/populate_namespace_statistics_spec.rb b/spec/lib/gitlab/background_migration/populate_namespace_statistics_spec.rb
new file mode 100644
index 00000000000..98b2bc437f3
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/populate_namespace_statistics_spec.rb
@@ -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
diff --git a/spec/lib/gitlab/data_builder/deployment_spec.rb b/spec/lib/gitlab/data_builder/deployment_spec.rb
index ab8c8a51694..e64e6ace6b4 100644
--- a/spec/lib/gitlab/data_builder/deployment_spec.rb
+++ b/spec/lib/gitlab/data_builder/deployment_spec.rb
@@ -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
diff --git a/spec/migrations/20220204095121_backfill_namespace_statistics_with_dependency_proxy_size_spec.rb b/spec/migrations/20220204095121_backfill_namespace_statistics_with_dependency_proxy_size_spec.rb
new file mode 100644
index 00000000000..39398fa058d
--- /dev/null
+++ b/spec/migrations/20220204095121_backfill_namespace_statistics_with_dependency_proxy_size_spec.rb
@@ -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
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index b38135fc0b2..12da5de5ef1 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -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
diff --git a/spec/policies/project_member_policy_spec.rb b/spec/policies/project_member_policy_spec.rb
index 12b3e60fdb2..b19ab71fcb5 100644
--- a/spec/policies/project_member_policy_spec.rb
+++ b/spec/policies/project_member_policy_spec.rb
@@ -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) }
diff --git a/spec/services/alert_management/alerts/update_service_spec.rb b/spec/services/alert_management/alerts/update_service_spec.rb
index 882543fd701..0388fe9e25c 100644
--- a/spec/services/alert_management/alerts/update_service_spec.rb
+++ b/spec/services/alert_management/alerts/update_service_spec.rb
@@ -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 the incident has an escalation status' do
- let_it_be(:escalation_status, reload: true) { create(:incident_management_issuable_escalation_status, issue: issue) }
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(incident_escalations: false)
+ end
- 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
+ it_behaves_like 'updates the incident escalation status with the new alert status'
+ end
- expect { response }.to change { escalation_status.reload.acknowledged? }.to(true)
- .and change { alert.reload.acknowledged? }.to(true)
+ 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_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
diff --git a/spec/services/incident_management/issuable_escalation_statuses/prepare_update_service_spec.rb b/spec/services/incident_management/issuable_escalation_statuses/prepare_update_service_spec.rb
index 25164df40ca..0ba26bf2c13 100644
--- a/spec/services/incident_management/issuable_escalation_statuses/prepare_update_service_spec.rb
+++ b/spec/services/incident_management/issuable_escalation_statuses/prepare_update_service_spec.rb
@@ -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
diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb
index 6b7b72d83fc..4b11b3cf40b 100644
--- a/spec/services/issues/create_service_spec.rb
+++ b/spec/services/issues/create_service_spec.rb
@@ -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
+
+ include_examples 'does not call the escalation status CreateService'
- issue
+ 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
diff --git a/spec/support/shared_examples/services/incident_management/escalation_status_shared_examples.rb b/spec/support/shared_examples/services/incident_management/escalation_status_shared_examples.rb
new file mode 100644
index 00000000000..d9fe217921c
--- /dev/null
+++ b/spec/support/shared_examples/services/incident_management/escalation_status_shared_examples.rb
@@ -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