diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-06-23 06:07:43 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-06-23 06:07:43 +0300 |
commit | 0fb62bd3e1df8e54a58382f177edc15926b6b861 (patch) | |
tree | 30d7cdd49a08aa4ff54bf615072746e36a7ab2ad | |
parent | ec8587780b41c8a895f2b26d60c86bf93be5e038 (diff) |
Add latest changes from gitlab-org/gitlab@master
38 files changed, 308 insertions, 231 deletions
diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js index 3080a6b282a..3a65a9d1d51 100644 --- a/app/assets/javascripts/lib/utils/common_utils.js +++ b/app/assets/javascripts/lib/utils/common_utils.js @@ -720,7 +720,18 @@ export const searchBy = (query = '', searchSpace = {}) => { * @param {Object} label * @returns Boolean */ -export const isScopedLabel = ({ title = '' }) => title.indexOf('::') !== -1; +export const isScopedLabel = ({ title = '' } = {}) => title.indexOf('::') !== -1; + +/** + * Returns the base value of the scoped label + * + * Expected Label to be an Object with `title` as a key: + * { title: 'LabelTitle', ...otherProperties }; + * + * @param {Object} label + * @returns String + */ +export const scopedLabelKey = ({ title = '' }) => isScopedLabel({ title }) && title.split('::')[0]; // Methods to set and get Cookie export const setCookie = (name, value) => Cookies.set(name, value, { expires: 365 }); diff --git a/app/assets/javascripts/members/components/app.vue b/app/assets/javascripts/members/components/app.vue index a08518584f3..0ec39f58930 100644 --- a/app/assets/javascripts/members/components/app.vue +++ b/app/assets/javascripts/members/components/app.vue @@ -19,6 +19,11 @@ export default { type: String, required: true, }, + tabQueryParamValue: { + type: String, + required: false, + default: '', + }, }, computed: { ...mapState({ @@ -55,6 +60,6 @@ export default { errorMessage }}</gl-alert> <filter-sort-container /> - <members-table /> + <members-table :tab-query-param-value="tabQueryParamValue" /> </div> </template> diff --git a/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue b/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue index f20cd463cbd..4af41dadc0d 100644 --- a/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue +++ b/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue @@ -5,7 +5,11 @@ import { getParameterByName } from '~/lib/utils/common_utils'; // eslint-disable-next-line import/no-deprecated import { setUrlParams, urlParamsToObject } from '~/lib/utils/url_utility'; import { s__ } from '~/locale'; -import { SEARCH_TOKEN_TYPE, SORT_PARAM } from '~/members/constants'; +import { + SEARCH_TOKEN_TYPE, + SORT_QUERY_PARAM_NAME, + ACTIVE_TAB_QUERY_PARAM_NAME, +} from '~/members/constants'; import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants'; import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue'; @@ -118,10 +122,15 @@ export default { return accumulator; }, {}); - const sortParam = getParameterByName(SORT_PARAM); + const sortParamValue = getParameterByName(SORT_QUERY_PARAM_NAME); + const activeTabParamValue = getParameterByName(ACTIVE_TAB_QUERY_PARAM_NAME); window.location.href = setUrlParams( - { ...params, ...(sortParam && { sort: sortParam }) }, + { + ...params, + ...(sortParamValue && { [SORT_QUERY_PARAM_NAME]: sortParamValue }), + ...(activeTabParamValue && { [ACTIVE_TAB_QUERY_PARAM_NAME]: activeTabParamValue }), + }, window.location.href, true, ); diff --git a/app/assets/javascripts/members/components/members_tabs.vue b/app/assets/javascripts/members/components/members_tabs.vue index 84843aac936..a4bd8ffd708 100644 --- a/app/assets/javascripts/members/components/members_tabs.vue +++ b/app/assets/javascripts/members/components/members_tabs.vue @@ -4,14 +4,15 @@ import { mapState } from 'vuex'; // eslint-disable-next-line import/no-deprecated import { urlParamsToObject } from '~/lib/utils/url_utility'; import { __ } from '~/locale'; -import { MEMBER_TYPES } from '../constants'; +import { MEMBER_TYPES, TAB_QUERY_PARAM_VALUES, ACTIVE_TAB_QUERY_PARAM_NAME } from '../constants'; import MembersApp from './app.vue'; const countComputed = (state, namespace) => state[namespace]?.pagination?.totalItems || 0; export default { name: 'MembersTabs', - tabs: [ + ACTIVE_TAB_QUERY_PARAM_NAME, + TABS: [ { namespace: MEMBER_TYPES.user, title: __('Members'), @@ -20,19 +21,21 @@ export default { namespace: MEMBER_TYPES.group, title: __('Groups'), attrs: { 'data-qa-selector': 'groups_list_tab' }, + queryParamValue: TAB_QUERY_PARAM_VALUES.group, }, { namespace: MEMBER_TYPES.invite, title: __('Invited'), canManageMembersPermissionsRequired: true, + queryParamValue: TAB_QUERY_PARAM_VALUES.invite, }, { namespace: MEMBER_TYPES.accessRequest, title: __('Access requests'), canManageMembersPermissionsRequired: true, + queryParamValue: TAB_QUERY_PARAM_VALUES.accessRequest, }, ], - urlParams: [], components: { MembersApp, GlTabs, GlTab, GlBadge }, inject: ['canManageMembers'], data() { @@ -60,29 +63,18 @@ export default { return Object.keys(urlParamsToObject(window.location.search)); }, activeTabIndexCalculatedFromUrlParams() { - return this.$options.tabs.findIndex(({ namespace }) => { + return this.$options.TABS.findIndex(({ namespace }) => { return this.getTabUrlParams(namespace).some((urlParam) => this.urlParams.includes(urlParam), ); }); }, }, - created() { - if (this.activeTabIndexCalculatedFromUrlParams === -1) { - return; - } - - this.selectedTabIndex = this.activeTabIndexCalculatedFromUrlParams; - }, methods: { getTabUrlParams(namespace) { const state = this.$store.state[namespace]; const urlParams = []; - if (state?.pagination?.paramName) { - urlParams.push(state.pagination.paramName); - } - if (state?.filteredSearchBar?.searchParam) { urlParams.push(state.filteredSearchBar.searchParam); } @@ -112,14 +104,23 @@ export default { </script> <template> - <gl-tabs v-model="selectedTabIndex"> - <template v-for="(tab, index) in $options.tabs"> - <gl-tab v-if="showTab(tab, index)" :key="tab.namespace" :title-link-attributes="tab.attrs"> + <gl-tabs + v-model="selectedTabIndex" + sync-active-tab-with-query-params + :query-param-name="$options.ACTIVE_TAB_QUERY_PARAM_NAME" + > + <template v-for="(tab, index) in $options.TABS"> + <gl-tab + v-if="showTab(tab, index)" + :key="tab.namespace" + :title-link-attributes="tab.attrs" + :query-param-value="tab.queryParamValue" + > <template slot="title"> <span>{{ tab.title }}</span> <gl-badge size="sm" class="gl-tab-counter-badge">{{ getTabCount(tab) }}</gl-badge> </template> - <members-app :namespace="tab.namespace" /> + <members-app :namespace="tab.namespace" :tab-query-param-value="tab.queryParamValue" /> </gl-tab> </template> </gl-tabs> diff --git a/app/assets/javascripts/members/components/table/members_table.vue b/app/assets/javascripts/members/components/table/members_table.vue index 09ef98ec411..b9c80edbc49 100644 --- a/app/assets/javascripts/members/components/table/members_table.vue +++ b/app/assets/javascripts/members/components/table/members_table.vue @@ -5,7 +5,7 @@ import MembersTableCell from 'ee_else_ce/members/components/table/members_table_ import { canOverride, canRemove, canResend, canUpdate } from 'ee_else_ce/members/utils'; import { mergeUrlParams } from '~/lib/utils/url_utility'; import initUserPopovers from '~/user_popovers'; -import { FIELDS } from '../../constants'; +import { FIELDS, ACTIVE_TAB_QUERY_PARAM_NAME } from '../../constants'; import RemoveGroupLinkModal from '../modals/remove_group_link_modal.vue'; import CreatedAt from './created_at.vue'; import ExpirationDatepicker from './expiration_datepicker.vue'; @@ -34,6 +34,13 @@ export default { import('ee_component/members/components/ldap/ldap_override_confirmation_modal.vue'), }, inject: ['namespace', 'currentUserId'], + props: { + tabQueryParamValue: { + type: String, + required: false, + default: '', + }, + }, computed: { ...mapState({ members(state) { @@ -112,7 +119,15 @@ export default { paginationLinkGenerator(page) { const { params = {}, paramName } = this.pagination; - return mergeUrlParams({ ...params, [paramName]: page }, window.location.href); + return mergeUrlParams( + { + ...params, + [ACTIVE_TAB_QUERY_PARAM_NAME]: + this.tabQueryParamValue !== '' ? this.tabQueryParamValue : null, + [paramName]: page, + }, + window.location.href, + ); }, }, }; diff --git a/app/assets/javascripts/members/constants.js b/app/assets/javascripts/members/constants.js index f68a8814fee..6f465245d20 100644 --- a/app/assets/javascripts/members/constants.js +++ b/app/assets/javascripts/members/constants.js @@ -89,6 +89,12 @@ export const MEMBER_TYPES = { accessRequest: 'accessRequest', }; +export const TAB_QUERY_PARAM_VALUES = { + group: 'groups', + invite: 'invited', + accessRequest: 'access_requests', +}; + export const DAYS_TO_EXPIRE_SOON = 7; export const LEAVE_MODAL_ID = 'member-leave-modal'; @@ -97,7 +103,8 @@ export const REMOVE_GROUP_LINK_MODAL_ID = 'remove-group-link-modal-id'; export const SEARCH_TOKEN_TYPE = 'filtered-search-term'; -export const SORT_PARAM = 'sort'; +export const SORT_QUERY_PARAM_NAME = 'sort'; +export const ACTIVE_TAB_QUERY_PARAM_NAME = 'tab'; export const MEMBER_ACCESS_LEVEL_PROPERTY_NAME = 'access_level'; diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js index 55716e1105e..2e0a57f15dd 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js @@ -1,3 +1,4 @@ +import { isScopedLabel, scopedLabelKey } from '~/lib/utils/common_utils'; import { DropdownVariant } from '../constants'; import * as types from './mutation_types'; @@ -66,5 +67,16 @@ export default { candidateLabel.touched = true; candidateLabel.set = !candidateLabel.set; } + + if (isScopedLabel(candidateLabel)) { + const scopedBase = scopedLabelKey(candidateLabel); + const currentActiveScopedLabel = state.labels.find(({ title }) => { + return title.startsWith(scopedBase) && title !== '' && title !== candidateLabel.title; + }); + + if (currentActiveScopedLabel) { + currentActiveScopedLabel.set = false; + } + } }, }; diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutations.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutations.js index 131c6e6fb57..1c03d95f37b 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutations.js +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutations.js @@ -1,3 +1,4 @@ +import { isScopedLabel, scopedLabelKey } from '~/lib/utils/common_utils'; import { DropdownVariant } from '../constants'; import * as types from './mutation_types'; @@ -55,5 +56,16 @@ export default { candidateLabel.touched = true; candidateLabel.set = !candidateLabel.set; } + + if (isScopedLabel(candidateLabel)) { + const scopedBase = scopedLabelKey(candidateLabel); + const currentActiveScopedLabel = state.labels.find( + ({ title }) => title.indexOf(scopedBase) === 0 && title !== candidateLabel.title, + ); + + if (currentActiveScopedLabel) { + currentActiveScopedLabel.set = false; + } + } }, }; diff --git a/config/feature_flags/development/ci_workflow_rules_variables.yml b/config/feature_flags/development/ci_workflow_rules_variables.yml deleted file mode 100644 index 427a07c51f6..00000000000 --- a/config/feature_flags/development/ci_workflow_rules_variables.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: ci_workflow_rules_variables -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52085 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/300997 -milestone: '13.11' -type: development -group: group::pipeline authoring -default_enabled: true diff --git a/config/initializers/7_redis.rb b/config/initializers/7_redis.rb index fe37dfd7579..84aa231089b 100644 --- a/config/initializers/7_redis.rb +++ b/config/initializers/7_redis.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +Redis::Client.prepend(Gitlab::Instrumentation::RedisInterceptor) + # Make sure we initialize a Redis connection pool before multi-threaded # execution starts by # 1. Sidekiq diff --git a/db/migrate/20210614142311_add_running_container_scanning_max_size_to_plan_limits.rb b/db/migrate/20210614142311_add_running_container_scanning_max_size_to_plan_limits.rb new file mode 100644 index 00000000000..248fff6c42f --- /dev/null +++ b/db/migrate/20210614142311_add_running_container_scanning_max_size_to_plan_limits.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class AddRunningContainerScanningMaxSizeToPlanLimits < ActiveRecord::Migration[6.0] + def change + add_column :plan_limits, :ci_max_artifact_size_running_container_scanning, :integer, null: false, default: 0 + end +end diff --git a/db/schema_migrations/20210614142311 b/db/schema_migrations/20210614142311 new file mode 100644 index 00000000000..69a2472990a --- /dev/null +++ b/db/schema_migrations/20210614142311 @@ -0,0 +1 @@ +5dc0a4f91dc35b7720b20e89fa77374a0337c380b9234704e7d4143639e512f0
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 032f1230f36..6d25d1c42df 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -16299,7 +16299,8 @@ CREATE TABLE plan_limits ( ci_registered_group_runners integer DEFAULT 1000 NOT NULL, ci_registered_project_runners integer DEFAULT 1000 NOT NULL, web_hook_calls integer DEFAULT 0 NOT NULL, - ci_daily_pipeline_schedule_triggers integer DEFAULT 0 NOT NULL + ci_daily_pipeline_schedule_triggers integer DEFAULT 0 NOT NULL, + ci_max_artifact_size_running_container_scanning integer DEFAULT 0 NOT NULL ); CREATE SEQUENCE plan_limits_id_seq diff --git a/doc/administration/instance_limits.md b/doc/administration/instance_limits.md index 9423045e3b5..bb49ebd873d 100644 --- a/doc/administration/instance_limits.md +++ b/doc/administration/instance_limits.md @@ -169,7 +169,7 @@ Read more about [Gitaly concurrency limits](gitaly/configure_gitaly.md#limit-rpc There's a limit to the number of comments that can be submitted on an issue, merge request, or commit. When the limit is reached, system notes can still be -added so that the history of events is not lost, but the user-submitted +added so that the history of events is not lost, but the user-submitted comment fails. - **Max limit**: 5,000 comments. @@ -443,33 +443,34 @@ setting is used: | Artifact limit name | Default value | |---------------------------------------------|---------------| -| `ci_max_artifact_size_accessibility` | 0 | -| `ci_max_artifact_size_api_fuzzing` | 0 | -| `ci_max_artifact_size_archive` | 0 | -| `ci_max_artifact_size_browser_performance` | 0 | -| `ci_max_artifact_size_cluster_applications` | 0 | -| `ci_max_artifact_size_cobertura` | 0 | -| `ci_max_artifact_size_codequality` | 0 | -| `ci_max_artifact_size_container_scanning` | 0 | -| `ci_max_artifact_size_coverage_fuzzing` | 0 | -| `ci_max_artifact_size_dast` | 0 | -| `ci_max_artifact_size_dependency_scanning` | 0 | -| `ci_max_artifact_size_dotenv` | 0 | -| `ci_max_artifact_size_junit` | 0 | -| `ci_max_artifact_size_license_management` | 0 | -| `ci_max_artifact_size_license_scanning` | 0 | -| `ci_max_artifact_size_load_performance` | 0 | -| `ci_max_artifact_size_lsif` | 100 MB ([Introduced at 20 MB](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37226) in GitLab 13.3 and [raised to 100 MB](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46980) in GitLab 13.6.) | -| `ci_max_artifact_size_metadata` | 0 | -| `ci_max_artifact_size_metrics_referee` | 0 | -| `ci_max_artifact_size_metrics` | 0 | -| `ci_max_artifact_size_network_referee` | 0 | -| `ci_max_artifact_size_performance` | 0 | -| `ci_max_artifact_size_requirements` | 0 | -| `ci_max_artifact_size_sast` | 0 | -| `ci_max_artifact_size_secret_detection` | 0 | -| `ci_max_artifact_size_terraform` | 5 MB ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37018) in GitLab 13.3) | -| `ci_max_artifact_size_trace` | 0 | +| `ci_max_artifact_size_accessibility` | 0 | +| `ci_max_artifact_size_api_fuzzing` | 0 | +| `ci_max_artifact_size_archive` | 0 | +| `ci_max_artifact_size_browser_performance` | 0 | +| `ci_max_artifact_size_cluster_applications` | 0 | +| `ci_max_artifact_size_cobertura` | 0 | +| `ci_max_artifact_size_codequality` | 0 | +| `ci_max_artifact_size_container_scanning` | 0 | +| `ci_max_artifact_size_coverage_fuzzing` | 0 | +| `ci_max_artifact_size_dast` | 0 | +| `ci_max_artifact_size_dependency_scanning` | 0 | +| `ci_max_artifact_size_dotenv` | 0 | +| `ci_max_artifact_size_junit` | 0 | +| `ci_max_artifact_size_license_management` | 0 | +| `ci_max_artifact_size_license_scanning` | 0 | +| `ci_max_artifact_size_load_performance` | 0 | +| `ci_max_artifact_size_lsif` | 100 MB ([Introduced at 20 MB](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37226) in GitLab 13.3 and [raised to 100 MB](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46980) in GitLab 13.6.) | +| `ci_max_artifact_size_metadata` | 0 | +| `ci_max_artifact_size_metrics_referee` | 0 | +| `ci_max_artifact_size_metrics` | 0 | +| `ci_max_artifact_size_network_referee` | 0 | +| `ci_max_artifact_size_performance` | 0 | +| `ci_max_artifact_size_requirements` | 0 | +| `ci_max_artifact_size_running_container_scanning` | 0 | +| `ci_max_artifact_size_sast` | 0 | +| `ci_max_artifact_size_secret_detection` | 0 | +| `ci_max_artifact_size_terraform` | 5 MB ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37018) in GitLab 13.3) | +| `ci_max_artifact_size_trace` | 0 | For example, to set the `ci_max_artifact_size_junit` limit to 10 MB on a self-managed installation, run the following in the [GitLab Rails console](operations/rails_console.md#starting-a-rails-console-session): @@ -607,7 +608,7 @@ Reports that go over the 20 MB limit won't be loaded. Affected reports: > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8638) in GitLab 13.3. You can set a limit on the content of repository files that are indexed in -Elasticsearch. Any files larger than this limit is neither indexed +Elasticsearch. Any files larger than this limit is neither indexed nor searchable. Setting a limit helps reduce the memory usage of the indexing processes and diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md index 017719657ef..3829f0d8856 100644 --- a/doc/administration/monitoring/prometheus/gitlab_metrics.md +++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md @@ -98,6 +98,8 @@ The following metrics are available: | `gitlab_transaction_db_write_count_total` | Counter | 13.1 | Counter for total number of write SQL calls | `controller`, `action` | | `gitlab_transaction_db_cached_count_total` | Counter | 13.1 | Counter for total number of cached SQL calls | `controller`, `action` | | `gitlab_transaction_db_<role>_cached_count_total` | Counter | 13.1 | Counter for total number of cached SQL calls, grouped by database roles (primary/replica) | `controller`, `action` | +| `gitlab_transaction_db_<role>_wal_count_total` | Counter | 14.0 | Counter for total number of WAL (write ahead log location) queries, grouped by database roles (primary/replica) | `controller`, `action` | +| `gitlab_transaction_db_<role>_wal_cached_count_total` | Counter | 14.1 | Counter for total number of cached WAL (write ahead log location) queries, grouped by database roles (primary/replica)| `controller`, `action` | | `http_elasticsearch_requests_duration_seconds` **(PREMIUM)** | Histogram | 13.1 | Elasticsearch requests duration during web transactions | `controller`, `action` | | `http_elasticsearch_requests_total` **(PREMIUM)** | Counter | 13.1 | Elasticsearch requests count during web transactions | `controller`, `action` | | `pipelines_created_total` | Counter | 9.4 | Counter of pipelines created | | diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md index 2aa4bd6e05c..f8e720123f8 100644 --- a/doc/ci/yaml/README.md +++ b/doc/ci/yaml/README.md @@ -233,15 +233,7 @@ If your rules match both branch pipelines and merge request pipelines, #### `workflow:rules:variables` > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/294232) in GitLab 13.11. -> - [Deployed behind a feature flag](../../user/feature_flags.md), disabled by default. -> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/300997) in GitLab 13.12. -> - Enabled on GitLab.com. -> - Recommended for production use. -> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-workflowrulesvariables). **(FREE SELF)** - -There can be -[risks when disabling released features](../../user/feature_flags.md#risks-when-disabling-released-features). -Refer to this feature's version history for more details. +> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/300997) in GitLab 14.1. You can use [`variables`](#variables) in `workflow:rules:` to define variables for specific pipeline conditions. @@ -294,25 +286,6 @@ When the branch is something else: - job1's `DEPLOY_VARIABLE` is `job1-default-deploy`. - job2's `DEPLOY_VARIABLE` is `default-deploy`. -##### Enable or disable workflow:rules:variables **(FREE SELF)** - -workflow:rules:variables is under development but ready for production use. -It is deployed behind a feature flag that is **enabled by default**. -[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md) -can opt to disable it. - -To enable it: - -```ruby -Feature.enable(:ci_workflow_rules_variables) -``` - -To disable it: - -```ruby -Feature.disable(:ci_workflow_rules_variables) -``` - #### `workflow:rules` templates > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217732) in GitLab 13.0. diff --git a/doc/development/avoiding_downtime_in_migrations.md b/doc/development/avoiding_downtime_in_migrations.md index 6b6c47cfece..646b07f7266 100644 --- a/doc/development/avoiding_downtime_in_migrations.md +++ b/doc/development/avoiding_downtime_in_migrations.md @@ -95,8 +95,6 @@ renaming. For example class RenameUsersUpdatedAtToUpdatedAtTimestamp < ActiveRecord::Migration[4.2] include Gitlab::Database::MigrationHelpers - DOWNTIME = false - disable_ddl_transaction! def up @@ -291,8 +289,6 @@ any remaining rows. For example: class MigrateRemainingIssuesClosedAt < ActiveRecord::Migration[4.2] include Gitlab::Database::MigrationHelpers - DOWNTIME = false - disable_ddl_transaction! class Issue < ActiveRecord::Base diff --git a/doc/user/analytics/value_stream_analytics.md b/doc/user/analytics/value_stream_analytics.md index c3b3fcba52e..98948243724 100644 --- a/doc/user/analytics/value_stream_analytics.md +++ b/doc/user/analytics/value_stream_analytics.md @@ -58,9 +58,9 @@ The **Time** metrics near the top of the page are measured as follows: ## How the stages are measured -Value Stream Analytics uses start events and stop events to measure the time that an issue or merge request spends in each stage. +Value Stream Analytics uses start events and end events to measure the time that an issue or merge request spends in each stage. For example, a stage might start when one label is added to an issue and end when another label is added. -Items aren't included in the stage time calculation if they have not reached the stop event. +Items aren't included in the stage time calculation if they have not reached the end event. | Stage | Description | |---------|---------------| diff --git a/doc/user/group/value_stream_analytics/index.md b/doc/user/group/value_stream_analytics/index.md index c1dd363c313..542ea81c04d 100644 --- a/doc/user/group/value_stream_analytics/index.md +++ b/doc/user/group/value_stream_analytics/index.md @@ -96,9 +96,9 @@ You can learn more about these metrics in our [analytics definitions](../../anal ## How the stages are measured -Value Stream Analytics measures each stage from its start event to its stop event. +Value Stream Analytics measures each stage from its start event to its end event. For example, a stage might start when one label is added to an issue, and end when another label is added. -Value Stream Analytics excludes work in progress, meaning it ignores any items that have not reached the stop event. +Value Stream Analytics excludes work in progress, meaning it ignores any items that have not reached the end event. Each stage of Value Stream Analytics is further described in the table below. diff --git a/lib/gitlab/ci/pipeline/chain/seed.rb b/lib/gitlab/ci/pipeline/chain/seed.rb index 66fc6741252..ef7447fa83d 100644 --- a/lib/gitlab/ci/pipeline/chain/seed.rb +++ b/lib/gitlab/ci/pipeline/chain/seed.rb @@ -10,10 +10,7 @@ module Gitlab def perform! raise ArgumentError, 'missing YAML processor result' unless @command.yaml_processor_result - - if ::Feature.enabled?(:ci_workflow_rules_variables, pipeline.project, default_enabled: :yaml) - raise ArgumentError, 'missing workflow rules result' unless @command.workflow_rules_result - end + raise ArgumentError, 'missing workflow rules result' unless @command.workflow_rules_result # Allocate next IID. This operation must be outside of transactions of pipeline creations. pipeline.ensure_project_iid! @@ -51,13 +48,9 @@ module Gitlab end def root_variables - if ::Feature.enabled?(:ci_workflow_rules_variables, pipeline.project, default_enabled: :yaml) - ::Gitlab::Ci::Variables::Helpers.merge_variables( - @command.yaml_processor_result.root_variables, @command.workflow_rules_result.variables - ) - else - @command.yaml_processor_result.root_variables - end + ::Gitlab::Ci::Variables::Helpers.merge_variables( + @command.yaml_processor_result.root_variables, @command.workflow_rules_result.variables + ) end end end diff --git a/lib/gitlab/ci/pipeline/seed/build.rb b/lib/gitlab/ci/pipeline/seed/build.rb index 299b27a5f13..c880b42968b 100644 --- a/lib/gitlab/ci/pipeline/seed/build.rb +++ b/lib/gitlab/ci/pipeline/seed/build.rb @@ -213,8 +213,6 @@ module Gitlab end def recalculate_yaml_variables! - return unless ::Feature.enabled?(:ci_workflow_rules_variables, @pipeline.project, default_enabled: :yaml) - @seed_attributes[:yaml_variables] = Gitlab::Ci::Variables::Helpers.inherit_yaml_variables( from: @context.root_variables, to: @job_variables, inheritance: @root_variables_inheritance ) diff --git a/lib/gitlab/instrumentation/redis_interceptor.rb b/lib/gitlab/instrumentation/redis_interceptor.rb index b5a5f8fd984..fa5dd8ce9af 100644 --- a/lib/gitlab/instrumentation/redis_interceptor.rb +++ b/lib/gitlab/instrumentation/redis_interceptor.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require 'redis' - module Gitlab module Instrumentation module RedisInterceptor @@ -99,7 +97,3 @@ module Gitlab end end end - -class ::Redis::Client - prepend ::Gitlab::Instrumentation::RedisInterceptor -end diff --git a/lib/gitlab/metrics/subscribers/active_record.rb b/lib/gitlab/metrics/subscribers/active_record.rb index 07480bcddee..a8fcad9ff9f 100644 --- a/lib/gitlab/metrics/subscribers/active_record.rb +++ b/lib/gitlab/metrics/subscribers/active_record.rb @@ -15,8 +15,8 @@ module Gitlab TRANSACTION_DURATION_BUCKET = [0.1, 0.25, 1].freeze DB_LOAD_BALANCING_COUNTERS = %i{ - db_replica_count db_replica_cached_count db_replica_wal_count - db_primary_count db_primary_cached_count db_primary_wal_count + db_replica_count db_replica_cached_count db_replica_wal_count db_replica_wal_cached_count + db_primary_count db_primary_cached_count db_primary_wal_count db_primary_wal_cached_count }.freeze DB_LOAD_BALANCING_DURATIONS = %i{db_primary_duration_s db_replica_duration_s}.freeze @@ -91,9 +91,14 @@ module Gitlab end def increment_db_role_counters(db_role, payload) + cached = cached_query?(payload) increment("db_#{db_role}_count".to_sym) - increment("db_#{db_role}_cached_count".to_sym) if cached_query?(payload) - increment("db_#{db_role}_wal_count".to_sym) if !cached_query?(payload) && wal_command?(payload) + increment("db_#{db_role}_cached_count".to_sym) if cached + + if wal_command?(payload) + increment("db_#{db_role}_wal_count".to_sym) + increment("db_#{db_role}_wal_cached_count".to_sym) if cached + end end def observe_db_role_duration(db_role, event) diff --git a/spec/frontend/members/components/app_spec.js b/spec/frontend/members/components/app_spec.js index b9fdf8792fd..9590cd9d8d4 100644 --- a/spec/frontend/members/components/app_spec.js +++ b/spec/frontend/members/components/app_spec.js @@ -5,7 +5,8 @@ import Vuex from 'vuex'; import * as commonUtils from '~/lib/utils/common_utils'; import MembersApp from '~/members/components/app.vue'; import FilterSortContainer from '~/members/components/filter_sort/filter_sort_container.vue'; -import { MEMBER_TYPES } from '~/members/constants'; +import MembersTable from '~/members/components/table/members_table.vue'; +import { MEMBER_TYPES, TAB_QUERY_PARAM_VALUES } from '~/members/constants'; import { RECEIVE_MEMBER_ROLE_ERROR, HIDE_ERROR } from '~/members/store/mutation_types'; import mutations from '~/members/store/mutations'; @@ -19,7 +20,7 @@ describe('MembersApp', () => { const createComponent = (state = {}, options = {}) => { store = new Vuex.Store({ modules: { - [MEMBER_TYPES.user]: { + [MEMBER_TYPES.group]: { namespaced: true, state: { showError: true, @@ -34,7 +35,8 @@ describe('MembersApp', () => { wrapper = shallowMount(MembersApp, { localVue, propsData: { - namespace: MEMBER_TYPES.user, + namespace: MEMBER_TYPES.group, + tabQueryParamValue: TAB_QUERY_PARAM_VALUES.group, }, store, ...options, @@ -57,7 +59,7 @@ describe('MembersApp', () => { it('renders and scrolls to error alert', async () => { createComponent({ showError: false, errorMessage: '' }); - store.commit(`${MEMBER_TYPES.user}/${RECEIVE_MEMBER_ROLE_ERROR}`, { + store.commit(`${MEMBER_TYPES.group}/${RECEIVE_MEMBER_ROLE_ERROR}`, { error: new Error('Network Error'), }); @@ -77,7 +79,7 @@ describe('MembersApp', () => { it('does not render and scroll to error alert', async () => { createComponent(); - store.commit(`${MEMBER_TYPES.user}/${HIDE_ERROR}`); + store.commit(`${MEMBER_TYPES.group}/${HIDE_ERROR}`); await nextTick(); @@ -103,4 +105,13 @@ describe('MembersApp', () => { expect(findFilterSortContainer().exists()).toBe(true); }); + + it('renders `MembersTable` component and passes `tabQueryParamValue` prop', () => { + createComponent(); + + const membersTableComponent = wrapper.findComponent(MembersTable); + + expect(membersTableComponent.exists()).toBe(true); + expect(membersTableComponent.props('tabQueryParamValue')).toBe(TAB_QUERY_PARAM_VALUES.group); + }); }); diff --git a/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js b/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js index 5e04e20801a..a3b91cb20bb 100644 --- a/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js +++ b/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js @@ -216,5 +216,17 @@ describe('MembersFilteredSearchBar', () => { 'https://localhost/?two_factor=enabled&search=foobar&sort=name_asc', ); }); + + it('adds active tab query param', () => { + window.location.search = '?tab=invited'; + + createComponent(); + + findFilteredSearchBar().vm.$emit('onFilter', [ + { type: 'filtered-search-term', value: { data: 'foobar' } }, + ]); + + expect(window.location.href).toBe('https://localhost/?search=foobar&tab=invited'); + }); }); }); diff --git a/spec/frontend/members/components/members_tabs_spec.js b/spec/frontend/members/components/members_tabs_spec.js index 6f1a6d0c223..33d8eebf7eb 100644 --- a/spec/frontend/members/components/members_tabs_spec.js +++ b/spec/frontend/members/components/members_tabs_spec.js @@ -1,9 +1,14 @@ +import { GlTabs } from '@gitlab/ui'; import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import { mountExtended } from 'helpers/vue_test_utils_helper'; import MembersApp from '~/members/components/app.vue'; import MembersTabs from '~/members/components/members_tabs.vue'; -import { MEMBER_TYPES } from '~/members/constants'; +import { + MEMBER_TYPES, + TAB_QUERY_PARAM_VALUES, + ACTIVE_TAB_QUERY_PARAM_NAME, +} from '~/members/constants'; import { pagination } from '../mock_data'; describe('MembersTabs', () => { @@ -93,6 +98,18 @@ describe('MembersTabs', () => { wrapper.destroy(); }); + it('renders `GlTabs` with `syncActiveTabWithQueryParams` and `queryParamName` props set', async () => { + await createComponent(); + + const glTabsComponent = wrapper.findComponent(GlTabs); + + expect(glTabsComponent.exists()).toBe(true); + expect(glTabsComponent.props()).toMatchObject({ + syncActiveTabWithQueryParams: true, + queryParamName: ACTIVE_TAB_QUERY_PARAM_NAME, + }); + }); + describe('when tabs have a count', () => { it('renders tabs with count', async () => { await createComponent(); @@ -106,7 +123,7 @@ describe('MembersTabs', () => { expect(findActiveTab().text()).toContain('Members'); }); - it('renders `MembersApp` and passes `namespace` prop', async () => { + it('renders `MembersApp` and passes `namespace` and `tabQueryParamValue` props', async () => { await createComponent(); const membersApps = wrapper.findAllComponents(MembersApp).wrappers; @@ -115,6 +132,10 @@ describe('MembersTabs', () => { expect(membersApps[1].props('namespace')).toBe(MEMBER_TYPES.group); expect(membersApps[2].props('namespace')).toBe(MEMBER_TYPES.invite); expect(membersApps[3].props('namespace')).toBe(MEMBER_TYPES.accessRequest); + + expect(membersApps[1].props('tabQueryParamValue')).toBe(TAB_QUERY_PARAM_VALUES.group); + expect(membersApps[2].props('tabQueryParamValue')).toBe(TAB_QUERY_PARAM_VALUES.invite); + expect(membersApps[3].props('tabQueryParamValue')).toBe(TAB_QUERY_PARAM_VALUES.accessRequest); }); }); @@ -127,56 +148,16 @@ describe('MembersTabs', () => { expect(findTabByText('Invited')).toBeUndefined(); expect(findTabByText('Access requests')).toBeUndefined(); }); - }); - describe('when url param matches `filteredSearchBar.searchParam`', () => { - beforeEach(() => { - window.location.search = '?search_groups=foo+bar'; - }); - - const expectGroupsTabActive = () => { - expect(findActiveTab().text()).toContain('Groups'); - }; - - describe('when tab has a count', () => { - it('sets tab that corresponds to search param as active tab', async () => { - await createComponent(); - - expectGroupsTabActive(); + describe('when url param matches `filteredSearchBar.searchParam`', () => { + beforeEach(() => { + window.location.search = '?search_groups=foo+bar'; }); - }); - - describe('when tab does not have a count', () => { - it('sets tab that corresponds to search param as active tab', async () => { - await createComponent({ totalItems: 0 }); - - expectGroupsTabActive(); - }); - }); - }); - - describe('when url param matches `pagination.paramName`', () => { - beforeEach(() => { - window.location.search = '?invited_page=2'; - }); - - const expectInvitedTabActive = () => { - expect(findActiveTab().text()).toContain('Invited'); - }; - - describe('when tab has a count', () => { - it('sets tab that corresponds to pagination param as active tab', async () => { - await createComponent(); - - expectInvitedTabActive(); - }); - }); - describe('when tab does not have a count', () => { - it('sets tab that corresponds to pagination param as active tab', async () => { + it('shows tab that corresponds to search param', async () => { await createComponent({ totalItems: 0 }); - expectInvitedTabActive(); + expect(findTabByText('Groups')).not.toBeUndefined(); }); }); }); diff --git a/spec/frontend/members/components/table/members_table_spec.js b/spec/frontend/members/components/table/members_table_spec.js index 5308d7651a3..3a17d78bd17 100644 --- a/spec/frontend/members/components/table/members_table_spec.js +++ b/spec/frontend/members/components/table/members_table_spec.js @@ -15,7 +15,7 @@ import MemberAvatar from '~/members/components/table/member_avatar.vue'; import MemberSource from '~/members/components/table/member_source.vue'; import MembersTable from '~/members/components/table/members_table.vue'; import RoleDropdown from '~/members/components/table/role_dropdown.vue'; -import { MEMBER_TYPES } from '~/members/constants'; +import { MEMBER_TYPES, TAB_QUERY_PARAM_VALUES } from '~/members/constants'; import * as initUserPopovers from '~/user_popovers'; import { member as memberMock, @@ -34,7 +34,7 @@ describe('MembersTable', () => { const createStore = (state = {}) => { return new Vuex.Store({ modules: { - [MEMBER_TYPES.user]: { + [MEMBER_TYPES.invite]: { namespaced: true, state: { members: [], @@ -54,11 +54,14 @@ describe('MembersTable', () => { const createComponent = (state, provide = {}) => { wrapper = mount(MembersTable, { localVue, + propsData: { + tabQueryParamValue: TAB_QUERY_PARAM_VALUES.invite, + }, store: createStore(state), provide: { sourceId: 1, currentUserId: 1, - namespace: MEMBER_TYPES.user, + namespace: MEMBER_TYPES.invite, ...provide, }, stubs: [ @@ -74,7 +77,7 @@ describe('MembersTable', () => { }); }; - const url = 'https://localhost/foo-bar/-/project_members'; + const url = 'https://localhost/foo-bar/-/project_members?tab=invited'; const getByText = (text, options) => createWrapper(getByTextHelper(wrapper.element, text, options)); @@ -92,7 +95,7 @@ describe('MembersTable', () => { const expectCorrectLinkToPage2 = () => { expect(findPagination().findByText('2', { selector: 'a' }).attributes('href')).toBe( - `${url}?page=2`, + `${url}&invited_members_page=2`, ); }; @@ -271,7 +274,7 @@ describe('MembersTable', () => { currentPage: 1, perPage: 5, totalItems: 10, - paramName: 'page', + paramName: 'invited_members_page', }, }); @@ -279,14 +282,14 @@ describe('MembersTable', () => { }); it('removes any url params defined as `null` in the `params` attribute', () => { - window.location = new URL(`${url}?search_groups=foo`); + window.location = new URL(`${url}&search_groups=foo`); createComponent({ pagination: { currentPage: 1, perPage: 5, totalItems: 10, - paramName: 'page', + paramName: 'invited_members_page', params: { search_groups: null }, }, }); diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js index ab266ac8aed..1d2a9c34599 100644 --- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js +++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js @@ -153,7 +153,16 @@ describe('LabelsSelect Mutations', () => { }); describe(`${types.UPDATE_SELECTED_LABELS}`, () => { - const labels = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }]; + let labels; + + beforeEach(() => { + labels = [ + { id: 1, title: 'scoped::test', set: true }, + { id: 2, set: false, title: 'scoped::one' }, + { id: 3, title: '' }, + { id: 4, title: '' }, + ]; + }); it('updates `state.labels` to include `touched` and `set` props based on provided `labels` param', () => { const updatedLabelIds = [2]; @@ -169,5 +178,23 @@ describe('LabelsSelect Mutations', () => { } }); }); + + describe('when label is scoped', () => { + it('unsets the currently selected scoped label and sets the current label', () => { + const state = { + labels, + }; + mutations[types.UPDATE_SELECTED_LABELS](state, { + labels: [{ id: 2, title: 'scoped::one' }], + }); + + expect(state.labels).toEqual([ + { id: 1, title: 'scoped::test', set: false }, + { id: 2, set: true, title: 'scoped::one', touched: true }, + { id: 3, title: '' }, + { id: 4, title: '' }, + ]); + }); + }); }); }); diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/store/mutations_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/store/mutations_spec.js index acb275b5d90..9e965cb33e8 100644 --- a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/store/mutations_spec.js +++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/store/mutations_spec.js @@ -120,7 +120,16 @@ describe('LabelsSelect Mutations', () => { }); describe(`${types.UPDATE_SELECTED_LABELS}`, () => { - const labels = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }]; + let labels; + + beforeEach(() => { + labels = [ + { id: 1, title: 'scoped::test', set: true }, + { id: 2, set: false, title: 'scoped::one' }, + { id: 3, title: '' }, + { id: 4, title: '' }, + ]; + }); it('updates `state.labels` to include `touched` and `set` props based on provided `labels` param', () => { const updatedLabelIds = [2]; @@ -136,5 +145,23 @@ describe('LabelsSelect Mutations', () => { } }); }); + + describe('when label is scoped', () => { + it('unsets the currently selected scoped label and sets the current label', () => { + const state = { + labels, + }; + mutations[types.UPDATE_SELECTED_LABELS](state, { + labels: [{ id: 2, title: 'scoped::one' }], + }); + + expect(state.labels).toEqual([ + { id: 1, title: 'scoped::test', set: false }, + { id: 2, set: true, title: 'scoped::one', touched: true }, + { id: 3, title: '' }, + { id: 4, title: '' }, + ]); + }); + }); }); }); diff --git a/spec/initializers/lograge_spec.rb b/spec/initializers/lograge_spec.rb index 651b0c8a9b8..a1fd9be299b 100644 --- a/spec/initializers/lograge_spec.rb +++ b/spec/initializers/lograge_spec.rb @@ -200,6 +200,8 @@ RSpec.describe 'lograge', type: :request do %w[ db_primary_wal_count db_replica_wal_count + db_primary_wal_cached_count + db_replica_wal_cached_count db_replica_count db_replica_cached_count db_primary_count diff --git a/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb index 2e537f40692..687bb82a8ef 100644 --- a/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb @@ -203,18 +203,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do expect(rspec_variables['VAR1']).to eq('overridden var 1') end - - context 'when the FF ci_workflow_rules_variables is disabled' do - before do - stub_feature_flags(ci_workflow_rules_variables: false) - end - - it 'sends root variable' do - run_chain - - expect(rspec_variables['VAR1']).to eq('var 1') - end - end end context 'N+1 queries' do diff --git a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb index 020f957cf70..f6c456e488d 100644 --- a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb @@ -250,19 +250,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do { key: 'VAR4', value: 'new var pipeline 4', public: true }] ) end - - context 'when FF ci_workflow_rules_variables is disabled' do - before do - stub_feature_flags(ci_workflow_rules_variables: false) - end - - it 'returns existing yaml variables' do - expect(subject[:yaml_variables]).to match_array( - [{ key: 'VAR2', value: 'var 2', public: true }, - { key: 'VAR3', value: 'var 3', public: true }] - ) - end - end end context 'when root_variables_inheritance is false' do diff --git a/spec/lib/gitlab/instrumentation_helper_spec.rb b/spec/lib/gitlab/instrumentation_helper_spec.rb index 28ae90d4947..1460af3488d 100644 --- a/spec/lib/gitlab/instrumentation_helper_spec.rb +++ b/spec/lib/gitlab/instrumentation_helper_spec.rb @@ -133,7 +133,9 @@ RSpec.describe Gitlab::InstrumentationHelper do db_primary_count: 0, db_primary_cached_count: 0, db_primary_wal_count: 0, - db_replica_wal_count: 0) + db_replica_wal_count: 0, + db_primary_wal_cached_count: 0, + db_replica_wal_cached_count: 0) end end @@ -150,7 +152,9 @@ RSpec.describe Gitlab::InstrumentationHelper do db_primary_count: 0, db_primary_cached_count: 0, db_primary_wal_count: 0, - db_replica_wal_count: 0) + db_replica_wal_count: 0, + db_primary_wal_cached_count: 0, + db_replica_wal_cached_count: 0) end end end diff --git a/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb b/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb index 915f28ec6e9..6fc8f090431 100644 --- a/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb +++ b/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb @@ -183,6 +183,8 @@ RSpec.describe Gitlab::Metrics::Subscribers::ActiveRecord do 'SQL' | 'UPDATE users SET admin = true WHERE id = 10' | true | true | false | false 'SQL' | 'SELECT pg_current_wal_insert_lsn()::text AS location' | true | false | false | true 'SQL' | 'SELECT pg_last_wal_replay_lsn()::text AS location' | true | false | false | true + 'CACHE' | 'SELECT pg_current_wal_insert_lsn()::text AS location' | true | false | true | true + 'CACHE' | 'SELECT pg_last_wal_replay_lsn()::text AS location' | true | false | true | true 'CACHE' | 'SELECT * FROM users WHERE id = 10' | true | false | true | false 'SCHEMA' | "SELECT attr.attname FROM pg_attribute attr INNER JOIN pg_constraint cons ON attr.attrelid = cons.conrelid AND attr.attnum = any(cons.conkey) WHERE cons.contype = 'p' AND cons.conrelid = '\"projects\"'::regclass" | false | false | false | false nil | 'BEGIN' | false | false | false | false diff --git a/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb b/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb index 22deaca824a..4406b34e638 100644 --- a/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb +++ b/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb @@ -314,7 +314,9 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do 'db_primary_cached_count' => 0, 'db_primary_wal_count' => 0, 'db_primary_duration_s' => a_value > 0, - "db_primary_#{dbname}_duration_s" => a_value > 0 + "db_primary_#{dbname}_duration_s" => a_value > 0, + 'db_primary_wal_cached_count' => 0, + 'db_replica_wal_cached_count' => 0 ) end @@ -336,6 +338,8 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do 'db_primary_count' => 0, 'db_primary_cached_count' => 0, 'db_primary_wal_count' => 0, + 'db_primary_wal_cached_count' => 0, + 'db_replica_wal_cached_count' => 0, 'db_primary_duration_s' => 0 ) end diff --git a/spec/models/plan_limits_spec.rb b/spec/models/plan_limits_spec.rb index cf8e30023eb..07347dfb6ec 100644 --- a/spec/models/plan_limits_spec.rb +++ b/spec/models/plan_limits_spec.rb @@ -184,6 +184,7 @@ RSpec.describe PlanLimits do ci_max_artifact_size_junit ci_max_artifact_size_sast ci_max_artifact_size_dast + ci_max_artifact_size_running_container_scanning ci_max_artifact_size_codequality ci_max_artifact_size_license_management ci_max_artifact_size_performance diff --git a/spec/services/ci/create_pipeline_service/rules_spec.rb b/spec/services/ci/create_pipeline_service/rules_spec.rb index 33ec6aacc44..acdf38bbc13 100644 --- a/spec/services/ci/create_pipeline_service/rules_spec.rb +++ b/spec/services/ci/create_pipeline_service/rules_spec.rb @@ -230,22 +230,6 @@ RSpec.describe Ci::CreatePipelineService do [nil, nil, nil, 'job var 4', nil, nil, 'overridden var 7'] ) end - - context 'when FF ci_workflow_rules_variables is disabled' do - before do - stub_feature_flags(ci_workflow_rules_variables: false) - end - - it 'does not affect workflow variables but job variables' do - expect(job1.scoped_variables.to_hash.values_at(*variable_keys)).to eq( - ['overridden var 1', 'job var 2', nil, 'workflow var 4', 'job var 5', nil, 'workflow var 7'] - ) - - expect(job2.scoped_variables.to_hash.values_at(*variable_keys)).to eq( - [nil, nil, nil, 'job var 4', nil, nil, 'overridden var 7'] - ) - end - end end context 'when matching to the second rule' do diff --git a/spec/support/shared_examples/metrics/active_record_subscriber_shared_examples.rb b/spec/support/shared_examples/metrics/active_record_subscriber_shared_examples.rb index cce9d584690..a84658780b9 100644 --- a/spec/support/shared_examples/metrics/active_record_subscriber_shared_examples.rb +++ b/spec/support/shared_examples/metrics/active_record_subscriber_shared_examples.rb @@ -19,6 +19,8 @@ RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role| db_replica_count: 0, db_replica_duration_s: 0.0, db_primary_wal_count: record_wal_query ? 1 : 0, + db_primary_wal_cached_count: record_wal_query && record_cached_query ? 1 : 0, + db_replica_wal_cached_count: 0, db_replica_wal_count: 0 } expected[:"db_primary_#{::Gitlab::Database.dbname(connection)}_duration_s"] = 0.002 if record_query @@ -34,6 +36,8 @@ RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role| db_replica_count: record_query ? 1 : 0, db_replica_duration_s: record_query ? 0.002 : 0, db_replica_wal_count: record_wal_query ? 1 : 0, + db_replica_wal_cached_count: record_wal_query && record_cached_query ? 1 : 0, + db_primary_wal_cached_count: 0, db_primary_wal_count: 0 } expected[:"db_replica_#{::Gitlab::Database.dbname(connection)}_duration_s"] = 0.002 if record_query @@ -91,7 +95,10 @@ RSpec.shared_examples 'record ActiveRecord metrics in a metrics transaction' do end if record_wal_query - expect(transaction).to receive(:increment).with("gitlab_transaction_db_#{db_role}_wal_count_total".to_sym, 1) if db_role + if db_role + expect(transaction).to receive(:increment).with("gitlab_transaction_db_#{db_role}_wal_count_total".to_sym, 1) + expect(transaction).to receive(:increment).with("gitlab_transaction_db_#{db_role}_wal_cached_count_total".to_sym, 1) if record_cached_query + end else expect(transaction).not_to receive(:increment).with("gitlab_transaction_db_#{db_role}_wal_count_total".to_sym, 1) if db_role end |