Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-06-18 18:08:45 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-06-18 18:08:45 +0300
commit874c603d7a21724885ed24f15f457146aa1497c2 (patch)
tree9b562f45f9e79cd0bbba8e94e69511f620a1c3ed
parent8eef083ccd59505b606e9733d38589cbd3d01fdf (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/alert_management/components/sidebar/sidebar_assignees.vue2
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_emoji.js2
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_user.js2
-rw-r--r--app/assets/javascripts/issue_show/components/app.vue2
-rw-r--r--app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue20
-rw-r--r--app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue2
-rw-r--r--app/assets/javascripts/projects/commits/store/actions.js2
-rw-r--r--app/assets/javascripts/users_select/index.js4
-rw-r--r--app/assets/stylesheets/framework/common.scss1
-rw-r--r--app/graphql/types/release_asset_link_type.rb (renamed from app/graphql/types/release_link_type.rb)6
-rw-r--r--app/graphql/types/release_asset_link_type_enum.rb (renamed from app/graphql/types/release_link_type_enum.rb)4
-rw-r--r--app/graphql/types/release_assets_type.rb2
-rw-r--r--app/models/concerns/bulk_insert_safe.rb8
-rw-r--r--app/services/metrics/dashboard/base_service.rb3
-rw-r--r--app/services/metrics/dashboard/gitlab_alert_embed_service.rb2
-rw-r--r--app/services/metrics/dashboard/predefined_dashboard_service.rb3
-rw-r--r--app/services/metrics/dashboard/self_monitoring_dashboard_service.rb3
-rw-r--r--app/services/metrics/dashboard/system_dashboard_service.rb3
-rw-r--r--app/services/metrics/dashboard/transient_embed_service.rb2
-rw-r--r--app/services/prometheus/proxy_service.rb10
-rw-r--r--changelogs/unreleased/207312-remove-optimisticlocking-monkeypatch.yml5
-rw-r--r--changelogs/unreleased/29279-add-resend-confirmation-link-to-login-failure-message.yml5
-rw-r--r--changelogs/unreleased/sort-code-coverage-graph-by-dates.yml5
-rw-r--r--config/initializers/config_initializers_active_record_locking.rb46
-rw-r--r--config/locales/devise.en.yml2
-rw-r--r--danger/metadata/Dangerfile7
-rw-r--r--danger/specs/Dangerfile9
-rw-r--r--db/migrate/20200618134223_restore_previous_schema_without_lock_version_null_constraint.rb (renamed from db/post_migrate/20200608195222_set_lock_version_not_null_constraint.rb)11
-rw-r--r--db/migrate/20200618134723_restore_previous_schema_with_lock_version_indices.rb22
-rw-r--r--db/post_migrate/20200608205813_set_lock_version_to_not_null.rb19
-rw-r--r--db/post_migrate/20200608212030_lock_version_cleanup_for_epics.rb18
-rw-r--r--db/post_migrate/20200608212435_lock_version_cleanup_for_merge_requests.rb18
-rw-r--r--db/post_migrate/20200608212549_lock_version_cleanup_for_issues.rb18
-rw-r--r--db/post_migrate/20200608212652_lock_version_cleanup_for_ci_stages.rb18
-rw-r--r--db/post_migrate/20200608212807_lock_version_cleanup_for_ci_builds.rb18
-rw-r--r--db/post_migrate/20200608212824_lock_version_cleanup_for_ci_pipelines.rb18
-rw-r--r--db/structure.sql40
-rw-r--r--doc/api/graphql/reference/gitlab_schema.graphql182
-rw-r--r--doc/api/graphql/reference/gitlab_schema.json422
-rw-r--r--doc/api/graphql/reference/index.md24
-rw-r--r--doc/ci/interactive_web_terminal/index.md4
-rw-r--r--doc/development/insert_into_tables_in_batches.md6
-rw-r--r--doc/user/project/web_ide/index.md9
-rw-r--r--lib/gitlab/danger/changelog.rb9
-rw-r--r--lib/gitlab/metrics/dashboard/stages/base_stage.rb8
-rw-r--r--lib/gitlab/metrics/dashboard/stages/metric_endpoint_inserter.rb (renamed from lib/gitlab/metrics/dashboard/stages/endpoint_inserter.rb)4
-rw-r--r--lib/gitlab/metrics/dashboard/stages/variable_endpoint_inserter.rb34
-rw-r--r--locale/gitlab.pot3
-rw-r--r--spec/features/users/login_spec.rb6
-rw-r--r--spec/fixtures/lib/gitlab/metrics/dashboard/sample_dashboard.yml6
-rw-r--r--spec/fixtures/lib/gitlab/metrics/dashboard/schemas/metric_label_values_variable_full_syntax.json12
-rw-r--r--spec/fixtures/lib/gitlab/metrics/dashboard/schemas/metric_label_values_variable_options.json12
-rw-r--r--spec/fixtures/lib/gitlab/metrics/dashboard/schemas/variables.json3
-rw-r--r--spec/frontend/alert_management/components/alert_managment_sidebar_assignees_spec.js2
-rw-r--r--spec/frontend/filtered_search/dropdown_user_spec.js8
-rw-r--r--spec/frontend/pages/projects/graphs/code_coverage_spec.js6
-rw-r--r--spec/frontend/pages/projects/graphs/mock_data.js91
-rw-r--r--spec/frontend/projects/commits/store/actions_spec.js4
-rw-r--r--spec/graphql/types/release_asset_link_type_spec.rb (renamed from spec/graphql/types/release_links_type_spec.rb)2
-rw-r--r--spec/graphql/types/release_assets_type_spec.rb2
-rw-r--r--spec/lib/gitlab/metrics/dashboard/processor_spec.rb4
-rw-r--r--spec/lib/gitlab/metrics/dashboard/stages/variable_endpoint_inserter_spec.rb77
-rw-r--r--spec/migrations/20200526231421_update_index_approval_rule_name_for_code_owners_rule_type_spec.rb2
-rw-r--r--spec/migrations/cleanup_optimistic_locking_nulls_pt2_fixed_spec.rb2
-rw-r--r--spec/models/issue_spec.rb23
-rw-r--r--spec/models/merge_request_spec.rb23
-rw-r--r--spec/support/helpers/metrics_dashboard_helpers.rb4
-rw-r--r--spec/support/shared_examples/models/concerns/bulk_insert_safe_shared_examples.rb10
68 files changed, 778 insertions, 588 deletions
diff --git a/app/assets/javascripts/alert_management/components/sidebar/sidebar_assignees.vue b/app/assets/javascripts/alert_management/components/sidebar/sidebar_assignees.vue
index ce9f0fc4422..6c01fbcd788 100644
--- a/app/assets/javascripts/alert_management/components/sidebar/sidebar_assignees.vue
+++ b/app/assets/javascripts/alert_management/components/sidebar/sidebar_assignees.vue
@@ -126,7 +126,7 @@ export default {
updateAssigneesDropdown() {
this.isDropdownSearching = true;
return axios
- .get(this.buildUrl(gon.relative_url_root, '/autocomplete/users.json'), {
+ .get(this.buildUrl(gon.relative_url_root, '/-/autocomplete/users.json'), {
params: {
search: this.search,
per_page: 20,
diff --git a/app/assets/javascripts/filtered_search/dropdown_emoji.js b/app/assets/javascripts/filtered_search/dropdown_emoji.js
index dad188f6f98..adeea0ed5f6 100644
--- a/app/assets/javascripts/filtered_search/dropdown_emoji.js
+++ b/app/assets/javascripts/filtered_search/dropdown_emoji.js
@@ -10,7 +10,7 @@ export default class DropdownEmoji extends FilteredSearchDropdown {
super(options);
this.config = {
Ajax: {
- endpoint: `${gon.relative_url_root || ''}/autocomplete/award_emojis`,
+ endpoint: `${gon.relative_url_root || ''}/-/autocomplete/award_emojis`,
method: 'setData',
loadingTemplate: this.loadingTemplate,
onError() {
diff --git a/app/assets/javascripts/filtered_search/dropdown_user.js b/app/assets/javascripts/filtered_search/dropdown_user.js
index a65c0012b4d..0fb1828fc98 100644
--- a/app/assets/javascripts/filtered_search/dropdown_user.js
+++ b/app/assets/javascripts/filtered_search/dropdown_user.js
@@ -5,7 +5,7 @@ export default class DropdownUser extends DropdownAjaxFilter {
constructor(options = {}) {
super({
...options,
- endpoint: '/autocomplete/users.json',
+ endpoint: '/-/autocomplete/users.json',
symbol: '@',
});
}
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue
index 09acfd1cfae..a122e0f70f6 100644
--- a/app/assets/javascripts/issue_show/components/app.vue
+++ b/app/assets/javascripts/issue_show/components/app.vue
@@ -420,7 +420,7 @@ export default {
<transition name="issuable-header-slide">
<div
v-if="shouldShowStickyHeader"
- class="issue-sticky-header gl-fixed gl-z-index-2 gl-bg-white gl-border-1 gl-border-b-solid gl-border-b-gray-200 gl-py-3"
+ class="issue-sticky-header gl-fixed gl-z-index-3 gl-bg-white gl-border-1 gl-border-b-solid gl-border-b-gray-200 gl-py-3"
data-testid="issue-sticky-header"
>
<div
diff --git a/app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue b/app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue
index af8fb032c22..39d6df33a85 100644
--- a/app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue
+++ b/app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue
@@ -63,17 +63,19 @@ export default {
selectedDailyCoverageName() {
return this.selectedDailyCoverage?.group_name;
},
- formattedData() {
- if (this.selectedDailyCoverage?.data) {
- return this.selectedDailyCoverage.data.map(value => [
- dateFormat(value.date, 'mmm dd'),
- value.coverage,
- ]);
- }
-
+ sortedData() {
// If the fetching failed, we return an empty array which
// allow the graph to render while empty
- return [];
+ if (!this.selectedDailyCoverage?.data) {
+ return [];
+ }
+
+ return [...this.selectedDailyCoverage.data].sort(
+ (a, b) => new Date(a.date) - new Date(b.date),
+ );
+ },
+ formattedData() {
+ return this.sortedData.map(value => [dateFormat(value.date, 'mmm dd'), value.coverage]);
},
chartData() {
return [
diff --git a/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue b/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue
index e3429184c05..8d99ce6704e 100644
--- a/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue
+++ b/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue
@@ -28,7 +28,7 @@ export default {
columnClass() {
const positionValues = {
right: 'prepend-left-64',
- left: 'append-right-32',
+ left: 'gl-mr-7',
};
return `graph-position-${this.graphPosition} ${positionValues[this.graphPosition]}`;
},
diff --git a/app/assets/javascripts/projects/commits/store/actions.js b/app/assets/javascripts/projects/commits/store/actions.js
index 0a52a92ae9d..f0832bd36a5 100644
--- a/app/assets/javascripts/projects/commits/store/actions.js
+++ b/app/assets/javascripts/projects/commits/store/actions.js
@@ -18,7 +18,7 @@ export default {
fetchAuthors({ dispatch, state }, author = null) {
const { projectId } = state;
return axios
- .get(joinPaths(gon.relative_url_root || '', '/autocomplete/users.json'), {
+ .get(joinPaths(gon.relative_url_root || '', '/-/autocomplete/users.json'), {
params: {
project_id: projectId,
active: true,
diff --git a/app/assets/javascripts/users_select/index.js b/app/assets/javascripts/users_select/index.js
index 2dbe5a8171e..79ef10c456f 100644
--- a/app/assets/javascripts/users_select/index.js
+++ b/app/assets/javascripts/users_select/index.js
@@ -21,8 +21,8 @@ function UsersSelect(currentUser, els, options = {}) {
const $els = $(els || '.js-user-search');
this.users = this.users.bind(this);
this.user = this.user.bind(this);
- this.usersPath = '/autocomplete/users.json';
- this.userPath = '/autocomplete/users/:id.json';
+ this.usersPath = '/-/autocomplete/users.json';
+ this.userPath = '/-/autocomplete/users/:id.json';
if (currentUser != null) {
if (typeof currentUser === 'object') {
this.currentUser = currentUser;
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index 3feb2004242..1d756210b9c 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -415,7 +415,6 @@ img.emoji {
.append-right-15 { margin-right: 15px; }
.append-right-default { margin-right: $gl-padding; }
.append-right-20 { margin-right: 20px; }
-.append-right-32 { margin-right: 32px; }
.append-right-48 { margin-right: 48px; }
.prepend-right-32 { margin-right: 32px; }
.append-bottom-5 { margin-bottom: 5px; }
diff --git a/app/graphql/types/release_link_type.rb b/app/graphql/types/release_asset_link_type.rb
index 00fd05f6f7e..21f1bd50cff 100644
--- a/app/graphql/types/release_link_type.rb
+++ b/app/graphql/types/release_asset_link_type.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
module Types
- class ReleaseLinkType < BaseObject
- graphql_name 'ReleaseLink'
+ class ReleaseAssetLinkType < BaseObject
+ graphql_name 'ReleaseAssetLink'
description 'Represents an asset link associated with a release'
authorize :read_release
@@ -13,7 +13,7 @@ module Types
description: 'Name of the link'
field :url, GraphQL::STRING_TYPE, null: true,
description: 'URL of the link'
- field :link_type, Types::ReleaseLinkTypeEnum, null: true,
+ field :link_type, Types::ReleaseAssetLinkTypeEnum, null: true,
description: 'Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`'
field :external, GraphQL::BOOLEAN_TYPE, null: true, method: :external?,
description: 'Indicates the link points to an external resource'
diff --git a/app/graphql/types/release_link_type_enum.rb b/app/graphql/types/release_asset_link_type_enum.rb
index b364855833f..01862ada56d 100644
--- a/app/graphql/types/release_link_type_enum.rb
+++ b/app/graphql/types/release_asset_link_type_enum.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
module Types
- class ReleaseLinkTypeEnum < BaseEnum
- graphql_name 'ReleaseLinkType'
+ class ReleaseAssetLinkTypeEnum < BaseEnum
+ graphql_name 'ReleaseAssetLinkType'
description 'Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`'
::Releases::Link.link_types.keys.each do |link_type|
diff --git a/app/graphql/types/release_assets_type.rb b/app/graphql/types/release_assets_type.rb
index 45bfe5fe06f..d6042bdbc0b 100644
--- a/app/graphql/types/release_assets_type.rb
+++ b/app/graphql/types/release_assets_type.rb
@@ -13,7 +13,7 @@ module Types
field :count, GraphQL::INT_TYPE, null: true, method: :assets_count,
description: 'Number of assets of the release'
- field :links, Types::ReleaseLinkType.connection_type, null: true,
+ field :links, Types::ReleaseAssetLinkType.connection_type, null: true,
description: 'Asset links of the release'
field :sources, Types::ReleaseSourceType.connection_type, null: true,
description: 'Sources of the release'
diff --git a/app/models/concerns/bulk_insert_safe.rb b/app/models/concerns/bulk_insert_safe.rb
index e09f44e68dc..f9eb3fb875e 100644
--- a/app/models/concerns/bulk_insert_safe.rb
+++ b/app/models/concerns/bulk_insert_safe.rb
@@ -37,7 +37,7 @@ module BulkInsertSafe
# These are the callbacks we think safe when used on models that are
# written to the database in bulk
- CALLBACK_NAME_WHITELIST = Set[
+ ALLOWED_CALLBACKS = Set[
:initialize,
:validate,
:validation,
@@ -179,16 +179,12 @@ module BulkInsertSafe
end
def _bulk_insert_callback_allowed?(name, args)
- _bulk_insert_whitelisted?(name) || _bulk_insert_saved_from_belongs_to?(name, args)
+ ALLOWED_CALLBACKS.include?(name) || _bulk_insert_saved_from_belongs_to?(name, args)
end
# belongs_to associations will install a before_save hook during class loading
def _bulk_insert_saved_from_belongs_to?(name, args)
args.first == :before && args.second.to_s.start_with?('autosave_associated_records_for_')
end
-
- def _bulk_insert_whitelisted?(name)
- CALLBACK_NAME_WHITELIST.include?(name)
- end
end
end
diff --git a/app/services/metrics/dashboard/base_service.rb b/app/services/metrics/dashboard/base_service.rb
index c2a0f22e73e..503ef208cb3 100644
--- a/app/services/metrics/dashboard/base_service.rb
+++ b/app/services/metrics/dashboard/base_service.rb
@@ -10,7 +10,8 @@ module Metrics
STAGES = ::Gitlab::Metrics::Dashboard::Stages
SEQUENCE = [
STAGES::CommonMetricsInserter,
- STAGES::EndpointInserter,
+ STAGES::MetricEndpointInserter,
+ STAGES::VariableEndpointInserter,
STAGES::PanelIdsInserter,
STAGES::Sorter,
STAGES::AlertsInserter,
diff --git a/app/services/metrics/dashboard/gitlab_alert_embed_service.rb b/app/services/metrics/dashboard/gitlab_alert_embed_service.rb
index 38e89d392ad..08d65413e1d 100644
--- a/app/services/metrics/dashboard/gitlab_alert_embed_service.rb
+++ b/app/services/metrics/dashboard/gitlab_alert_embed_service.rb
@@ -11,7 +11,7 @@ module Metrics
include Gitlab::Utils::StrongMemoize
SEQUENCE = [
- STAGES::EndpointInserter,
+ STAGES::MetricEndpointInserter,
STAGES::PanelIdsInserter
].freeze
diff --git a/app/services/metrics/dashboard/predefined_dashboard_service.rb b/app/services/metrics/dashboard/predefined_dashboard_service.rb
index f454df63773..ee7a529dbc0 100644
--- a/app/services/metrics/dashboard/predefined_dashboard_service.rb
+++ b/app/services/metrics/dashboard/predefined_dashboard_service.rb
@@ -10,7 +10,8 @@ module Metrics
DASHBOARD_NAME = nil
SEQUENCE = [
- STAGES::EndpointInserter,
+ STAGES::MetricEndpointInserter,
+ STAGES::VariableEndpointInserter,
STAGES::PanelIdsInserter,
STAGES::Sorter
].freeze
diff --git a/app/services/metrics/dashboard/self_monitoring_dashboard_service.rb b/app/services/metrics/dashboard/self_monitoring_dashboard_service.rb
index 8599c23c206..afbcd73cd96 100644
--- a/app/services/metrics/dashboard/self_monitoring_dashboard_service.rb
+++ b/app/services/metrics/dashboard/self_monitoring_dashboard_service.rb
@@ -10,7 +10,8 @@ module Metrics
SEQUENCE = [
STAGES::CustomMetricsInserter,
- STAGES::EndpointInserter,
+ STAGES::MetricEndpointInserter,
+ STAGES::VariableEndpointInserter,
STAGES::PanelIdsInserter,
STAGES::Sorter
].freeze
diff --git a/app/services/metrics/dashboard/system_dashboard_service.rb b/app/services/metrics/dashboard/system_dashboard_service.rb
index db5599b4def..ff6cede18ae 100644
--- a/app/services/metrics/dashboard/system_dashboard_service.rb
+++ b/app/services/metrics/dashboard/system_dashboard_service.rb
@@ -12,7 +12,8 @@ module Metrics
STAGES::CommonMetricsInserter,
STAGES::CustomMetricsInserter,
STAGES::CustomMetricsDetailsInserter,
- STAGES::EndpointInserter,
+ STAGES::MetricEndpointInserter,
+ STAGES::VariableEndpointInserter,
STAGES::PanelIdsInserter,
STAGES::Sorter,
STAGES::AlertsInserter
diff --git a/app/services/metrics/dashboard/transient_embed_service.rb b/app/services/metrics/dashboard/transient_embed_service.rb
index cb6ca215447..9dd1d25692c 100644
--- a/app/services/metrics/dashboard/transient_embed_service.rb
+++ b/app/services/metrics/dashboard/transient_embed_service.rb
@@ -30,7 +30,7 @@ module Metrics
override :sequence
def sequence
- [STAGES::EndpointInserter]
+ [STAGES::MetricEndpointInserter]
end
override :identifiers
diff --git a/app/services/prometheus/proxy_service.rb b/app/services/prometheus/proxy_service.rb
index e0bc5518d30..33635796771 100644
--- a/app/services/prometheus/proxy_service.rb
+++ b/app/services/prometheus/proxy_service.rb
@@ -22,16 +22,20 @@ module Prometheus
attr_accessor :proxyable, :method, :path, :params
+ PROMETHEUS_QUERY_API = 'query'
+ PROMETHEUS_QUERY_RANGE_API = 'query_range'
+ PROMETHEUS_SERIES_API = 'series'
+
PROXY_SUPPORT = {
- 'query' => {
+ PROMETHEUS_QUERY_API => {
method: ['GET'],
params: %w(query time timeout)
},
- 'query_range' => {
+ PROMETHEUS_QUERY_RANGE_API => {
method: ['GET'],
params: %w(query start end step timeout)
},
- 'series' => {
+ PROMETHEUS_SERIES_API => {
method: %w(GET),
params: %w(match start end)
}
diff --git a/changelogs/unreleased/207312-remove-optimisticlocking-monkeypatch.yml b/changelogs/unreleased/207312-remove-optimisticlocking-monkeypatch.yml
deleted file mode 100644
index e2084b8170f..00000000000
--- a/changelogs/unreleased/207312-remove-optimisticlocking-monkeypatch.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove Rails Optimistic Locking monkeypatch
-merge_request: 25566
-author:
-type: fixed
diff --git a/changelogs/unreleased/29279-add-resend-confirmation-link-to-login-failure-message.yml b/changelogs/unreleased/29279-add-resend-confirmation-link-to-login-failure-message.yml
new file mode 100644
index 00000000000..e678a073f91
--- /dev/null
+++ b/changelogs/unreleased/29279-add-resend-confirmation-link-to-login-failure-message.yml
@@ -0,0 +1,5 @@
+---
+title: Improve error message when unconfirmed user tries to log in
+merge_request: 34818
+author:
+type: changed
diff --git a/changelogs/unreleased/sort-code-coverage-graph-by-dates.yml b/changelogs/unreleased/sort-code-coverage-graph-by-dates.yml
new file mode 100644
index 00000000000..43fa9d519df
--- /dev/null
+++ b/changelogs/unreleased/sort-code-coverage-graph-by-dates.yml
@@ -0,0 +1,5 @@
+---
+title: Sort code coverage graph in ascending order
+merge_request: 34750
+author:
+type: fixed
diff --git a/config/initializers/config_initializers_active_record_locking.rb b/config/initializers/config_initializers_active_record_locking.rb
new file mode 100644
index 00000000000..9f9908283c6
--- /dev/null
+++ b/config/initializers/config_initializers_active_record_locking.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+# ensure ActiveRecord's version has been required already
+require 'active_record/locking/optimistic'
+
+# rubocop:disable Lint/RescueException
+module ActiveRecord
+ module Locking
+ module Optimistic
+ private
+
+ def _update_row(attribute_names, attempted_action = "update")
+ return super unless locking_enabled?
+
+ begin
+ locking_column = self.class.locking_column
+ previous_lock_value = read_attribute_before_type_cast(locking_column)
+ attribute_names << locking_column
+
+ self[locking_column] += 1
+
+ # Patched because when `lock_version` is read as `0`, it may actually be `NULL` in the DB.
+ possible_previous_lock_value = previous_lock_value.to_i == 0 ? [nil, 0] : previous_lock_value
+
+ affected_rows = self.class.unscoped.where(
+ locking_column => possible_previous_lock_value,
+ self.class.primary_key => id_in_database
+ ).update_all(
+ attributes_with_values(attribute_names)
+ )
+
+ if affected_rows != 1
+ raise ActiveRecord::StaleObjectError.new(self, attempted_action)
+ end
+
+ affected_rows
+
+ # If something went wrong, revert the locking_column value.
+ rescue Exception
+ self[locking_column] = previous_lock_value.to_i
+ raise
+ end
+ end
+ end
+ end
+end
diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml
index bd4c3ebc69e..ee75ffbb8e9 100644
--- a/config/locales/devise.en.yml
+++ b/config/locales/devise.en.yml
@@ -15,7 +15,7 @@ en:
not_found_in_database: "Invalid %{authentication_keys} or password."
timeout: "Your session expired. Please sign in again to continue."
unauthenticated: "You need to sign in or sign up before continuing."
- unconfirmed: "You have to confirm your email address before continuing."
+ unconfirmed: "You have to confirm your email address before continuing. Please check your email for the link we sent you, or click 'Resend confirmation email'."
mailer:
confirmation_instructions:
subject: "Confirmation instructions"
diff --git a/danger/metadata/Dangerfile b/danger/metadata/Dangerfile
index b3313674951..504db88d1d3 100644
--- a/danger/metadata/Dangerfile
+++ b/danger/metadata/Dangerfile
@@ -4,8 +4,13 @@ THROUGHPUT_LABELS = [
'Community contribution',
'security',
'bug',
+ 'backstage', # To be removed by https://gitlab.com/gitlab-org/gitlab/-/issues/222360.
'feature',
- 'backstage',
+ 'feature::addition',
+ 'feature::maintenance',
+ 'tooling',
+ 'tooling::pipelines',
+ 'tooling::workflow',
'documentation'
].freeze
diff --git a/danger/specs/Dangerfile b/danger/specs/Dangerfile
index 784ce75fef8..d5951e6d6c1 100644
--- a/danger/specs/Dangerfile
+++ b/danger/specs/Dangerfile
@@ -1,6 +1,13 @@
# frozen_string_literal: true
-NO_SPECS_LABELS = %w[backstage documentation QA].freeze
+NO_SPECS_LABELS = [
+ 'backstage', # To be removed by https://gitlab.com/gitlab-org/gitlab/-/issues/222360.
+ 'tooling',
+ 'tooling::pipelines',
+ 'tooling::workflow',
+ 'documentation',
+ 'QA'
+].freeze
NO_NEW_SPEC_MESSAGE = <<~MSG
You've made some app changes, but didn't add any tests.
That's OK as long as you're refactoring existing code,
diff --git a/db/post_migrate/20200608195222_set_lock_version_not_null_constraint.rb b/db/migrate/20200618134223_restore_previous_schema_without_lock_version_null_constraint.rb
index ec72053b307..85e98d05d02 100644
--- a/db/post_migrate/20200608195222_set_lock_version_not_null_constraint.rb
+++ b/db/migrate/20200618134223_restore_previous_schema_without_lock_version_null_constraint.rb
@@ -1,23 +1,20 @@
# frozen_string_literal: true
-class SetLockVersionNotNullConstraint < ActiveRecord::Migration[6.0]
+class RestorePreviousSchemaWithoutLockVersionNullConstraint < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
+ TABLES = %i(epics merge_requests issues ci_stages ci_builds ci_pipelines).freeze
disable_ddl_transaction!
- TABLES = %i(epics merge_requests issues ci_stages ci_builds ci_pipelines).freeze
-
def up
TABLES.each do |table|
- add_not_null_constraint table, :lock_version, validate: false
+ remove_not_null_constraint table, :lock_version
end
end
def down
- TABLES.each do |table|
- remove_not_null_constraint table, :lock_version
- end
+ # no-op
end
end
diff --git a/db/migrate/20200618134723_restore_previous_schema_with_lock_version_indices.rb b/db/migrate/20200618134723_restore_previous_schema_with_lock_version_indices.rb
new file mode 100644
index 00000000000..64fdb373387
--- /dev/null
+++ b/db/migrate/20200618134723_restore_previous_schema_with_lock_version_indices.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class RestorePreviousSchemaWithLockVersionIndices < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :issues, :lock_version, where: "lock_version IS NULL"
+ add_concurrent_index :merge_requests, :lock_version, where: "lock_version IS NULL"
+ add_concurrent_index :epics, :lock_version, where: "lock_version IS NULL"
+ add_concurrent_index :ci_stages, :id, where: "lock_version IS NULL", name: "tmp_index_ci_stages_lock_version"
+ add_concurrent_index :ci_builds, :id, where: "lock_version IS NULL", name: "tmp_index_ci_builds_lock_version"
+ add_concurrent_index :ci_pipelines, :id, where: "lock_version IS NULL", name: "tmp_index_ci_pipelines_lock_version"
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20200608205813_set_lock_version_to_not_null.rb b/db/post_migrate/20200608205813_set_lock_version_to_not_null.rb
deleted file mode 100644
index fc97484ff4d..00000000000
--- a/db/post_migrate/20200608205813_set_lock_version_to_not_null.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class SetLockVersionToNotNull < ActiveRecord::Migration[6.0]
- DOWNTIME = false
-
- MODELS = [Epic, MergeRequest, Issue, Ci::Stage, Ci::Build, Ci::Pipeline].freeze
-
- disable_ddl_transaction!
-
- def up
- MODELS.each do |model|
- model.where(lock_version: nil).update_all(lock_version: 0)
- end
- end
-
- def down
- # Nothing to do...
- end
-end
diff --git a/db/post_migrate/20200608212030_lock_version_cleanup_for_epics.rb b/db/post_migrate/20200608212030_lock_version_cleanup_for_epics.rb
deleted file mode 100644
index 70faa1caca0..00000000000
--- a/db/post_migrate/20200608212030_lock_version_cleanup_for_epics.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class LockVersionCleanupForEpics < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- validate_not_null_constraint :epics, :lock_version
- remove_concurrent_index :epics, :lock_version, where: "lock_version IS NULL"
- end
-
- def down
- add_concurrent_index :epics, :lock_version, where: "lock_version IS NULL"
- end
-end
diff --git a/db/post_migrate/20200608212435_lock_version_cleanup_for_merge_requests.rb b/db/post_migrate/20200608212435_lock_version_cleanup_for_merge_requests.rb
deleted file mode 100644
index bc4ac3bdc31..00000000000
--- a/db/post_migrate/20200608212435_lock_version_cleanup_for_merge_requests.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class LockVersionCleanupForMergeRequests < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- validate_not_null_constraint :merge_requests, :lock_version
- remove_concurrent_index :merge_requests, :lock_version, where: "lock_version IS NULL"
- end
-
- def down
- add_concurrent_index :merge_requests, :lock_version, where: "lock_version IS NULL"
- end
-end
diff --git a/db/post_migrate/20200608212549_lock_version_cleanup_for_issues.rb b/db/post_migrate/20200608212549_lock_version_cleanup_for_issues.rb
deleted file mode 100644
index 21936ac4fa6..00000000000
--- a/db/post_migrate/20200608212549_lock_version_cleanup_for_issues.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class LockVersionCleanupForIssues < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- validate_not_null_constraint :issues, :lock_version
- remove_concurrent_index :issues, :lock_version, where: "lock_version IS NULL"
- end
-
- def down
- add_concurrent_index :issues, :lock_version, where: "lock_version IS NULL"
- end
-end
diff --git a/db/post_migrate/20200608212652_lock_version_cleanup_for_ci_stages.rb b/db/post_migrate/20200608212652_lock_version_cleanup_for_ci_stages.rb
deleted file mode 100644
index 12e2897123e..00000000000
--- a/db/post_migrate/20200608212652_lock_version_cleanup_for_ci_stages.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class LockVersionCleanupForCiStages < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- validate_not_null_constraint :ci_stages, :lock_version
- remove_concurrent_index :ci_stages, :id, where: "lock_version IS NULL", name: "tmp_index_ci_stages_lock_version"
- end
-
- def down
- add_concurrent_index :ci_stages, :id, where: "lock_version IS NULL", name: "tmp_index_ci_stages_lock_version"
- end
-end
diff --git a/db/post_migrate/20200608212807_lock_version_cleanup_for_ci_builds.rb b/db/post_migrate/20200608212807_lock_version_cleanup_for_ci_builds.rb
deleted file mode 100644
index 0512869971b..00000000000
--- a/db/post_migrate/20200608212807_lock_version_cleanup_for_ci_builds.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class LockVersionCleanupForCiBuilds < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- validate_not_null_constraint :ci_builds, :lock_version
- remove_concurrent_index :ci_builds, :id, where: "lock_version IS NULL", name: "tmp_index_ci_builds_lock_version"
- end
-
- def down
- add_concurrent_index :ci_builds, :id, where: "lock_version IS NULL", name: "tmp_index_ci_builds_lock_version"
- end
-end
diff --git a/db/post_migrate/20200608212824_lock_version_cleanup_for_ci_pipelines.rb b/db/post_migrate/20200608212824_lock_version_cleanup_for_ci_pipelines.rb
deleted file mode 100644
index 228dd72da8d..00000000000
--- a/db/post_migrate/20200608212824_lock_version_cleanup_for_ci_pipelines.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class LockVersionCleanupForCiPipelines < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- disable_ddl_transaction!
-
- def up
- validate_not_null_constraint :ci_pipelines, :lock_version
- remove_concurrent_index :ci_pipelines, :id, where: "lock_version IS NULL", name: "tmp_index_ci_pipelines_lock_version"
- end
-
- def down
- add_concurrent_index :ci_pipelines, :id, where: "lock_version IS NULL", name: "tmp_index_ci_pipelines_lock_version"
- end
-end
diff --git a/db/structure.sql b/db/structure.sql
index 06c23d84c77..6d26562a5f0 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -1056,8 +1056,7 @@ CREATE TABLE public.ci_builds (
resource_group_id bigint,
waiting_for_resource_at timestamp with time zone,
processed boolean,
- scheduling_type smallint,
- CONSTRAINT check_1e2fbd1b39 CHECK ((lock_version IS NOT NULL))
+ scheduling_type smallint
);
CREATE SEQUENCE public.ci_builds_id_seq
@@ -1368,8 +1367,7 @@ CREATE TABLE public.ci_pipelines (
source_sha bytea,
target_sha bytea,
external_pull_request_id bigint,
- ci_ref_id bigint,
- CONSTRAINT check_d7e99a025e CHECK ((lock_version IS NOT NULL))
+ ci_ref_id bigint
);
CREATE TABLE public.ci_pipelines_config (
@@ -1554,8 +1552,7 @@ CREATE TABLE public.ci_stages (
name character varying,
status integer,
lock_version integer DEFAULT 0,
- "position" integer,
- CONSTRAINT check_81b431e49b CHECK ((lock_version IS NOT NULL))
+ "position" integer
);
CREATE SEQUENCE public.ci_stages_id_seq
@@ -2514,8 +2511,7 @@ CREATE TABLE public.epics (
start_date_sourcing_epic_id integer,
due_date_sourcing_epic_id integer,
confidential boolean DEFAULT false NOT NULL,
- external_key character varying(255),
- CONSTRAINT check_fcfb4a93ff CHECK ((lock_version IS NOT NULL))
+ external_key character varying(255)
);
CREATE SEQUENCE public.epics_id_seq
@@ -3558,8 +3554,7 @@ CREATE TABLE public.issues (
promoted_to_epic_id integer,
health_status smallint,
external_key character varying(255),
- sprint_id bigint,
- CONSTRAINT check_fba63f706d CHECK ((lock_version IS NOT NULL))
+ sprint_id bigint
);
CREATE SEQUENCE public.issues_id_seq
@@ -4139,8 +4134,7 @@ CREATE TABLE public.merge_requests (
state_id smallint DEFAULT 1 NOT NULL,
rebase_jid character varying,
squash_commit_sha bytea,
- sprint_id bigint,
- CONSTRAINT check_970d272570 CHECK ((lock_version IS NOT NULL))
+ sprint_id bigint
);
CREATE TABLE public.merge_requests_closing_issues (
@@ -9892,6 +9886,8 @@ CREATE INDEX index_epics_on_iid ON public.epics USING btree (iid);
CREATE INDEX index_epics_on_last_edited_by_id ON public.epics USING btree (last_edited_by_id);
+CREATE INDEX index_epics_on_lock_version ON public.epics USING btree (lock_version) WHERE (lock_version IS NULL);
+
CREATE INDEX index_epics_on_parent_id ON public.epics USING btree (parent_id);
CREATE INDEX index_epics_on_start_date ON public.epics USING btree (start_date);
@@ -10138,6 +10134,8 @@ CREATE INDEX index_issues_on_duplicated_to_id ON public.issues USING btree (dupl
CREATE INDEX index_issues_on_last_edited_by_id ON public.issues USING btree (last_edited_by_id);
+CREATE INDEX index_issues_on_lock_version ON public.issues USING btree (lock_version) WHERE (lock_version IS NULL);
+
CREATE INDEX index_issues_on_milestone_id ON public.issues USING btree (milestone_id);
CREATE INDEX index_issues_on_moved_to_id ON public.issues USING btree (moved_to_id) WHERE (moved_to_id IS NOT NULL);
@@ -10304,6 +10302,8 @@ CREATE INDEX index_merge_requests_on_head_pipeline_id ON public.merge_requests U
CREATE INDEX index_merge_requests_on_latest_merge_request_diff_id ON public.merge_requests USING btree (latest_merge_request_diff_id);
+CREATE INDEX index_merge_requests_on_lock_version ON public.merge_requests USING btree (lock_version) WHERE (lock_version IS NULL);
+
CREATE INDEX index_merge_requests_on_merge_user_id ON public.merge_requests USING btree (merge_user_id) WHERE (merge_user_id IS NOT NULL);
CREATE INDEX index_merge_requests_on_milestone_id ON public.merge_requests USING btree (milestone_id);
@@ -11308,6 +11308,12 @@ CREATE INDEX tmp_build_stage_position_index ON public.ci_builds USING btree (sta
CREATE INDEX tmp_idx_on_user_id_where_bio_is_filled ON public.users USING btree (id) WHERE ((COALESCE(bio, ''::character varying))::text IS DISTINCT FROM ''::text);
+CREATE INDEX tmp_index_ci_builds_lock_version ON public.ci_builds USING btree (id) WHERE (lock_version IS NULL);
+
+CREATE INDEX tmp_index_ci_pipelines_lock_version ON public.ci_pipelines USING btree (id) WHERE (lock_version IS NULL);
+
+CREATE INDEX tmp_index_ci_stages_lock_version ON public.ci_stages USING btree (id) WHERE (lock_version IS NULL);
+
CREATE UNIQUE INDEX users_security_dashboard_projects_unique_index ON public.users_security_dashboard_projects USING btree (project_id, user_id);
CREATE UNIQUE INDEX vulnerability_feedback_unique_idx ON public.vulnerability_feedback USING btree (project_id, category, feedback_type, project_fingerprint);
@@ -14053,14 +14059,6 @@ COPY "schema_migrations" (version) FROM STDIN;
20200605093113
20200608072931
20200608075553
-20200608195222
-20200608205813
-20200608212030
-20200608212435
-20200608212549
-20200608212652
-20200608212807
-20200608212824
20200608214008
20200609002841
20200609142506
@@ -14080,5 +14078,7 @@ COPY "schema_migrations" (version) FROM STDIN;
20200617001637
20200617001848
20200617002030
+20200618134223
+20200618134723
\.
diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql
index 99ea456e737..c25f0988723 100644
--- a/doc/api/graphql/reference/gitlab_schema.graphql
+++ b/doc/api/graphql/reference/gitlab_schema.graphql
@@ -10208,6 +10208,96 @@ type Release {
}
"""
+Represents an asset link associated with a release
+"""
+type ReleaseAssetLink {
+ """
+ Indicates the link points to an external resource
+ """
+ external: Boolean
+
+ """
+ ID of the link
+ """
+ id: ID!
+
+ """
+ Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`
+ """
+ linkType: ReleaseAssetLinkType
+
+ """
+ Name of the link
+ """
+ name: String
+
+ """
+ URL of the link
+ """
+ url: String
+}
+
+"""
+The connection type for ReleaseAssetLink.
+"""
+type ReleaseAssetLinkConnection {
+ """
+ A list of edges.
+ """
+ edges: [ReleaseAssetLinkEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [ReleaseAssetLink]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type ReleaseAssetLinkEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: ReleaseAssetLink
+}
+
+"""
+Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`
+"""
+enum ReleaseAssetLinkType {
+ """
+ Image link type
+ """
+ IMAGE
+
+ """
+ Other link type
+ """
+ OTHER
+
+ """
+ Package link type
+ """
+ PACKAGE
+
+ """
+ Runbook link type
+ """
+ RUNBOOK
+}
+
+"""
A container for all assets associated with a release
"""
type ReleaseAssets {
@@ -10239,7 +10329,7 @@ type ReleaseAssets {
Returns the last _n_ elements from the list.
"""
last: Int
- ): ReleaseLinkConnection
+ ): ReleaseAssetLinkConnection
"""
Sources of the release
@@ -10363,96 +10453,6 @@ type ReleaseEvidenceEdge {
}
"""
-Represents an asset link associated with a release
-"""
-type ReleaseLink {
- """
- Indicates the link points to an external resource
- """
- external: Boolean
-
- """
- ID of the link
- """
- id: ID!
-
- """
- Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`
- """
- linkType: ReleaseLinkType
-
- """
- Name of the link
- """
- name: String
-
- """
- URL of the link
- """
- url: String
-}
-
-"""
-The connection type for ReleaseLink.
-"""
-type ReleaseLinkConnection {
- """
- A list of edges.
- """
- edges: [ReleaseLinkEdge]
-
- """
- A list of nodes.
- """
- nodes: [ReleaseLink]
-
- """
- Information to aid in pagination.
- """
- pageInfo: PageInfo!
-}
-
-"""
-An edge in a connection.
-"""
-type ReleaseLinkEdge {
- """
- A cursor for use in pagination.
- """
- cursor: String!
-
- """
- The item at the end of the edge.
- """
- node: ReleaseLink
-}
-
-"""
-Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`
-"""
-enum ReleaseLinkType {
- """
- Image link type
- """
- IMAGE
-
- """
- Other link type
- """
- OTHER
-
- """
- Package link type
- """
- PACKAGE
-
- """
- Runbook link type
- """
- RUNBOOK
-}
-
-"""
Represents the source code attached to a release in a particular format
"""
type ReleaseSource {
diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json
index 003f992c746..1ced40f96ca 100644
--- a/doc/api/graphql/reference/gitlab_schema.json
+++ b/doc/api/graphql/reference/gitlab_schema.json
@@ -29846,124 +29846,78 @@
},
{
"kind": "OBJECT",
- "name": "ReleaseAssets",
- "description": "A container for all assets associated with a release",
+ "name": "ReleaseAssetLink",
+ "description": "Represents an asset link associated with a release",
"fields": [
{
- "name": "count",
- "description": "Number of assets of the release",
+ "name": "external",
+ "description": "Indicates the link points to an external resource",
"args": [
],
"type": {
"kind": "SCALAR",
- "name": "Int",
+ "name": "Boolean",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
- "name": "links",
- "description": "Asset links of the release",
+ "name": "id",
+ "description": "ID of the link",
"args": [
- {
- "name": "after",
- "description": "Returns the elements in the list that come after the specified cursor.",
- "type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- },
- "defaultValue": null
- },
- {
- "name": "before",
- "description": "Returns the elements in the list that come before the specified cursor.",
- "type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- },
- "defaultValue": null
- },
- {
- "name": "first",
- "description": "Returns the first _n_ elements from the list.",
- "type": {
- "kind": "SCALAR",
- "name": "Int",
- "ofType": null
- },
- "defaultValue": null
- },
- {
- "name": "last",
- "description": "Returns the last _n_ elements from the list.",
- "type": {
- "kind": "SCALAR",
- "name": "Int",
- "ofType": null
- },
- "defaultValue": null
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
}
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "linkType",
+ "description": "Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`",
+ "args": [
+
],
"type": {
- "kind": "OBJECT",
- "name": "ReleaseLinkConnection",
+ "kind": "ENUM",
+ "name": "ReleaseAssetLinkType",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
- "name": "sources",
- "description": "Sources of the release",
+ "name": "name",
+ "description": "Name of the link",
"args": [
- {
- "name": "after",
- "description": "Returns the elements in the list that come after the specified cursor.",
- "type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- },
- "defaultValue": null
- },
- {
- "name": "before",
- "description": "Returns the elements in the list that come before the specified cursor.",
- "type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- },
- "defaultValue": null
- },
- {
- "name": "first",
- "description": "Returns the first _n_ elements from the list.",
- "type": {
- "kind": "SCALAR",
- "name": "Int",
- "ofType": null
- },
- "defaultValue": null
- },
- {
- "name": "last",
- "description": "Returns the last _n_ elements from the list.",
- "type": {
- "kind": "SCALAR",
- "name": "Int",
- "ofType": null
- },
- "defaultValue": null
- }
+
],
"type": {
- "kind": "OBJECT",
- "name": "ReleaseSourceConnection",
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "url",
+ "description": "URL of the link",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
"ofType": null
},
"isDeprecated": false,
@@ -29979,8 +29933,8 @@
},
{
"kind": "OBJECT",
- "name": "ReleaseConnection",
- "description": "The connection type for Release.",
+ "name": "ReleaseAssetLinkConnection",
+ "description": "The connection type for ReleaseAssetLink.",
"fields": [
{
"name": "edges",
@@ -29993,7 +29947,7 @@
"name": null,
"ofType": {
"kind": "OBJECT",
- "name": "ReleaseEdge",
+ "name": "ReleaseAssetLinkEdge",
"ofType": null
}
},
@@ -30011,7 +29965,7 @@
"name": null,
"ofType": {
"kind": "OBJECT",
- "name": "Release",
+ "name": "ReleaseAssetLink",
"ofType": null
}
},
@@ -30046,7 +30000,7 @@
},
{
"kind": "OBJECT",
- "name": "ReleaseEdge",
+ "name": "ReleaseAssetLinkEdge",
"description": "An edge in a connection.",
"fields": [
{
@@ -30075,7 +30029,7 @@
],
"type": {
"kind": "OBJECT",
- "name": "Release",
+ "name": "ReleaseAssetLink",
"ofType": null
},
"isDeprecated": false,
@@ -30090,65 +30044,160 @@
"possibleTypes": null
},
{
- "kind": "OBJECT",
- "name": "ReleaseEvidence",
- "description": "Evidence for a release",
- "fields": [
+ "kind": "ENUM",
+ "name": "ReleaseAssetLinkType",
+ "description": "Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
{
- "name": "collectedAt",
- "description": "Timestamp when the evidence was collected",
- "args": [
-
- ],
- "type": {
- "kind": "SCALAR",
- "name": "Time",
- "ofType": null
- },
+ "name": "OTHER",
+ "description": "Other link type",
"isDeprecated": false,
"deprecationReason": null
},
{
- "name": "filepath",
- "description": "URL from where the evidence can be downloaded",
+ "name": "RUNBOOK",
+ "description": "Runbook link type",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "PACKAGE",
+ "description": "Package link type",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "IMAGE",
+ "description": "Image link type",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "ReleaseAssets",
+ "description": "A container for all assets associated with a release",
+ "fields": [
+ {
+ "name": "count",
+ "description": "Number of assets of the release",
"args": [
],
"type": {
"kind": "SCALAR",
- "name": "String",
+ "name": "Int",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
- "name": "id",
- "description": "ID of the evidence",
+ "name": "links",
+ "description": "Asset links of the release",
"args": [
-
+ {
+ "name": "after",
+ "description": "Returns the elements in the list that come after the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "before",
+ "description": "Returns the elements in the list that come before the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "first",
+ "description": "Returns the first _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "last",
+ "description": "Returns the last _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
],
"type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "SCALAR",
- "name": "ID",
- "ofType": null
- }
+ "kind": "OBJECT",
+ "name": "ReleaseAssetLinkConnection",
+ "ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
- "name": "sha",
- "description": "SHA1 ID of the evidence hash",
+ "name": "sources",
+ "description": "Sources of the release",
"args": [
-
+ {
+ "name": "after",
+ "description": "Returns the elements in the list that come after the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "before",
+ "description": "Returns the elements in the list that come before the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "first",
+ "description": "Returns the first _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "last",
+ "description": "Returns the last _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
],
"type": {
- "kind": "SCALAR",
- "name": "String",
+ "kind": "OBJECT",
+ "name": "ReleaseSourceConnection",
"ofType": null
},
"isDeprecated": false,
@@ -30164,8 +30213,8 @@
},
{
"kind": "OBJECT",
- "name": "ReleaseEvidenceConnection",
- "description": "The connection type for ReleaseEvidence.",
+ "name": "ReleaseConnection",
+ "description": "The connection type for Release.",
"fields": [
{
"name": "edges",
@@ -30178,7 +30227,7 @@
"name": null,
"ofType": {
"kind": "OBJECT",
- "name": "ReleaseEvidenceEdge",
+ "name": "ReleaseEdge",
"ofType": null
}
},
@@ -30196,7 +30245,7 @@
"name": null,
"ofType": {
"kind": "OBJECT",
- "name": "ReleaseEvidence",
+ "name": "Release",
"ofType": null
}
},
@@ -30231,7 +30280,7 @@
},
{
"kind": "OBJECT",
- "name": "ReleaseEvidenceEdge",
+ "name": "ReleaseEdge",
"description": "An edge in a connection.",
"fields": [
{
@@ -30260,7 +30309,7 @@
],
"type": {
"kind": "OBJECT",
- "name": "ReleaseEvidence",
+ "name": "Release",
"ofType": null
},
"isDeprecated": false,
@@ -30276,72 +30325,58 @@
},
{
"kind": "OBJECT",
- "name": "ReleaseLink",
- "description": "Represents an asset link associated with a release",
+ "name": "ReleaseEvidence",
+ "description": "Evidence for a release",
"fields": [
{
- "name": "external",
- "description": "Indicates the link points to an external resource",
+ "name": "collectedAt",
+ "description": "Timestamp when the evidence was collected",
"args": [
],
"type": {
"kind": "SCALAR",
- "name": "Boolean",
+ "name": "Time",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
- "name": "id",
- "description": "ID of the link",
- "args": [
-
- ],
- "type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "SCALAR",
- "name": "ID",
- "ofType": null
- }
- },
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
- "name": "linkType",
- "description": "Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`",
+ "name": "filepath",
+ "description": "URL from where the evidence can be downloaded",
"args": [
],
"type": {
- "kind": "ENUM",
- "name": "ReleaseLinkType",
+ "kind": "SCALAR",
+ "name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
- "name": "name",
- "description": "Name of the link",
+ "name": "id",
+ "description": "ID of the evidence",
"args": [
],
"type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
},
"isDeprecated": false,
"deprecationReason": null
},
{
- "name": "url",
- "description": "URL of the link",
+ "name": "sha",
+ "description": "SHA1 ID of the evidence hash",
"args": [
],
@@ -30363,8 +30398,8 @@
},
{
"kind": "OBJECT",
- "name": "ReleaseLinkConnection",
- "description": "The connection type for ReleaseLink.",
+ "name": "ReleaseEvidenceConnection",
+ "description": "The connection type for ReleaseEvidence.",
"fields": [
{
"name": "edges",
@@ -30377,7 +30412,7 @@
"name": null,
"ofType": {
"kind": "OBJECT",
- "name": "ReleaseLinkEdge",
+ "name": "ReleaseEvidenceEdge",
"ofType": null
}
},
@@ -30395,7 +30430,7 @@
"name": null,
"ofType": {
"kind": "OBJECT",
- "name": "ReleaseLink",
+ "name": "ReleaseEvidence",
"ofType": null
}
},
@@ -30430,7 +30465,7 @@
},
{
"kind": "OBJECT",
- "name": "ReleaseLinkEdge",
+ "name": "ReleaseEvidenceEdge",
"description": "An edge in a connection.",
"fields": [
{
@@ -30459,7 +30494,7 @@
],
"type": {
"kind": "OBJECT",
- "name": "ReleaseLink",
+ "name": "ReleaseEvidence",
"ofType": null
},
"isDeprecated": false,
@@ -30474,41 +30509,6 @@
"possibleTypes": null
},
{
- "kind": "ENUM",
- "name": "ReleaseLinkType",
- "description": "Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`",
- "fields": null,
- "inputFields": null,
- "interfaces": null,
- "enumValues": [
- {
- "name": "OTHER",
- "description": "Other link type",
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
- "name": "RUNBOOK",
- "description": "Runbook link type",
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
- "name": "PACKAGE",
- "description": "Package link type",
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
- "name": "IMAGE",
- "description": "Image link type",
- "isDeprecated": false,
- "deprecationReason": null
- }
- ],
- "possibleTypes": null
- },
- {
"kind": "OBJECT",
"name": "ReleaseSource",
"description": "Represents the source code attached to a release in a particular format",
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index a8e033d3420..1245b553548 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -1415,6 +1415,18 @@ Represents a release
| `tagName` | String | Name of the tag associated with the release |
| `tagPath` | String | Relative web path to the tag associated with the release |
+## ReleaseAssetLink
+
+Represents an asset link associated with a release
+
+| Name | Type | Description |
+| --- | ---- | ---------- |
+| `external` | Boolean | Indicates the link points to an external resource |
+| `id` | ID! | ID of the link |
+| `linkType` | ReleaseAssetLinkType | Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other` |
+| `name` | String | Name of the link |
+| `url` | String | URL of the link |
+
## ReleaseAssets
A container for all assets associated with a release
@@ -1434,18 +1446,6 @@ Evidence for a release
| `id` | ID! | ID of the evidence |
| `sha` | String | SHA1 ID of the evidence hash |
-## ReleaseLink
-
-Represents an asset link associated with a release
-
-| Name | Type | Description |
-| --- | ---- | ---------- |
-| `external` | Boolean | Indicates the link points to an external resource |
-| `id` | ID! | ID of the link |
-| `linkType` | ReleaseLinkType | Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other` |
-| `name` | String | Name of the link |
-| `url` | String | URL of the link |
-
## ReleaseSource
Represents the source code attached to a release in a particular format
diff --git a/doc/ci/interactive_web_terminal/index.md b/doc/ci/interactive_web_terminal/index.md
index be3741332e0..385a9280202 100644
--- a/doc/ci/interactive_web_terminal/index.md
+++ b/doc/ci/interactive_web_terminal/index.md
@@ -67,6 +67,6 @@ close the terminal window.
![finished job with terminal open](img/finished_job_with_terminal_open.png)
-## Interactive Web Terminals for the Web IDE **(ULTIMATE ONLY)**
+## Interactive Web Terminals for the Web IDE
-Read the Web IDE docs to learn how to run [Interactive Terminals through the Web IDE](../../user/project/web_ide/index.md).
+Read the Web IDE docs to learn how to run [Interactive Terminals through the Web IDE](../../user/project/web_ide/index.md#interactive-web-terminals-for-the-web-ide).
diff --git a/doc/development/insert_into_tables_in_batches.md b/doc/development/insert_into_tables_in_batches.md
index d8919789808..f65d2478d2e 100644
--- a/doc/development/insert_into_tables_in_batches.md
+++ b/doc/development/insert_into_tables_in_batches.md
@@ -121,10 +121,10 @@ These callbacks cannot be used with bulk insertions, since they are meant to be
every instance that is saved or created. Since these events do not fire when
records are inserted in bulk, we currently disallow their use.
-The specifics around which callbacks are disallowed are defined in
+The specifics around which callbacks are explicitly allowed are defined in
[`BulkInsertSafe`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/concerns/bulk_insert_safe.rb).
-Consult the module source code for details. If your class uses any of the blacklisted
-functionality, and you `include BulkInsertSafe`, the application will fail with an error.
+Consult the module source code for details. If your class uses callbacks that are not explicitly designated
+safe and you `include BulkInsertSafe` the application will fail with an error.
### `BulkInsertSafe` versus `InsertAll`
diff --git a/doc/user/project/web_ide/index.md b/doc/user/project/web_ide/index.md
index 67164a6b6ca..4ae2a3c0d79 100644
--- a/doc/user/project/web_ide/index.md
+++ b/doc/user/project/web_ide/index.md
@@ -213,16 +213,19 @@ to work:
- The Runner needs to have
[`[session_server]` configured properly](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-session_server-section).
+ This section requires at least a `session_timeout` value (which defaults to 1800
+ seconds) and a `listen_address` value. If `advertise_address` is not defined, `listen_address` is used.
- If you are using a reverse proxy with your GitLab instance, web terminals need to be
[enabled](../../../administration/integration/terminal.md#enabling-and-disabling-terminal-support). **(ULTIMATE ONLY)**
If you have the terminal open and the job has finished with its tasks, the
terminal will block the job from finishing for the duration configured in
-[`[session_server].terminal_max_retention_time`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-session_server-section)
+[`[session_server].session_timeout`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-session_server-section)
until you close the terminal window.
NOTE: **Note:** Not all executors are
-[supported](https://docs.gitlab.com/runner/executors/#compatibility-chart)
+[supported](https://docs.gitlab.com/runner/executors/#compatibility-chart).
+The [File Sync](#file-syncing-to-web-terminal) feature is supported on Kubernetes runners only.
### Web IDE configuration file
@@ -246,6 +249,8 @@ In the code below there is an example of this configuration file:
```yaml
terminal:
+ # This can be any image that has the necessary runtime environment for your project.
+ image: node:10-alpine
before_script:
- apt-get update
script: sleep 60
diff --git a/lib/gitlab/danger/changelog.rb b/lib/gitlab/danger/changelog.rb
index 85f386594be..4589bc435e1 100644
--- a/lib/gitlab/danger/changelog.rb
+++ b/lib/gitlab/danger/changelog.rb
@@ -3,7 +3,14 @@
module Gitlab
module Danger
module Changelog
- NO_CHANGELOG_LABELS = %w[backstage ci-build meta].freeze
+ NO_CHANGELOG_LABELS = [
+ 'backstage', # To be removed by https://gitlab.com/gitlab-org/gitlab/-/issues/222360.
+ 'tooling',
+ 'tooling::pipelines',
+ 'tooling::workflow',
+ 'ci-build',
+ 'meta'
+ ].freeze
NO_CHANGELOG_CATEGORIES = %i[docs none].freeze
def needed?
diff --git a/lib/gitlab/metrics/dashboard/stages/base_stage.rb b/lib/gitlab/metrics/dashboard/stages/base_stage.rb
index 622d5aa8cdb..ee2d36621b4 100644
--- a/lib/gitlab/metrics/dashboard/stages/base_stage.rb
+++ b/lib/gitlab/metrics/dashboard/stages/base_stage.rb
@@ -48,6 +48,14 @@ module Gitlab
end
end
+ def for_variables
+ return unless dashboard.dig(:templating, :variables).is_a?(Hash)
+
+ dashboard.dig(:templating, :variables).each do |variable_name, variable|
+ yield variable_name, variable
+ end
+ end
+
def for_panel_groups
dashboard[:panel_groups].each do |panel_group|
yield panel_group
diff --git a/lib/gitlab/metrics/dashboard/stages/endpoint_inserter.rb b/lib/gitlab/metrics/dashboard/stages/metric_endpoint_inserter.rb
index e085f551952..fea0a24107e 100644
--- a/lib/gitlab/metrics/dashboard/stages/endpoint_inserter.rb
+++ b/lib/gitlab/metrics/dashboard/stages/metric_endpoint_inserter.rb
@@ -4,9 +4,9 @@ module Gitlab
module Metrics
module Dashboard
module Stages
- class EndpointInserter < BaseStage
+ class MetricEndpointInserter < BaseStage
def transform!
- raise Errors::DashboardProcessingError.new('Environment is required for Stages::EndpointInserter') unless params[:environment]
+ raise Errors::DashboardProcessingError.new('Environment is required for Stages::MetricEndpointInserter') unless params[:environment]
for_metrics do |metric|
metric[:prometheus_endpoint_path] = endpoint_for_metric(metric)
diff --git a/lib/gitlab/metrics/dashboard/stages/variable_endpoint_inserter.rb b/lib/gitlab/metrics/dashboard/stages/variable_endpoint_inserter.rb
new file mode 100644
index 00000000000..20e7fe477e5
--- /dev/null
+++ b/lib/gitlab/metrics/dashboard/stages/variable_endpoint_inserter.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Metrics
+ module Dashboard
+ module Stages
+ class VariableEndpointInserter < BaseStage
+ VARIABLE_TYPE_METRIC_LABEL_VALUES = 'metric_label_values'
+
+ def transform!
+ raise Errors::DashboardProcessingError.new(_('Environment is required for Stages::VariableEndpointInserter')) unless params[:environment]
+
+ for_variables do |variable_name, variable|
+ if variable.is_a?(Hash) && variable[:type] == VARIABLE_TYPE_METRIC_LABEL_VALUES
+ variable[:options][:prometheus_endpoint_path] = endpoint_for_variable(variable.dig(:options, :series_selector))
+ end
+ end
+ end
+
+ private
+
+ def endpoint_for_variable(series_selector)
+ Gitlab::Routing.url_helpers.prometheus_api_project_environment_path(
+ project,
+ params[:environment],
+ proxy_path: ::Prometheus::ProxyService::PROMETHEUS_SERIES_API,
+ match: Array(series_selector)
+ )
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 3f329917e75..5af8ffae8f3 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -8555,6 +8555,9 @@ msgstr ""
msgid "Environment does not have deployments"
msgstr ""
+msgid "Environment is required for Stages::VariableEndpointInserter"
+msgstr ""
+
msgid "Environment scope"
msgstr ""
diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb
index 7ba663d08d4..2d0fcfe84e6 100644
--- a/spec/features/users/login_spec.rb
+++ b/spec/features/users/login_spec.rb
@@ -110,7 +110,7 @@ RSpec.describe 'Login' do
gitlab_sign_in(user)
- expect(page).not_to have_content('You have to confirm your email address before continuing.')
+ expect(page).not_to have_content(I18n.t('devise.failure.unconfirmed'))
expect(page).not_to have_link('Resend confirmation email', href: new_user_confirmation_path)
end
end
@@ -124,7 +124,7 @@ RSpec.describe 'Login' do
gitlab_sign_in(user)
- expect(page).to have_content('You have to confirm your email address before continuing.')
+ expect(page).to have_content(I18n.t('devise.failure.unconfirmed'))
expect(page).to have_link('Resend confirmation email', href: new_user_confirmation_path)
end
end
@@ -820,7 +820,7 @@ RSpec.describe 'Login' do
gitlab_sign_in(user)
expect(current_path).to eq new_user_session_path
- expect(page).to have_content('You have to confirm your email address before continuing.')
+ expect(page).to have_content(I18n.t('devise.failure.unconfirmed'))
end
end
end
diff --git a/spec/fixtures/lib/gitlab/metrics/dashboard/sample_dashboard.yml b/spec/fixtures/lib/gitlab/metrics/dashboard/sample_dashboard.yml
index c888561978d..1e41ef669d1 100644
--- a/spec/fixtures/lib/gitlab/metrics/dashboard/sample_dashboard.yml
+++ b/spec/fixtures/lib/gitlab/metrics/dashboard/sample_dashboard.yml
@@ -24,6 +24,12 @@ templating:
- value: 'value_option_2'
text: 'Option 2'
default: true
+ metric_label_values_variable:
+ label: 'Variable 3'
+ type: metric_label_values
+ options:
+ series_selector: 'backend:haproxy_backend_availability:ratio{env="{{env}}"}'
+ label: 'backend'
panel_groups:
- group: Group A
priority: 1
diff --git a/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/metric_label_values_variable_full_syntax.json b/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/metric_label_values_variable_full_syntax.json
new file mode 100644
index 00000000000..6eb2c0e51e2
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/metric_label_values_variable_full_syntax.json
@@ -0,0 +1,12 @@
+{
+ "type": "object",
+ "required": [
+ "type", "options"
+ ],
+ "properties": {
+ "type": { "enum": "metric_label_values" },
+ "label": { "type": "string" },
+ "options": { "$ref": "metric_label_values_variable_options.json" }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/metric_label_values_variable_options.json b/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/metric_label_values_variable_options.json
new file mode 100644
index 00000000000..304372ed876
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/metric_label_values_variable_options.json
@@ -0,0 +1,12 @@
+{
+ "type": "object",
+ "required": [
+ "series_selector", "label", "prometheus_endpoint_path"
+ ],
+ "properties": {
+ "series_selector": { "type": "string" },
+ "label": { "type": "string" },
+ "prometheus_endpoint_path": { "type": "string" }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/variables.json b/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/variables.json
index e9b36fe20ce..aec129111e0 100644
--- a/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/variables.json
+++ b/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/variables.json
@@ -9,7 +9,8 @@
"type": "array",
"items": { "type": "string" }
},
- { "$ref": "custom_variable_full_syntax.json" }
+ { "$ref": "custom_variable_full_syntax.json" },
+ { "$ref": "metric_label_values_variable_full_syntax.json" }
]
}
},
diff --git a/spec/frontend/alert_management/components/alert_managment_sidebar_assignees_spec.js b/spec/frontend/alert_management/components/alert_managment_sidebar_assignees_spec.js
index 45f7f8f4444..2452ba7c63b 100644
--- a/spec/frontend/alert_management/components/alert_managment_sidebar_assignees_spec.js
+++ b/spec/frontend/alert_management/components/alert_managment_sidebar_assignees_spec.js
@@ -70,7 +70,7 @@ describe('Alert Details Sidebar Assignees', () => {
beforeEach(() => {
mock = new MockAdapter(axios);
- const path = '/autocomplete/users.json';
+ const path = '/-/autocomplete/users.json';
const users = [
{
avatar_url:
diff --git a/spec/frontend/filtered_search/dropdown_user_spec.js b/spec/frontend/filtered_search/dropdown_user_spec.js
index 8eef10290bf..c1c09ea5d3e 100644
--- a/spec/frontend/filtered_search/dropdown_user_spec.js
+++ b/spec/frontend/filtered_search/dropdown_user_spec.js
@@ -48,13 +48,13 @@ describe('Dropdown User', () => {
};
const dropdown = new DropdownUser();
- expect(dropdown.config.AjaxFilter.endpoint).toBe('/autocomplete/users.json');
+ expect(dropdown.config.AjaxFilter.endpoint).toBe('/-/autocomplete/users.json');
});
it('should return endpoint when relative_url_root is undefined', () => {
const dropdown = new DropdownUser();
- expect(dropdown.config.AjaxFilter.endpoint).toBe('/autocomplete/users.json');
+ expect(dropdown.config.AjaxFilter.endpoint).toBe('/-/autocomplete/users.json');
});
it('should return endpoint with relative url when available', () => {
@@ -63,7 +63,9 @@ describe('Dropdown User', () => {
};
const dropdown = new DropdownUser();
- expect(dropdown.config.AjaxFilter.endpoint).toBe('/gitlab_directory/autocomplete/users.json');
+ expect(dropdown.config.AjaxFilter.endpoint).toBe(
+ '/gitlab_directory/-/autocomplete/users.json',
+ );
});
afterEach(() => {
diff --git a/spec/frontend/pages/projects/graphs/code_coverage_spec.js b/spec/frontend/pages/projects/graphs/code_coverage_spec.js
index 4990985b076..30c7ff78c6e 100644
--- a/spec/frontend/pages/projects/graphs/code_coverage_spec.js
+++ b/spec/frontend/pages/projects/graphs/code_coverage_spec.js
@@ -5,7 +5,7 @@ import { GlAreaChart } from '@gitlab/ui/dist/charts';
import axios from '~/lib/utils/axios_utils';
import CodeCoverage from '~/pages/projects/graphs/components/code_coverage.vue';
-import codeCoverageMockData from './mock_data';
+import { codeCoverageMockData, sortedDataByDates } from './mock_data';
import waitForPromises from 'helpers/wait_for_promises';
import httpStatusCodes from '~/lib/utils/http_status';
@@ -52,6 +52,10 @@ describe('Code Coverage', () => {
expect(findAreaChart().exists()).toBe(true);
});
+ it('sorts the dates in ascending order', () => {
+ expect(wrapper.vm.sortedData).toEqual(sortedDataByDates);
+ });
+
it('matches the snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
});
diff --git a/spec/frontend/pages/projects/graphs/mock_data.js b/spec/frontend/pages/projects/graphs/mock_data.js
index a15f861ee7a..28d97b9d3f0 100644
--- a/spec/frontend/pages/projects/graphs/mock_data.js
+++ b/spec/frontend/pages/projects/graphs/mock_data.js
@@ -1,60 +1,69 @@
-export default [
+export const codeCoverageMockData = [
{
group_name: 'rspec',
data: [
- { date: '2020-04-30', coverage: 40.0 },
- { date: '2020-05-01', coverage: 80.0 },
- { date: '2020-05-02', coverage: 99.0 },
- { date: '2020-05-10', coverage: 80.0 },
- { date: '2020-05-15', coverage: 70.0 },
{ date: '2020-05-20', coverage: 69.0 },
+ { date: '2020-05-15', coverage: 70.0 },
+ { date: '2020-05-10', coverage: 80.0 },
+ { date: '2020-05-02', coverage: 99.0 },
+ { date: '2020-05-01', coverage: 80.0 },
+ { date: '2020-04-30', coverage: 40.0 },
],
},
{
group_name: 'cypress',
data: [
- { date: '2022-07-30', coverage: 1.0 },
- { date: '2022-08-01', coverage: 2.4 },
- { date: '2022-08-02', coverage: 5.0 },
- { date: '2022-08-10', coverage: 15.0 },
- { date: '2022-08-15', coverage: 30.0 },
{ date: '2022-08-20', coverage: 40.0 },
+ { date: '2022-08-15', coverage: 30.0 },
+ { date: '2022-08-10', coverage: 15.0 },
+ { date: '2022-08-02', coverage: 5.0 },
+ { date: '2022-08-01', coverage: 2.4 },
+ { date: '2022-07-30', coverage: 1.0 },
],
},
{
group_name: 'karma',
data: [
- { date: '2020-05-01', coverage: 94.0 },
- { date: '2020-05-02', coverage: 94.0 },
- { date: '2020-05-03', coverage: 94.0 },
- { date: '2020-05-04', coverage: 94.0 },
- { date: '2020-05-05', coverage: 92.0 },
- { date: '2020-05-06', coverage: 91.0 },
- { date: '2020-05-07', coverage: 78.0 },
- { date: '2020-05-08', coverage: 94.0 },
- { date: '2020-05-09', coverage: 94.0 },
- { date: '2020-05-10', coverage: 94.0 },
- { date: '2020-05-11', coverage: 94.0 },
- { date: '2020-05-12', coverage: 94.0 },
- { date: '2020-05-13', coverage: 92.0 },
- { date: '2020-05-14', coverage: 91.0 },
- { date: '2020-05-15', coverage: 78.0 },
- { date: '2020-05-16', coverage: 94.0 },
- { date: '2020-05-17', coverage: 94.0 },
- { date: '2020-05-18', coverage: 93.0 },
- { date: '2020-05-19', coverage: 92.0 },
- { date: '2020-05-20', coverage: 91.0 },
- { date: '2020-05-21', coverage: 90.0 },
- { date: '2020-05-22', coverage: 91.0 },
- { date: '2020-05-23', coverage: 92.0 },
- { date: '2020-05-24', coverage: 75.0 },
- { date: '2020-05-25', coverage: 74.0 },
- { date: '2020-05-26', coverage: 74.0 },
- { date: '2020-05-27', coverage: 74.0 },
- { date: '2020-05-28', coverage: 80.0 },
- { date: '2020-05-29', coverage: 85.0 },
- { date: '2020-05-30', coverage: 92.0 },
{ date: '2020-05-31', coverage: 91.0 },
+ { date: '2020-05-30', coverage: 94.0 },
+ { date: '2020-05-29', coverage: 94.0 },
+ { date: '2020-05-28', coverage: 92.0 },
+ { date: '2020-05-27', coverage: 91.0 },
+ { date: '2020-05-26', coverage: 78.0 },
+ { date: '2020-05-25', coverage: 94.0 },
+ { date: '2020-05-24', coverage: 94.0 },
+ { date: '2020-05-23', coverage: 94.0 },
+ { date: '2020-05-22', coverage: 94.0 },
+ { date: '2020-05-21', coverage: 94.0 },
+ { date: '2020-05-20', coverage: 92.0 },
+ { date: '2020-05-19', coverage: 91.0 },
+ { date: '2020-05-18', coverage: 78.0 },
+ { date: '2020-05-17', coverage: 94.0 },
+ { date: '2020-05-16', coverage: 94.0 },
+ { date: '2020-05-15', coverage: 93.0 },
+ { date: '2020-05-14', coverage: 92.0 },
+ { date: '2020-05-13', coverage: 91.0 },
+ { date: '2020-05-12', coverage: 90.0 },
+ { date: '2020-05-11', coverage: 91.0 },
+ { date: '2020-05-10', coverage: 92.0 },
+ { date: '2020-05-09', coverage: 75.0 },
+ { date: '2020-05-08', coverage: 74.0 },
+ { date: '2020-05-07', coverage: 74.0 },
+ { date: '2020-05-06', coverage: 74.0 },
+ { date: '2020-05-05', coverage: 80.0 },
+ { date: '2020-05-04', coverage: 85.0 },
+ { date: '2020-05-03', coverage: 92.0 },
+ { date: '2020-05-02', coverage: 94.0 },
+ { date: '2020-05-01', coverage: 94.0 },
],
},
];
+
+export const sortedDataByDates = [
+ { date: '2020-04-30', coverage: 40.0 },
+ { date: '2020-05-01', coverage: 80.0 },
+ { date: '2020-05-02', coverage: 99.0 },
+ { date: '2020-05-10', coverage: 80.0 },
+ { date: '2020-05-15', coverage: 70.0 },
+ { date: '2020-05-20', coverage: 69.0 },
+];
diff --git a/spec/frontend/projects/commits/store/actions_spec.js b/spec/frontend/projects/commits/store/actions_spec.js
index c9945e1cc27..886224252ad 100644
--- a/spec/frontend/projects/commits/store/actions_spec.js
+++ b/spec/frontend/projects/commits/store/actions_spec.js
@@ -45,7 +45,7 @@ describe('Project commits actions', () => {
describe('fetchAuthors', () => {
it('dispatches request/receive', () => {
- const path = '/autocomplete/users.json';
+ const path = '/-/autocomplete/users.json';
state.projectId = '8';
const data = [{ id: 1 }];
@@ -60,7 +60,7 @@ describe('Project commits actions', () => {
});
it('dispatches request/receive on error', () => {
- const path = '/autocomplete/users.json';
+ const path = '/-/autocomplete/users.json';
mock.onGet(path).replyOnce(500);
testAction(actions.fetchAuthors, null, state, [], [{ type: 'receiveAuthorsError' }]);
diff --git a/spec/graphql/types/release_links_type_spec.rb b/spec/graphql/types/release_asset_link_type_spec.rb
index 49e04e120f4..4da630c6500 100644
--- a/spec/graphql/types/release_links_type_spec.rb
+++ b/spec/graphql/types/release_asset_link_type_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-describe GitlabSchema.types['ReleaseLink'] do
+describe GitlabSchema.types['ReleaseAssetLink'] do
it { expect(described_class).to require_graphql_authorizations(:read_release) }
it 'has the expected fields' do
diff --git a/spec/graphql/types/release_assets_type_spec.rb b/spec/graphql/types/release_assets_type_spec.rb
index d8db162db62..655098c4684 100644
--- a/spec/graphql/types/release_assets_type_spec.rb
+++ b/spec/graphql/types/release_assets_type_spec.rb
@@ -16,7 +16,7 @@ describe GitlabSchema.types['ReleaseAssets'] do
describe 'links field' do
subject { described_class.fields['links'] }
- it { is_expected.to have_graphql_type(Types::ReleaseLinkType.connection_type) }
+ it { is_expected.to have_graphql_type(Types::ReleaseAssetLinkType.connection_type) }
end
describe 'sources field' do
diff --git a/spec/lib/gitlab/metrics/dashboard/processor_spec.rb b/spec/lib/gitlab/metrics/dashboard/processor_spec.rb
index 7250cefb9ff..a1decbe0446 100644
--- a/spec/lib/gitlab/metrics/dashboard/processor_spec.rb
+++ b/spec/lib/gitlab/metrics/dashboard/processor_spec.rb
@@ -13,7 +13,7 @@ describe Gitlab::Metrics::Dashboard::Processor do
Gitlab::Metrics::Dashboard::Stages::CommonMetricsInserter,
Gitlab::Metrics::Dashboard::Stages::CustomMetricsInserter,
Gitlab::Metrics::Dashboard::Stages::CustomMetricsDetailsInserter,
- Gitlab::Metrics::Dashboard::Stages::EndpointInserter,
+ Gitlab::Metrics::Dashboard::Stages::MetricEndpointInserter,
Gitlab::Metrics::Dashboard::Stages::Sorter,
Gitlab::Metrics::Dashboard::Stages::AlertsInserter,
Gitlab::Metrics::Dashboard::Stages::PanelIdsInserter,
@@ -98,7 +98,7 @@ describe Gitlab::Metrics::Dashboard::Processor do
let(:sequence) do
[
Gitlab::Metrics::Dashboard::Stages::CommonMetricsInserter,
- Gitlab::Metrics::Dashboard::Stages::EndpointInserter,
+ Gitlab::Metrics::Dashboard::Stages::MetricEndpointInserter,
Gitlab::Metrics::Dashboard::Stages::Sorter
]
end
diff --git a/spec/lib/gitlab/metrics/dashboard/stages/variable_endpoint_inserter_spec.rb b/spec/lib/gitlab/metrics/dashboard/stages/variable_endpoint_inserter_spec.rb
new file mode 100644
index 00000000000..06e789d025b
--- /dev/null
+++ b/spec/lib/gitlab/metrics/dashboard/stages/variable_endpoint_inserter_spec.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Metrics::Dashboard::Stages::VariableEndpointInserter do
+ include MetricsDashboardHelpers
+
+ let(:project) { build_stubbed(:project) }
+ let(:environment) { build_stubbed(:environment, project: project) }
+
+ describe '#transform!' do
+ subject(:transform!) { described_class.new(project, dashboard, environment: environment).transform! }
+
+ let(:dashboard) { load_sample_dashboard.deep_symbolize_keys }
+
+ context 'when dashboard variables are present' do
+ it 'assigns prometheus_endpoint_path to metric_label_values variable type' do
+ endpoint_path = Gitlab::Routing.url_helpers.prometheus_api_project_environment_path(
+ project,
+ environment,
+ proxy_path: :series,
+ match: ['backend:haproxy_backend_availability:ratio{env="{{env}}"}']
+ )
+
+ transform!
+
+ expect(
+ dashboard.dig(:templating, :variables, :metric_label_values_variable, :options)
+ ).to include(prometheus_endpoint_path: endpoint_path)
+ end
+
+ it 'does not modify other variable types' do
+ original_text_variable = dashboard[:templating][:variables][:text_variable_full_syntax].deep_dup
+
+ transform!
+
+ expect(dashboard[:templating][:variables][:text_variable_full_syntax]).to eq(original_text_variable)
+ end
+
+ context 'when variable does not have the required series_selector' do
+ it 'adds prometheus_endpoint_path without match parameter' do
+ dashboard[:templating][:variables][:metric_label_values_variable][:options].delete(:series_selector)
+ endpoint_path = Gitlab::Routing.url_helpers.prometheus_api_project_environment_path(
+ project,
+ environment,
+ proxy_path: :series
+ )
+
+ transform!
+
+ expect(
+ dashboard.dig(:templating, :variables, :metric_label_values_variable, :options)
+ ).to include(prometheus_endpoint_path: endpoint_path)
+ end
+ end
+ end
+
+ context 'when no variables are present' do
+ it 'does not fail' do
+ dashboard.delete(:templating)
+
+ expect { transform! }.not_to raise_error
+ end
+ end
+
+ context 'with no environment' do
+ subject(:transform!) { described_class.new(project, dashboard, {}).transform! }
+
+ it 'raises error' do
+ expect { transform! }.to raise_error(
+ Gitlab::Metrics::Dashboard::Errors::DashboardProcessingError,
+ 'Environment is required for Stages::VariableEndpointInserter'
+ )
+ end
+ end
+ end
+end
diff --git a/spec/migrations/20200526231421_update_index_approval_rule_name_for_code_owners_rule_type_spec.rb b/spec/migrations/20200526231421_update_index_approval_rule_name_for_code_owners_rule_type_spec.rb
index df98316490b..9842cfbc28d 100644
--- a/spec/migrations/20200526231421_update_index_approval_rule_name_for_code_owners_rule_type_spec.rb
+++ b/spec/migrations/20200526231421_update_index_approval_rule_name_for_code_owners_rule_type_spec.rb
@@ -151,7 +151,7 @@ describe UpdateIndexApprovalRuleNameForCodeOwnersRuleType do
expect(MergeRequests::SyncCodeOwnerApprovalRules)
.to receive(:new).with(MergeRequest.find(merge_request.id)).once.and_call_original
- # We expect approval_rules.count to be changed by -2 as we're deleting the
+ # We expect approval_rules.count to be changed by -3 as we're deleting the
# 3 rules created above, and MergeRequests::SyncCodeOwnerApprovalRules
# will not be able to create new one with an empty (or missing)
# CODEOWNERS file.
diff --git a/spec/migrations/cleanup_optimistic_locking_nulls_pt2_fixed_spec.rb b/spec/migrations/cleanup_optimistic_locking_nulls_pt2_fixed_spec.rb
index d6dd90e1320..2e5e450afc7 100644
--- a/spec/migrations/cleanup_optimistic_locking_nulls_pt2_fixed_spec.rb
+++ b/spec/migrations/cleanup_optimistic_locking_nulls_pt2_fixed_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20200427064130_cleanup_optimistic_locking_nulls_pt2_fixed.rb')
-describe CleanupOptimisticLockingNullsPt2Fixed, :migration, schema: 20200219193117 do
+describe CleanupOptimisticLockingNullsPt2Fixed, :migration do
test_tables = %w(ci_stages ci_builds ci_pipelines).freeze
test_tables.each do |table|
let(table.to_sym) { table(table.to_sym) }
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index 63f3e467143..291cccd72db 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -95,6 +95,29 @@ describe Issue do
end
end
+ describe 'locking' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:lock_version) do
+ [
+ [0],
+ ["0"]
+ ]
+ end
+
+ with_them do
+ it 'works when an issue has a NULL lock_version' do
+ issue = create(:issue)
+
+ described_class.where(id: issue.id).update_all('lock_version = NULL')
+
+ issue.update!(lock_version: lock_version, title: 'locking test')
+
+ expect(issue.reload.title).to eq('locking test')
+ end
+ end
+ end
+
describe '.simple_sorts' do
it 'includes all keys' do
expect(described_class.simple_sorts.keys).to include(
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index dc2d760dbeb..c70ddac5da6 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -55,6 +55,29 @@ describe MergeRequest do
end
end
+ describe 'locking' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:lock_version) do
+ [
+ [0],
+ ["0"]
+ ]
+ end
+
+ with_them do
+ it 'works when a merge request has a NULL lock_version' do
+ merge_request = create(:merge_request)
+
+ described_class.where(id: merge_request.id).update_all('lock_version = NULL')
+
+ merge_request.update!(lock_version: lock_version, title: 'locking test')
+
+ expect(merge_request.reload.title).to eq('locking test')
+ end
+ end
+ end
+
describe '#squash_in_progress?' do
let(:repo_path) do
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
diff --git a/spec/support/helpers/metrics_dashboard_helpers.rb b/spec/support/helpers/metrics_dashboard_helpers.rb
index b8a641d5911..6dbb0cd651f 100644
--- a/spec/support/helpers/metrics_dashboard_helpers.rb
+++ b/spec/support/helpers/metrics_dashboard_helpers.rb
@@ -18,6 +18,10 @@ module MetricsDashboardHelpers
project.repository.refresh_method_caches([:metrics_dashboard])
end
+ def load_sample_dashboard
+ YAML.safe_load(fixture_file('lib/gitlab/metrics/dashboard/sample_dashboard.yml'))
+ end
+
def system_dashboard_path
Metrics::Dashboard::SystemDashboardService::DASHBOARD_PATH
end
diff --git a/spec/support/shared_examples/models/concerns/bulk_insert_safe_shared_examples.rb b/spec/support/shared_examples/models/concerns/bulk_insert_safe_shared_examples.rb
index 7bcd6191f1d..3db5d7a8d7d 100644
--- a/spec/support/shared_examples/models/concerns/bulk_insert_safe_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/bulk_insert_safe_shared_examples.rb
@@ -7,17 +7,17 @@ RSpec.shared_examples 'a BulkInsertSafe model' do |klass|
let(:target_class) { klass.dup }
# We consider all callbacks unsafe for bulk insertions unless we have explicitly
- # whitelisted them (esp. anything related to :save, :create, :commit etc.)
- let(:callback_method_blacklist) do
+ # allowed them (especially anything related to :save, :create, :commit, etc.)
+ let(:unsafe_callbacks) do
ActiveRecord::Callbacks::CALLBACKS.reject do |callback|
cb_name = callback.to_s.gsub(/(before_|after_|around_)/, '').to_sym
- BulkInsertSafe::CALLBACK_NAME_WHITELIST.include?(cb_name)
+ BulkInsertSafe::ALLOWED_CALLBACKS.include?(cb_name)
end.to_set
end
context 'when calling class methods directly' do
it 'raises an error when method is not bulk-insert safe' do
- callback_method_blacklist.each do |m|
+ unsafe_callbacks.each do |m|
expect { target_class.send(m, nil) }.to(
raise_error(BulkInsertSafe::MethodNotAllowedError),
"Expected call to #{m} to raise an error, but it didn't"
@@ -26,7 +26,7 @@ RSpec.shared_examples 'a BulkInsertSafe model' do |klass|
end
it 'does not raise an error when method is bulk-insert safe' do
- BulkInsertSafe::CALLBACK_NAME_WHITELIST.each do |name|
+ BulkInsertSafe::ALLOWED_CALLBACKS.each do |name|
expect { target_class.set_callback(name) {} }.not_to raise_error
end
end