diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-06-15 15:10:11 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-06-15 15:10:11 +0300 |
commit | 96acc69fae1ee7d559ba7eaa4e8304c8261525e3 (patch) | |
tree | b1ed433da35a415cab8ed544d85ac4c939efab0e | |
parent | a1498861799d1695682d72870580a6c3fb5ca3cf (diff) |
Add latest changes from gitlab-org/gitlab@master
208 files changed, 1105 insertions, 3649 deletions
diff --git a/.gitlab/ci/global.gitlab-ci.yml b/.gitlab/ci/global.gitlab-ci.yml index 5d17fad0c47..ba49ddfce9d 100644 --- a/.gitlab/ci/global.gitlab-ci.yml +++ b/.gitlab/ci/global.gitlab-ci.yml @@ -181,6 +181,15 @@ - *node-modules-cache-push - *assets-cache-push +.use-pg11: + image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.16-git-2.31-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.36" + services: + - name: postgres:11.6 + command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"] + - name: redis:5.0-alpine + variables: + POSTGRES_HOST_AUTH_METHOD: trust + .use-pg12: image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.16-git-2.31-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-12-graphicsmagick-1.3.36" services: @@ -190,6 +199,17 @@ variables: POSTGRES_HOST_AUTH_METHOD: trust +.use-pg11-ee: + image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.16-git-2.31-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.36" + services: + - name: postgres:11.6 + command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"] + - name: redis:5.0-alpine + - name: elasticsearch:7.11.1 + command: ["elasticsearch", "-E", "discovery.type=single-node"] + variables: + POSTGRES_HOST_AUTH_METHOD: trust + .use-pg12-ee: image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.2.patched-golang-1.16-git-2.31-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-12-graphicsmagick-1.3.36" services: diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml index c4d393eb16c..b74c8ebf575 100644 --- a/.gitlab/ci/rails.gitlab-ci.yml +++ b/.gitlab/ci/rails.gitlab-ci.yml @@ -58,6 +58,11 @@ - !reference [.base-script, script] - rspec_paralellized_job "--tag ~quarantine --tag ~geo --tag level:migration" +.rspec-base-pg11: + extends: + - .rspec-base + - .use-pg11 + .rspec-base-pg12: extends: - .rspec-base @@ -70,6 +75,11 @@ - .use-pg12 needs: ["setup-test-env", "retrieve-tests-metadata", "compile-test-assets as-if-foss", "detect-tests"] +.rspec-ee-base-pg11: + extends: + - .rspec-base + - .use-pg11-ee + .rspec-ee-base-pg12: extends: - .rspec-base @@ -81,6 +91,11 @@ - !reference [.base-script, script] - rspec_paralellized_job "--tag ~quarantine --tag geo" +.rspec-ee-base-geo-pg11: + extends: + - .rspec-ee-base-geo + - .use-pg11-ee + .rspec-ee-base-geo-pg12: extends: - .rspec-ee-base-geo @@ -277,6 +292,16 @@ rspec system pg12 minimal: - .minimal-rspec-tests - .rails:rules:ee-and-foss-system:minimal +# Dedicated job to test DB library code against PG11. +# Note that these are already tested against PG12 in the `rspec unit pg12` / `rspec-ee unit pg12` jobs. +rspec db-library-code pg11: + extends: + - .rspec-base-pg11 + - .rails:rules:ee-and-foss-db-library-code + script: + - !reference [.base-script, script] + - rspec_db_library_code + rspec fast_spec_helper: extends: - .rspec-base-pg12 @@ -637,6 +662,80 @@ db:rollback geo: # EE: default refs (MRs, default branch, schedules) jobs # ################################################## +########################################## +# EE/FOSS: default branch nightly scheduled jobs # +rspec migration pg11: + extends: + - .rspec-base-pg11 + - .rspec-base-migration + - .rails:rules:default-branch-schedule-nightly--code-backstage + - .rspec-migration-parallel + +rspec unit pg11: + extends: + - .rspec-base-pg11 + - .rails:rules:default-branch-schedule-nightly--code-backstage + - .rspec-unit-parallel + +rspec integration pg11: + extends: + - .rspec-base-pg11 + - .rails:rules:default-branch-schedule-nightly--code-backstage + - .rspec-integration-parallel + +rspec system pg11: + extends: + - .rspec-base-pg11 + - .rails:rules:default-branch-schedule-nightly--code-backstage + - .rspec-system-parallel +# EE/FOSS: default branch nightly scheduled jobs # +########################################## + +##################################### +# EE: default branch nightly scheduled jobs # +rspec-ee migration pg11: + extends: + - .rspec-ee-base-pg11 + - .rspec-base-migration + - .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only + - .rspec-ee-migration-parallel + +rspec-ee unit pg11: + extends: + - .rspec-ee-base-pg11 + - .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only + - .rspec-ee-unit-parallel + +rspec-ee integration pg11: + extends: + - .rspec-ee-base-pg11 + - .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only + - .rspec-ee-integration-parallel + +rspec-ee system pg11: + extends: + - .rspec-ee-base-pg11 + - .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only + - .rspec-ee-system-parallel + +rspec-ee unit pg11 geo: + extends: + - .rspec-ee-base-geo-pg11 + - .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only + - .rspec-ee-unit-geo-parallel + +rspec-ee integration pg11 geo: + extends: + - .rspec-ee-base-geo-pg11 + - .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only + +rspec-ee system pg11 geo: + extends: + - .rspec-ee-base-geo-pg11 + - .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only +# EE: default branch nightly scheduled jobs # +##################################### + ################################################## # EE: Canonical MR pipelines rspec fail-fast: diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index b6b02e5ce0e..ad59f7f93a8 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -c50b0080e9996e5db5eb4d75dfc3811618812798 +56aaf62b7d7045b9f6bdcd25566c005e5eca72fd @@ -402,7 +402,7 @@ group :development, :test do end group :development, :test, :danger do - gem 'gitlab-dangerfiles', '~> 2.0.0', require: false + gem 'gitlab-dangerfiles', '~> 2.1.2', require: false end group :development, :test, :coverage do diff --git a/Gemfile.lock b/Gemfile.lock index fc257672822..323353d61ce 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -451,7 +451,7 @@ GEM terminal-table (~> 1.5, >= 1.5.1) gitlab-chronic (0.10.5) numerizer (~> 0.2) - gitlab-dangerfiles (2.0.0) + gitlab-dangerfiles (2.1.2) danger-gitlab gitlab-experiment (0.5.4) activesupport (>= 3.0) @@ -1474,7 +1474,7 @@ DEPENDENCIES gitaly (~> 13.12.0.pre.rc1) github-markup (~> 1.7.0) gitlab-chronic (~> 0.10.5) - gitlab-dangerfiles (~> 2.0.0) + gitlab-dangerfiles (~> 2.1.2) gitlab-experiment (~> 0.5.4) gitlab-fog-azure-rm (~> 1.1.1) gitlab-fog-google (~> 1.13) diff --git a/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue b/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue index bc1e401d373..77ec1f1af47 100644 --- a/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue +++ b/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue @@ -93,7 +93,7 @@ export default { placement="top" class="trigger-description gl-display-flex" > - <div class="gl-flex-fill-1 gl-text-truncate">{{ item.description }}</div> + <div class="gl-flex-grow-1 gl-text-truncate">{{ item.description }}</div> </tooltip-on-truncate> </template> <template #cell(owner)="{ item }"> diff --git a/app/assets/javascripts/emoji/components/picker.vue b/app/assets/javascripts/emoji/components/picker.vue index 78ba2aabcf8..dc3eac0cd0c 100644 --- a/app/assets/javascripts/emoji/components/picker.vue +++ b/app/assets/javascripts/emoji/components/picker.vue @@ -111,7 +111,7 @@ export default { 'gl-text-body! emoji-picker-category-active': index === currentCategory, }" type="button" - class="gl-border-0 gl-border-b-2 gl-border-b-solid gl-flex-fill-1 gl-text-gray-300 gl-pt-3 gl-pb-3 gl-bg-transparent emoji-picker-category-tab" + class="gl-border-0 gl-border-b-2 gl-border-b-solid gl-flex-grow-1 gl-text-gray-300 gl-pt-3 gl-pb-3 gl-bg-transparent emoji-picker-category-tab" :aria-label="category.name" @click="scrollToCategory(category.name)" > diff --git a/app/assets/javascripts/environments/components/environment_actions.vue b/app/assets/javascripts/environments/components/environment_actions.vue index 8911380290a..542b8c9219d 100644 --- a/app/assets/javascripts/environments/components/environment_actions.vue +++ b/app/assets/javascripts/environments/components/environment_actions.vue @@ -89,7 +89,7 @@ export default { data-testid="manual-action-link" @click="onClickAction(action)" > - <span class="gl-flex-fill-1">{{ action.name }}</span> + <span class="gl-flex-grow-1">{{ action.name }}</span> <span v-if="action.scheduledAt" class="gl-text-gray-500 float-right"> <gl-icon name="clock" /> {{ remainingTime(action) }} diff --git a/app/assets/javascripts/environments/components/environments_app.vue b/app/assets/javascripts/environments/components/environments_app.vue index 602639f09a6..8bd71db957c 100644 --- a/app/assets/javascripts/environments/components/environments_app.vue +++ b/app/assets/javascripts/environments/components/environments_app.vue @@ -121,7 +121,7 @@ export default { variant="info" category="secondary" type="button" - class="gl-mb-3 gl-flex-fill-1" + class="gl-mb-3 gl-flex-grow-1" >{{ $options.i18n.reviewAppButtonLabel }}</gl-button > <gl-button diff --git a/app/assets/javascripts/environments/components/stop_environment_modal.vue b/app/assets/javascripts/environments/components/stop_environment_modal.vue index 828a7098b36..7a9233048a9 100644 --- a/app/assets/javascripts/environments/components/stop_environment_modal.vue +++ b/app/assets/javascripts/environments/components/stop_environment_modal.vue @@ -58,7 +58,7 @@ export default { <span v-gl-tooltip :title="environment.name" - class="gl-text-truncate gl-ml-2 gl-mr-2 gl-flex-fill" + class="gl-text-truncate gl-ml-2 gl-mr-2 gl-flex-grow-1" > {{ environment.name }}? </span> diff --git a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue index 0f564fc3c60..2e27f51b71f 100644 --- a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue +++ b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue @@ -260,7 +260,7 @@ export default { </template> <div v-else class="px-3">{{ __("You don't have any recent searches") }}</div> </gl-dropdown> - <div class="filtered-search-input-container gl-flex-fill-1"> + <div class="filtered-search-input-container gl-flex-grow-1"> <gl-form-input v-model="errorSearchQuery" class="pl-2 filtered-search" diff --git a/app/assets/javascripts/import_entities/import_groups/components/import_table_row.vue b/app/assets/javascripts/import_entities/import_groups/components/import_table_row.vue index e86c418f216..63c18f4d78e 100644 --- a/app/assets/javascripts/import_entities/import_groups/components/import_table_row.vue +++ b/app/assets/javascripts/import_entities/import_groups/components/import_table_row.vue @@ -157,7 +157,7 @@ export default { :text="importTarget.target_namespace" :disabled="isAlreadyImported" toggle-class="gl-rounded-top-right-none! gl-rounded-bottom-right-none!" - class="import-entities-namespace-dropdown gl-h-7 gl-flex-fill-1" + class="import-entities-namespace-dropdown gl-h-7 gl-flex-grow-1" data-qa-selector="target_namespace_selector_dropdown" > <gl-dropdown-item @click="$emit('update-target-namespace', '')">{{ @@ -184,7 +184,7 @@ export default { > / </div> - <div class="gl-flex-fill-1"> + <div class="gl-flex-grow-1"> <gl-form-input class="gl-rounded-top-left-none gl-rounded-bottom-left-none" :class="{ 'is-invalid': isInvalid && !isAlreadyImported }" diff --git a/app/assets/javascripts/issuable_list/components/issuable_tabs.vue b/app/assets/javascripts/issuable_list/components/issuable_tabs.vue index dfe158ae2b0..977d03e62be 100644 --- a/app/assets/javascripts/issuable_list/components/issuable_tabs.vue +++ b/app/assets/javascripts/issuable_list/components/issuable_tabs.vue @@ -36,7 +36,7 @@ export default { <template> <div class="top-area"> <gl-tabs - class="gl-display-flex gl-flex-fill-1 gl-p-0 gl-m-0 mobile-separator issuable-state-filters" + class="gl-display-flex gl-flex-grow-1 gl-p-0 gl-m-0 mobile-separator issuable-state-filters" nav-class="gl-border-b-0" > <gl-tab diff --git a/app/assets/javascripts/packages/details/components/package_files.vue b/app/assets/javascripts/packages/details/components/package_files.vue index 3c71ac5137e..0563b612d04 100644 --- a/app/assets/javascripts/packages/details/components/package_files.vue +++ b/app/assets/javascripts/packages/details/components/package_files.vue @@ -148,7 +148,7 @@ export default { <template #row-details="{ item }"> <div - class="gl-display-flex gl-flex-direction-column gl-flex-fill-1 gl-bg-gray-10 gl-rounded-base gl-inset-border-1-gray-100" + class="gl-display-flex gl-flex-direction-column gl-flex-grow-1 gl-bg-gray-10 gl-rounded-base gl-inset-border-1-gray-100" > <file-sha v-if="item.file_sha256" diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue index c110c1d4d62..9fb8be3fdb9 100644 --- a/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue +++ b/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue @@ -91,7 +91,7 @@ export default { label-position="hidden" @change="toggleFeature" /> - <div class="select-wrapper gl-flex-fill-1"> + <div class="select-wrapper gl-flex-grow-1"> <select :disabled="displaySelectInput" class="form-control project-repo-select select-control" diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue index 0b7b4c0ded1..11e6b4577e0 100644 --- a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue +++ b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue @@ -381,7 +381,7 @@ export default { :label="s__('ProjectSettings|Project visibility')" > <div class="project-feature-controls gl-display-flex gl-align-items-center gl-my-3 gl-mx-0"> - <div class="select-wrapper gl-flex-fill-1"> + <div class="select-wrapper gl-flex-grow-1"> <select v-model="visibilityLevel" :disabled="!canChangeVisibilityLevel" diff --git a/app/assets/javascripts/reports/codequality_report/components/codequality_issue_body.vue b/app/assets/javascripts/reports/codequality_report/components/codequality_issue_body.vue index dabfb623f43..736c8668a34 100644 --- a/app/assets/javascripts/reports/codequality_report/components/codequality_issue_body.vue +++ b/app/assets/javascripts/reports/codequality_report/components/codequality_issue_body.vue @@ -61,7 +61,7 @@ export default { <span :class="severityClass" class="gl-mr-5" data-testid="codequality-severity-icon"> <gl-icon v-tooltip="severityLabel" :name="severityIcon" :size="12" /> </span> - <div class="gl-flex-fill-1"> + <div class="gl-flex-grow-1"> <div> <strong v-if="isStatusSuccess">{{ s__('ciReport|Fixed:') }}</strong> {{ issueName }} diff --git a/app/assets/javascripts/runner/constants.js b/app/assets/javascripts/runner/constants.js index d47efc85eff..a57d18ba745 100644 --- a/app/assets/javascripts/runner/constants.js +++ b/app/assets/javascripts/runner/constants.js @@ -10,6 +10,7 @@ export const RUNNER_ENTITY_TYPE = 'Ci::Runner'; // - Used for URL params names // - GlFilteredSearch tokens type +export const PARAM_KEY_SEARCH = 'search'; export const PARAM_KEY_STATUS = 'status'; export const PARAM_KEY_RUNNER_TYPE = 'runner_type'; export const PARAM_KEY_SORT = 'sort'; diff --git a/app/assets/javascripts/runner/graphql/get_runners.query.graphql b/app/assets/javascripts/runner/graphql/get_runners.query.graphql index 84b7e2547f5..45df9c625a6 100644 --- a/app/assets/javascripts/runner/graphql/get_runners.query.graphql +++ b/app/assets/javascripts/runner/graphql/get_runners.query.graphql @@ -6,6 +6,7 @@ query getRunners( $after: String $first: Int $last: Int + $search: String $status: CiRunnerStatus $type: CiRunnerType $sort: CiRunnerSort @@ -15,6 +16,7 @@ query getRunners( after: $after first: $first last: $last + search: $search status: $status type: $type sort: $sort diff --git a/app/assets/javascripts/runner/runner_list/runner_list_app.vue b/app/assets/javascripts/runner/runner_list/runner_list_app.vue index d53774709ba..b4eacb911a2 100644 --- a/app/assets/javascripts/runner/runner_list/runner_list_app.vue +++ b/app/assets/javascripts/runner/runner_list/runner_list_app.vue @@ -12,7 +12,7 @@ import { fromUrlQueryToSearch, fromSearchToUrl, fromSearchToVariables, -} from './filtered_search_utils'; +} from './runner_search_utils'; export default { components: { diff --git a/app/assets/javascripts/runner/runner_list/filtered_search_utils.js b/app/assets/javascripts/runner/runner_list/runner_search_utils.js index 2303dd587e1..e45972b81db 100644 --- a/app/assets/javascripts/runner/runner_list/filtered_search_utils.js +++ b/app/assets/javascripts/runner/runner_list/runner_search_utils.js @@ -1,5 +1,12 @@ import { queryToObject, setUrlParams } from '~/lib/utils/url_utility'; import { + filterToQueryObject, + processFilters, + urlQueryToFilter, + prepareTokens, +} from '~/vue_shared/components/filtered_search_bar/filtered_search_utils'; +import { + PARAM_KEY_SEARCH, PARAM_KEY_STATUS, PARAM_KEY_RUNNER_TYPE, PARAM_KEY_SORT, @@ -10,30 +17,6 @@ import { RUNNER_PAGE_SIZE, } from '../constants'; -const getValuesFromFilters = (paramKey, filters) => { - return filters - .filter(({ type, value }) => type === paramKey && value.operator === '=') - .map(({ value }) => value.data); -}; - -const getFilterFromParams = (paramKey, params) => { - const value = params[paramKey]; - if (!value) { - return []; - } - - const values = Array.isArray(value) ? value : [value]; - return values.map((data) => { - return { - type: paramKey, - value: { - data, - operator: '=', - }, - }; - }); -}; - const getPaginationFromParams = (params) => { const page = parseInt(params[PARAM_KEY_PAGE], 10); const after = params[PARAM_KEY_AFTER]; @@ -55,10 +38,13 @@ export const fromUrlQueryToSearch = (query = window.location.search) => { const params = queryToObject(query, { gatherArrays: true }); return { - filters: [ - ...getFilterFromParams(PARAM_KEY_STATUS, params), - ...getFilterFromParams(PARAM_KEY_RUNNER_TYPE, params), - ], + filters: prepareTokens( + urlQueryToFilter(query, { + filterNamesAllowList: [PARAM_KEY_STATUS, PARAM_KEY_RUNNER_TYPE], + filteredSearchTermKey: PARAM_KEY_SEARCH, + legacySpacesDecode: false, + }), + ), sort: params[PARAM_KEY_SORT] || DEFAULT_SORT, pagination: getPaginationFromParams(params), }; @@ -68,37 +54,44 @@ export const fromSearchToUrl = ( { filters = [], sort = null, pagination = {} }, url = window.location.href, ) => { - const urlParams = { - [PARAM_KEY_STATUS]: getValuesFromFilters(PARAM_KEY_STATUS, filters), - [PARAM_KEY_RUNNER_TYPE]: getValuesFromFilters(PARAM_KEY_RUNNER_TYPE, filters), + const filterParams = { + // Defaults + [PARAM_KEY_SEARCH]: null, + [PARAM_KEY_STATUS]: [], + [PARAM_KEY_RUNNER_TYPE]: [], + // Current filters + ...filterToQueryObject(processFilters(filters), { + filteredSearchTermKey: PARAM_KEY_SEARCH, + }), }; - if (sort && sort !== DEFAULT_SORT) { - urlParams[PARAM_KEY_SORT] = sort; - } - - // Remove pagination params for first page - if (pagination?.page === 1) { - urlParams[PARAM_KEY_PAGE] = null; - urlParams[PARAM_KEY_BEFORE] = null; - urlParams[PARAM_KEY_AFTER] = null; - } else { - urlParams[PARAM_KEY_PAGE] = pagination.page; - urlParams[PARAM_KEY_BEFORE] = pagination.before; - urlParams[PARAM_KEY_AFTER] = pagination.after; - } + const isDefaultSort = sort !== DEFAULT_SORT; + const isFirstPage = pagination?.page === 1; + const otherParams = { + // Sorting & Pagination + [PARAM_KEY_SORT]: isDefaultSort ? sort : null, + [PARAM_KEY_PAGE]: isFirstPage ? null : pagination.page, + [PARAM_KEY_BEFORE]: isFirstPage ? null : pagination.before, + [PARAM_KEY_AFTER]: isFirstPage ? null : pagination.after, + }; - return setUrlParams(urlParams, url, false, true, true); + return setUrlParams({ ...filterParams, ...otherParams }, url, false, true, true); }; export const fromSearchToVariables = ({ filters = [], sort = null, pagination = {} } = {}) => { const variables = {}; + const queryObj = filterToQueryObject(processFilters(filters), { + filteredSearchTermKey: PARAM_KEY_SEARCH, + }); + + variables.search = queryObj[PARAM_KEY_SEARCH]; + // TODO Get more than one value when GraphQL API supports OR for "status" - [variables.status] = getValuesFromFilters(PARAM_KEY_STATUS, filters); + [variables.status] = queryObj[PARAM_KEY_STATUS] || []; // TODO Get more than one value when GraphQL API supports OR for "runner type" - [variables.type] = getValuesFromFilters(PARAM_KEY_RUNNER_TYPE, filters); + [variables.type] = queryObj[PARAM_KEY_RUNNER_TYPE] || []; if (sort) { variables.sort = sort; diff --git a/app/assets/javascripts/search/topbar/components/app.vue b/app/assets/javascripts/search/topbar/components/app.vue index 2439ab55923..a490adbc11a 100644 --- a/app/assets/javascripts/search/topbar/components/app.vue +++ b/app/assets/javascripts/search/topbar/components/app.vue @@ -48,7 +48,7 @@ export default { <template> <gl-form class="search-page-form" @submit.prevent="applyQuery"> <section class="gl-lg-display-flex gl-align-items-flex-end"> - <div class="gl-flex-fill-1 gl-mb-4 gl-lg-mb-0 gl-lg-mr-2"> + <div class="gl-flex-grow-1 gl-mb-4 gl-lg-mb-0 gl-lg-mr-2"> <label>{{ __('What are you searching for?') }}</label> <gl-search-box-by-type id="dashboard_search" diff --git a/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue b/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue index 6a6300dcde0..592cfea5e32 100644 --- a/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue +++ b/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue @@ -148,7 +148,9 @@ export default { </div> <div class="hide-collapsed"> - <p class="title gl-display-flex gl-justify-content-space-between"> + <p + class="gl-line-height-20 gl-mb-0 gl-text-gray-900 gl-display-flex gl-justify-content-space-between" + > {{ $options.i18n.SEVERITY }} <gl-link data-testid="editButton" diff --git a/app/assets/javascripts/user_lists/components/user_list_form.vue b/app/assets/javascripts/user_lists/components/user_list_form.vue index a0364089d68..b53aaf46ace 100644 --- a/app/assets/javascripts/user_lists/components/user_list_form.vue +++ b/app/assets/javascripts/user_lists/components/user_list_form.vue @@ -75,7 +75,7 @@ export default { </template> </gl-sprintf> </div> - <div class="gl-flex-fill-1 gl-ml-7"> + <div class="gl-flex-grow-1 gl-ml-7"> <gl-form-group label-for="user-list-name" :label="$options.translations.nameLabel" diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_expandable_section.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_expandable_section.vue index c368399ed6f..f8c4ad69e39 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_expandable_section.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_expandable_section.vue @@ -51,7 +51,7 @@ export default { <gl-icon :name="iconName" :size="24" /> </span> - <div class="gl-display-flex gl-flex-fill-1 gl-flex-direction-column gl-md-flex-direction-row"> + <div class="gl-display-flex gl-flex-grow-1 gl-flex-direction-column gl-md-flex-direction-row"> <slot name="header"></slot> <div> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue index fa46b4b1364..6c162a06161 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue @@ -160,7 +160,7 @@ export default { <div class="ci-widget media"> <template v-if="hasCIError"> <gl-icon name="status_failed" class="gl-text-red-500" :size="24" /> - <p class="gl-flex-fill-1 gl-ml-5 gl-mb-0" data-testid="ci-error-message"> + <p class="gl-flex-grow-1 gl-ml-5 gl-mb-0" data-testid="ci-error-message"> <gl-sprintf :message="$options.errorText"> <template #link="{ content }"> <gl-link :href="mrTroubleshootingDocsPath">{{ content }}</gl-link> @@ -171,7 +171,7 @@ export default { <template v-else-if="!hasPipeline"> <gl-loading-icon size="md" /> <p - class="gl-flex-fill-1 gl-display-flex gl-ml-5 gl-mb-0" + class="gl-flex-grow-1 gl-display-flex gl-ml-5 gl-mb-0" data-testid="monitoring-pipeline-message" > {{ $options.monitoringPipelineText }} diff --git a/app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue b/app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue index 25f339b362f..2ba945a3ecf 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue @@ -107,7 +107,7 @@ export default { <template #header> <div data-testid="terraform-header-text" - class="gl-flex-fill-1 gl-display-flex gl-flex-direction-column" + class="gl-flex-grow-1 gl-display-flex gl-flex-direction-column" > <p v-if="validPlanCountText" class="gl-m-0"> <gl-sprintf :message="validPlanCountText"> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue b/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue index 25e3dae92e8..427ab0842ea 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue @@ -71,8 +71,8 @@ export default { <gl-icon :name="iconType" :size="16" data-testid="change-type-icon" /> </span> - <div class="gl-display-flex gl-flex-fill-1 gl-flex-direction-column flex-md-row gl-pl-3"> - <div class="gl-flex-fill-1 gl-display-flex gl-flex-direction-column gl-pr-3"> + <div class="gl-display-flex gl-flex-grow-1 gl-flex-direction-column flex-md-row gl-pl-3"> + <div class="gl-flex-grow-1 gl-display-flex gl-flex-direction-column gl-pr-3"> <p class="gl-mb-3 gl-line-height-normal"> <gl-sprintf :message="reportHeaderText"> <template #name> diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_utils.js b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_utils.js index 4b1b09adcfd..37436de907f 100644 --- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_utils.js +++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_utils.js @@ -2,7 +2,7 @@ import { isEmpty, uniqWith, isEqual } from 'lodash'; import AccessorUtilities from '~/lib/utils/accessor'; import { queryToObject } from '~/lib/utils/url_utility'; -import { MAX_RECENT_TOKENS_SIZE } from './constants'; +import { MAX_RECENT_TOKENS_SIZE, FILTERED_SEARCH_TERM } from './constants'; /** * Strips enclosing quotations from a string if it has one. @@ -23,7 +23,7 @@ export const stripQuotes = (value) => value.replace(/^('|")(.*)('|")$/, '$2'); export const uniqueTokens = (tokens) => { const knownTokens = []; return tokens.reduce((uniques, token) => { - if (typeof token === 'object' && token.type !== 'filtered-search-term') { + if (typeof token === 'object' && token.type !== FILTERED_SEARCH_TERM) { const tokenString = `${token.type}${token.value.operator}${token.value.data}`; if (!knownTokens.includes(tokenString)) { uniques.push(token); @@ -86,21 +86,37 @@ export function processFilters(filters) { }, {}); } +function filteredSearchQueryParam(filter) { + return filter + .map(({ value }) => value) + .join(' ') + .trim(); +} + /** * This function takes a filter object and maps it into a query object. Example filter: - * { myFilterName: { value: 'foo', operator: '=' } } + * { myFilterName: { value: 'foo', operator: '=' }, search: [{ value: 'my' }, { value: 'search' }] } * gets translated into: - * { myFilterName: 'foo', 'not[myFilterName]': null } + * { myFilterName: 'foo', 'not[myFilterName]': null, search: 'my search' } * @param {Object} filters - * @param {Object.myFilterName} a single filter value or an array of filters + * @param {Object} filters.myFilterName a single filter value or an array of filters + * @param {Object} options + * @param {Object} [options.filteredSearchTermKey] if set, 'filtered-search-term' filters are assigned to this key, 'search' is suggested * @return {Object} query object with both filter name and not-name with values */ -export function filterToQueryObject(filters = {}) { +export function filterToQueryObject(filters = {}, options = {}) { + const { filteredSearchTermKey } = options; + return Object.keys(filters).reduce((memo, key) => { const filter = filters[key]; + if (typeof filteredSearchTermKey === 'string' && key === FILTERED_SEARCH_TERM) { + return { ...memo, [filteredSearchTermKey]: filteredSearchQueryParam(filter) }; + } + let selected; let unselected; + if (Array.isArray(filter)) { selected = filter.filter((item) => item.operator === '=').map((item) => item.value); unselected = filter.filter((item) => item.operator === '!=').map((item) => item.value); @@ -125,7 +141,7 @@ export function filterToQueryObject(filters = {}) { * and returns the operator with it depending on the filter name * @param {String} filterName from url * @return {Object} - * @return {Object.filterName} extracted filtern ame + * @return {Object.filterName} extracted filter name * @return {Object.operator} `=` or `!=` */ function extractNameAndOperator(filterName) { @@ -138,21 +154,52 @@ function extractNameAndOperator(filterName) { } /** + * Gathers search term as values + * @param {String|Array} value + * @returns {Array} List of search terms split by word + */ +function filteredSearchTermValue(value) { + const values = Array.isArray(value) ? value : [value]; + return values + .filter((term) => term) + .join(' ') + .split(' ') + .map((term) => ({ value: term })); +} + +/** * This function takes a URL query string and maps it into a filter object. Example query string: * '?myFilterName=foo' * gets translated into: * { myFilterName: { value: 'foo', operator: '=' } } * @param {String} query URL query string, e.g. from `window.location.search` + * @param {Object} options + * @param {Object} options + * @param {String} [options.filteredSearchTermKey] if set, a FILTERED_SEARCH_TERM filter is created to this parameter. `'search'` is suggested + * @param {String[]} [options.filterNamesAllowList] if set, only this list of filters names is mapped + * @param {Boolean} [options.legacySpacesDecode] if set, plus symbols (+) are not encoded as spaces. `false` is suggested * @return {Object} filter object with filter names and their values */ -export function urlQueryToFilter(query = '') { - const filters = queryToObject(query, { gatherArrays: true, legacySpacesDecode: true }); +export function urlQueryToFilter(query = '', options = {}) { + const { filteredSearchTermKey, filterNamesAllowList, legacySpacesDecode = true } = options; + + const filters = queryToObject(query, { gatherArrays: true, legacySpacesDecode }); return Object.keys(filters).reduce((memo, key) => { const value = filters[key]; if (!value) { return memo; } + if (key === filteredSearchTermKey) { + return { + ...memo, + [FILTERED_SEARCH_TERM]: filteredSearchTermValue(value), + }; + } + const { filterName, operator } = extractNameAndOperator(key); + if (filterNamesAllowList && !filterNamesAllowList.includes(filterName)) { + return memo; + } let previousValues = []; if (Array.isArray(memo[filterName])) { previousValues = memo[filterName]; diff --git a/app/assets/javascripts/vue_shared/components/registry/list_item.vue b/app/assets/javascripts/vue_shared/components/registry/list_item.vue index b9e916bc199..933a215112b 100644 --- a/app/assets/javascripts/vue_shared/components/registry/list_item.vue +++ b/app/assets/javascripts/vue_shared/components/registry/list_item.vue @@ -62,7 +62,7 @@ export default { <slot name="left-action"></slot> </div> <div - class="gl-display-flex gl-xs-flex-direction-column gl-justify-content-space-between gl-align-items-stretch gl-flex-fill-1" + class="gl-display-flex gl-xs-flex-direction-column gl-justify-content-space-between gl-align-items-stretch gl-flex-grow-1" > <div class="gl-display-flex gl-flex-direction-column gl-xs-mb-3 gl-min-w-0 gl-flex-grow-1"> <div @@ -81,7 +81,7 @@ export default { </div> <div v-if="$slots['left-secondary']" - class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-min-h-6 gl-min-w-0 gl-flex-fill-1" + class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-min-h-6 gl-min-w-0 gl-flex-grow-1" > <slot name="left-secondary"></slot> </div> @@ -114,7 +114,7 @@ export default { <div class="gl-w-7"></div> <div v-if="isDetailsShown" - class="gl-display-flex gl-flex-direction-column gl-flex-fill-1 gl-bg-gray-10 gl-rounded-base gl-inset-border-1-gray-100 gl-mb-3" + class="gl-display-flex gl-flex-direction-column gl-flex-grow-1 gl-bg-gray-10 gl-rounded-base gl-inset-border-1-gray-100 gl-mb-3" > <div v-for="(row, detailIndex) in detailsSlots" diff --git a/app/assets/javascripts/vue_shared/components/registry/registry_search.vue b/app/assets/javascripts/vue_shared/components/registry/registry_search.vue index 0825c3a76ea..767a108dde5 100644 --- a/app/assets/javascripts/vue_shared/components/registry/registry_search.vue +++ b/app/assets/javascripts/vue_shared/components/registry/registry_search.vue @@ -109,7 +109,7 @@ export default { <div class="gl-display-flex gl-p-5 gl-bg-gray-10 gl-border-solid gl-border-1 gl-border-gray-100"> <gl-filtered-search v-model="internalFilter" - class="gl-mr-4 gl-flex-fill-1" + class="gl-mr-4 gl-flex-grow-1" :placeholder="__('Filter results')" :available-tokens="tokens" @submit="submitSearch" diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue index 1f70644eb2c..580e1668f41 100644 --- a/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue +++ b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue @@ -225,7 +225,7 @@ export default { <template v-if="!instructionsEmpty"> <div class="gl-display-flex"> <pre - class="gl-bg-gray gl-flex-fill-1 gl-white-space-pre-line" + class="gl-bg-gray gl-flex-grow-1 gl-white-space-pre-line" data-testid="binary-instructions" >{{ instructions.installInstructions }}</pre > @@ -241,7 +241,7 @@ export default { <h5 class="gl-mb-3">{{ $options.i18n.registerRunnerCommand }}</h5> <div class="gl-display-flex"> <pre - class="gl-bg-gray gl-flex-fill-1 gl-white-space-pre-line" + class="gl-bg-gray gl-flex-grow-1 gl-white-space-pre-line" data-testid="register-command" >{{ instructions.registerInstructions }}</pre > diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss index 603747aa490..2fbdaaaf467 100644 --- a/app/assets/stylesheets/framework.scss +++ b/app/assets/stylesheets/framework.scss @@ -47,6 +47,7 @@ @import 'framework/toggle'; @import 'framework/typography'; @import 'framework/zen'; +@import 'framework/blank'; @import 'framework/wells'; @import 'framework/page_header'; @import 'framework/page_title'; diff --git a/app/assets/stylesheets/framework/blank.scss b/app/assets/stylesheets/framework/blank.scss new file mode 100644 index 00000000000..7dd7ab339dd --- /dev/null +++ b/app/assets/stylesheets/framework/blank.scss @@ -0,0 +1,118 @@ +.blank-state-parent-container { + .section-container { + padding: 10px; + } + + .section-body { + width: 100%; + height: 100%; + padding-bottom: 25px; + border-radius: $border-radius-default; + } +} + +.blank-state-row { + display: flex; + flex-wrap: wrap; + justify-content: space-between; +} + +.blank-state-welcome { + text-align: center; + padding: $gl-padding 0 ($gl-padding * 2); + + .blank-state-welcome-title { + font-size: 24px; + } + + .blank-state-text { + margin-bottom: 0; + } +} + +.blank-state-link { + color: $gl-text-color; + margin-bottom: 15px; + + &:hover { + background-color: $gray-light; + text-decoration: none; + color: $gl-text-color; + } +} + +.blank-state-center { + padding-top: 20px; + padding-bottom: 20px; + text-align: center; +} + +.blank-state { + display: flex; + align-items: center; + padding: 20px 50px; + border: 1px solid $border-color; + border-radius: $border-radius-default; + min-height: 240px; + margin-bottom: $gl-padding; + width: calc(50% - #{$gl-padding-8}); + + @include media-breakpoint-down(sm) { + width: 100%; + flex-direction: column; + justify-content: center; + padding: 50px 20px; + + .column-small & { + width: 100%; + } + + } +} + +.blank-state, +.blank-state-center { + .blank-state-icon { + svg { + display: block; + margin: auto; + } + } + + .blank-state-title { + margin-top: 0; + font-size: 18px; + } + + .blank-state-body { + @include media-breakpoint-down(sm) { + text-align: center; + margin-top: 20px; + } + + @include media-breakpoint-up(sm) { + padding-left: 20px; + } + } +} + +@include media-breakpoint-up(lg) { + .column-large { + flex: 2; + } + + .column-small { + flex: 1; + margin-bottom: 15px; + + .blank-state { + max-width: 400px; + flex-wrap: wrap; + margin-left: 15px; + } + + .blank-state-icon { + margin-bottom: 30px; + } + } +} diff --git a/app/controllers/clusters/applications_controller.rb b/app/controllers/clusters/applications_controller.rb index 5c1d85f4374..91003e9580d 100644 --- a/app/controllers/clusters/applications_controller.rb +++ b/app/controllers/clusters/applications_controller.rb @@ -47,7 +47,7 @@ class Clusters::ApplicationsController < Clusters::BaseController end def cluster_application_params - params.permit(:application, :hostname, :pages_domain_id, :email, :stack, :host, :port, :protocol, :cilium_log_enabled) + params.permit(:application, :hostname, :pages_domain_id, :email, :stack, :host, :port, :protocol) end def cluster_application_destroy_params diff --git a/app/controllers/concerns/membership_actions.rb b/app/controllers/concerns/membership_actions.rb index 565484495ba..8fd4e98d557 100644 --- a/app/controllers/concerns/membership_actions.rb +++ b/app/controllers/concerns/membership_actions.rb @@ -140,39 +140,15 @@ module MembershipActions end def root_params_key - case membershipable - when Namespace - :group_member - when Project - :project_member - else - raise "Unknown membershipable type: #{membershipable}!" - end + raise NotImplementedError end def members_page_url - case membershipable - when Namespace - polymorphic_url([membershipable, :members]) - when Project - project_project_members_path(membershipable) - else - raise "Unknown membershipable type: #{membershipable}!" - end + raise NotImplementedError end def source_type - @source_type ||= - begin - case membershipable - when Namespace - _("group") - when Project - _("project") - else - raise "Unknown membershipable type: #{membershipable}!" - end - end + raise NotImplementedError end def plain_source_type diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb index f3b1d71d06e..8d9059d271f 100644 --- a/app/controllers/groups/group_members_controller.rb +++ b/app/controllers/groups/group_members_controller.rb @@ -82,6 +82,18 @@ class Groups::GroupMembersController < Groups::ApplicationController def plain_source_type 'group' end + + def source_type + _("group") + end + + def members_page_url + polymorphic_url([group, :members]) + end + + def root_params_key + :group_member + end end Groups::GroupMembersController.prepend_mod_with('Groups::GroupMembersController') diff --git a/app/controllers/projects/feature_flags_controller.rb b/app/controllers/projects/feature_flags_controller.rb index 03561e73828..a59824b1085 100644 --- a/app/controllers/projects/feature_flags_controller.rb +++ b/app/controllers/projects/feature_flags_controller.rb @@ -11,6 +11,7 @@ class Projects::FeatureFlagsController < Projects::ApplicationController before_action :feature_flag, only: [:edit, :update, :destroy] before_action :ensure_flag_writable!, only: [:update] + before_action :exclude_legacy_flags_check, only: [:edit] before_action do push_frontend_feature_flag(:feature_flag_permissions) @@ -63,7 +64,6 @@ class Projects::FeatureFlagsController < Projects::ApplicationController end def edit - exclude_legacy_flags_check end def update @@ -108,6 +108,12 @@ class Projects::FeatureFlagsController < Projects::ApplicationController end end + def exclude_legacy_flags_check + if feature_flag.legacy_flag? + not_found + end + end + def create_params params.require(:operations_feature_flag) .permit(:name, :description, :active, :version, @@ -159,12 +165,4 @@ class Projects::FeatureFlagsController < Projects::ApplicationController render json: { message: messages }, status: status end - - def exclude_legacy_flags_check - if Feature.enabled?(:remove_legacy_flags, project, default_enabled: :yaml) && - Feature.disabled?(:remove_legacy_flags_override, project, default_enabled: :yaml) && - feature_flag.legacy_flag? - not_found - end - end end diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index 4f342980bf0..370cd2b02a1 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -66,6 +66,18 @@ class Projects::ProjectMembersController < Projects::ApplicationController def plain_source_type 'project' end + + def source_type + _("project") + end + + def members_page_url + project_project_members_path(project) + end + + def root_params_key + :project_member + end end Projects::ProjectMembersController.prepend_mod_with('Projects::ProjectMembersController') diff --git a/app/finders/feature_flags_finder.rb b/app/finders/feature_flags_finder.rb index 0ab65d3630e..20b18c62f7a 100644 --- a/app/finders/feature_flags_finder.rb +++ b/app/finders/feature_flags_finder.rb @@ -24,11 +24,7 @@ class FeatureFlagsFinder private def feature_flags - if exclude_legacy_flags? - project.operations_feature_flags.new_version_only - else - project.operations_feature_flags - end + project.operations_feature_flags.new_version_only end def by_scope(items) @@ -41,9 +37,4 @@ class FeatureFlagsFinder items end end - - def exclude_legacy_flags? - Feature.enabled?(:remove_legacy_flags, project, default_enabled: :yaml) && - Feature.disabled?(:remove_legacy_flags_override, project, default_enabled: :yaml) - end end diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index 1f4c98d6f28..e07ee22339a 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -9,7 +9,8 @@ module SearchHelper :repository_ref, :snippets, :sort, - :force_search_results + :force_search_results, + :project_ids ].freeze def search_autocomplete_opts(term) diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb index 586142a7646..6a7a2b3f6bd 100644 --- a/app/models/ci/job_artifact.rb +++ b/app/models/ci/job_artifact.rb @@ -43,7 +43,7 @@ module Ci dotenv: '.env', cobertura: 'cobertura-coverage.xml', terraform: 'tfplan.json', - cluster_applications: 'gl-cluster-applications.json', + cluster_applications: 'gl-cluster-applications.json', # DEPRECATED: https://gitlab.com/gitlab-org/gitlab/-/issues/333441 requirements: 'requirements.json', coverage_fuzzing: 'gl-coverage-fuzzing.json', api_fuzzing: 'gl-api-fuzzing-report.json' diff --git a/app/models/clusters/applications/fluentd.rb b/app/models/clusters/applications/fluentd.rb deleted file mode 100644 index c5d674c1908..00000000000 --- a/app/models/clusters/applications/fluentd.rb +++ /dev/null @@ -1,121 +0,0 @@ -# frozen_string_literal: true - -module Clusters - module Applications - class Fluentd < ApplicationRecord - VERSION = '2.4.0' - CILIUM_CONTAINER_NAME = 'cilium-monitor' - - self.table_name = 'clusters_applications_fluentd' - - include ::Clusters::Concerns::ApplicationCore - include ::Clusters::Concerns::ApplicationStatus - include ::Clusters::Concerns::ApplicationVersion - include ::Clusters::Concerns::ApplicationData - include IgnorableColumns - - default_value_for :version, VERSION - default_value_for :port, 514 - default_value_for :protocol, :tcp - - ignore_column :waf_log_enabled, remove_with: '14.2', remove_after: '2021-07-22' - - enum protocol: { tcp: 0, udp: 1 } - - validate :has_at_least_one_log_enabled? - - def chart - 'fluentd/fluentd' - end - - def repository - 'https://gitlab-org.gitlab.io/cluster-integration/helm-stable-archive' - end - - def install_command - helm_command_module::InstallCommand.new( - name: 'fluentd', - repository: repository, - version: VERSION, - rbac: cluster.platform_kubernetes_rbac?, - chart: chart, - files: files - ) - end - - def values - content_values.to_yaml - end - - private - - def has_at_least_one_log_enabled? - errors.add(:base, _("At least one logging option is required to be enabled")) unless cilium_log_enabled - end - - def content_values - YAML.load_file(chart_values_file).deep_merge!(specification) - end - - def specification - { - "configMaps" => { - "output.conf" => output_configuration_content, - "general.conf" => general_configuration_content - } - } - end - - def output_configuration_content - <<~EOF - <match kubernetes.**> - @type remote_syslog - @id out_kube_remote_syslog - host #{host} - port #{port} - program fluentd - hostname ${kubernetes_host} - protocol #{protocol} - packet_size 131072 - <buffer kubernetes_host> - </buffer> - <format> - @type ltsv - </format> - </match> - EOF - end - - def general_configuration_content - <<~EOF - <match fluent.**> - @type null - </match> - <source> - @type http - port 9880 - bind 0.0.0.0 - </source> - <source> - @type tail - @id in_tail_container_logs - path #{path_to_logs} - pos_file /var/log/fluentd-containers.log.pos - tag kubernetes.* - read_from_head true - <parse> - @type json - time_format %Y-%m-%dT%H:%M:%S.%NZ - </parse> - </source> - EOF - end - - def path_to_logs - path = [] - path << "/var/log/containers/*#{CILIUM_CONTAINER_NAME}*.log" if cilium_log_enabled - path.join(',') - end - end - end -end diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index aeebd2b368e..13ec8953353 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -21,7 +21,6 @@ module Clusters Clusters::Applications::Jupyter.application_name => Clusters::Applications::Jupyter, Clusters::Applications::Knative.application_name => Clusters::Applications::Knative, Clusters::Applications::ElasticStack.application_name => Clusters::Applications::ElasticStack, - Clusters::Applications::Fluentd.application_name => Clusters::Applications::Fluentd, Clusters::Applications::Cilium.application_name => Clusters::Applications::Cilium }.freeze DEFAULT_ENVIRONMENT = '*' @@ -68,7 +67,6 @@ module Clusters has_one_cluster_application :jupyter has_one_cluster_application :knative has_one_cluster_application :elastic_stack - has_one_cluster_application :fluentd has_one_cluster_application :cilium has_many :kubernetes_namespaces diff --git a/app/serializers/cluster_application_entity.rb b/app/serializers/cluster_application_entity.rb index fab590dbe09..f57ac4af113 100644 --- a/app/serializers/cluster_application_entity.rb +++ b/app/serializers/cluster_application_entity.rb @@ -17,5 +17,4 @@ class ClusterApplicationEntity < Grape::Entity expose :host, if: -> (e, _) { e.respond_to?(:host) } expose :port, if: -> (e, _) { e.respond_to?(:port) } expose :protocol, if: -> (e, _) { e.respond_to?(:protocol) } - expose :cilium_log_enabled, if: -> (e, _) { e.respond_to?(:cilium_log_enabled) } end diff --git a/app/services/ci/job_artifacts/create_service.rb b/app/services/ci/job_artifacts/create_service.rb index a22ac87f660..9fc7c3b4d40 100644 --- a/app/services/ci/job_artifacts/create_service.rb +++ b/app/services/ci/job_artifacts/create_service.rb @@ -115,7 +115,6 @@ module Ci case artifact.file_type when 'dotenv' then parse_dotenv_artifact(artifact) - when 'cluster_applications' then parse_cluster_applications_artifact(artifact) else success end end @@ -165,10 +164,6 @@ module Ci def parse_dotenv_artifact(artifact) Ci::ParseDotenvArtifactService.new(project, current_user).execute(artifact) end - - def parse_cluster_applications_artifact(artifact) - Clusters::ParseClusterApplicationsArtifactService.new(job, job.user).execute(artifact) - end end end end diff --git a/app/services/clusters/applications/base_service.rb b/app/services/clusters/applications/base_service.rb index 47d6fbbeda2..c6f22cfa04c 100644 --- a/app/services/clusters/applications/base_service.rb +++ b/app/services/clusters/applications/base_service.rb @@ -5,8 +5,6 @@ module Clusters class BaseService InvalidApplicationError = Class.new(StandardError) - FLUENTD_KNOWN_ATTRS = %i[host protocol port cilium_log_enabled].freeze - attr_reader :cluster, :current_user, :params def initialize(cluster, user, params = {}) @@ -29,8 +27,6 @@ module Clusters application.stack = params[:stack] end - apply_fluentd_related_attributes(application) - if application.respond_to?(:oauth_application) application.oauth_application = create_oauth_application(application, request) end @@ -95,12 +91,6 @@ module Clusters ::Applications::CreateService.new(current_user, oauth_application_params).execute(request) end - - def apply_fluentd_related_attributes(application) - FLUENTD_KNOWN_ATTRS.each do |attr| - application[attr] = params[attr] if application.has_attribute?(attr) - end - end end end end diff --git a/app/services/clusters/parse_cluster_applications_artifact_service.rb b/app/services/clusters/parse_cluster_applications_artifact_service.rb deleted file mode 100644 index b9b2953b6bd..00000000000 --- a/app/services/clusters/parse_cluster_applications_artifact_service.rb +++ /dev/null @@ -1,94 +0,0 @@ -# frozen_string_literal: true - -module Clusters - class ParseClusterApplicationsArtifactService < ::BaseService - include Gitlab::Utils::StrongMemoize - - MAX_ACCEPTABLE_ARTIFACT_SIZE = 5.kilobytes - RELEASE_NAMES = %w[cilium].freeze - - def initialize(job, current_user) - @job = job - - super(job.project, current_user) - end - - def execute(artifact) - raise ArgumentError, 'Artifact is not cluster_applications file type' unless artifact&.cluster_applications? - - return error(too_big_error_message, :bad_request) unless artifact.file.size < MAX_ACCEPTABLE_ARTIFACT_SIZE - return error(no_deployment_message, :bad_request) unless job.deployment - return error(no_deployment_cluster_message, :bad_request) unless cluster - - parse!(artifact) - - success - rescue Gitlab::Kubernetes::Helm::Parsers::ListV2::ParserError, ActiveRecord::RecordInvalid => error - Gitlab::ErrorTracking.track_exception(error, job_id: artifact.job_id) - error(error.message, :bad_request) - end - - private - - attr_reader :job - - def cluster - strong_memoize(:cluster) do - deployment_cluster = job.deployment&.cluster - - deployment_cluster if Ability.allowed?(current_user, :admin_cluster, deployment_cluster) - end - end - - def parse!(artifact) - releases = [] - - artifact.each_blob do |blob| - next if blob.empty? - - releases.concat(Gitlab::Kubernetes::Helm::Parsers::ListV2.new(blob).releases) - end - - update_cluster_application_statuses!(releases) - end - - def update_cluster_application_statuses!(releases) - release_by_name = releases.index_by { |release| release['Name'] } - - Clusters::Cluster.transaction do - RELEASE_NAMES.each do |release_name| - application_class = Clusters::Cluster::APPLICATIONS[release_name] - application = cluster.find_or_build_application(application_class) - - release = release_by_name[release_name] - - if release - case release['Status'] - when 'DEPLOYED' - application.make_externally_installed! - when 'FAILED' - application.make_errored!(s_('ClusterIntegration|Helm release failed to install')) - end - else - # missing, so by definition, we consider this uninstalled - application.make_externally_uninstalled! if application.persisted? - end - end - end - end - - def too_big_error_message - human_size = ActiveSupport::NumberHelper.number_to_human_size(MAX_ACCEPTABLE_ARTIFACT_SIZE) - - s_('ClusterIntegration|Cluster_applications artifact too big. Maximum allowable size: %{human_size}') % { human_size: human_size } - end - - def no_deployment_message - s_('ClusterIntegration|No deployment found for this job') - end - - def no_deployment_cluster_message - s_('ClusterIntegration|No deployment cluster found for this job') - end - end -end diff --git a/app/services/feature_flags/disable_service.rb b/app/services/feature_flags/disable_service.rb deleted file mode 100644 index 8a443ac1795..00000000000 --- a/app/services/feature_flags/disable_service.rb +++ /dev/null @@ -1,46 +0,0 @@ -# frozen_string_literal: true - -module FeatureFlags - class DisableService < BaseService - def execute - return error('Feature Flag not found', 404) unless feature_flag_by_name - return error('Feature Flag Scope not found', 404) unless feature_flag_scope_by_environment_scope - return error('Strategy not found', 404) unless strategy_exist_in_persisted_data? - - ::FeatureFlags::UpdateService - .new(project, current_user, update_params) - .execute(feature_flag_by_name) - end - - private - - def update_params - if remaining_strategies.empty? - params_to_destroy_scope - else - params_to_update_scope - end - end - - def remaining_strategies - strong_memoize(:remaining_strategies) do - feature_flag_scope_by_environment_scope.strategies.reject do |strategy| - strategy['name'] == params[:strategy]['name'] && - strategy['parameters'] == params[:strategy]['parameters'] - end - end - end - - def strategy_exist_in_persisted_data? - feature_flag_scope_by_environment_scope.strategies != remaining_strategies - end - - def params_to_destroy_scope - { scopes_attributes: [{ id: feature_flag_scope_by_environment_scope.id, _destroy: true }] } - end - - def params_to_update_scope - { scopes_attributes: [{ id: feature_flag_scope_by_environment_scope.id, strategies: remaining_strategies }] } - end - end -end diff --git a/app/services/feature_flags/enable_service.rb b/app/services/feature_flags/enable_service.rb deleted file mode 100644 index b4cbb32e003..00000000000 --- a/app/services/feature_flags/enable_service.rb +++ /dev/null @@ -1,93 +0,0 @@ -# frozen_string_literal: true - -module FeatureFlags - class EnableService < BaseService - def execute - if feature_flag_by_name - update_feature_flag - else - create_feature_flag - end - end - - private - - def create_feature_flag - ::FeatureFlags::CreateService - .new(project, current_user, create_params) - .execute - end - - def update_feature_flag - ::FeatureFlags::UpdateService - .new(project, current_user, update_params) - .execute(feature_flag_by_name) - end - - def create_params - if params[:environment_scope] == '*' - params_to_create_flag_with_default_scope - else - params_to_create_flag_with_additional_scope - end - end - - def update_params - if feature_flag_scope_by_environment_scope - params_to_update_scope - else - params_to_create_scope - end - end - - def params_to_create_flag_with_default_scope - { - name: params[:name], - scopes_attributes: [ - { - active: true, - environment_scope: '*', - strategies: [params[:strategy]] - } - ] - } - end - - def params_to_create_flag_with_additional_scope - { - name: params[:name], - scopes_attributes: [ - { - active: false, - environment_scope: '*' - }, - { - active: true, - environment_scope: params[:environment_scope], - strategies: [params[:strategy]] - } - ] - } - end - - def params_to_create_scope - { - scopes_attributes: [{ - active: true, - environment_scope: params[:environment_scope], - strategies: [params[:strategy]] - }] - } - end - - def params_to_update_scope - { - scopes_attributes: [{ - id: feature_flag_scope_by_environment_scope.id, - active: true, - strategies: feature_flag_scope_by_environment_scope.strategies | [params[:strategy]] - }] - } - end - end -end diff --git a/app/services/search/project_service.rb b/app/services/search/project_service.rb index 3181c0098cc..3e93346bfdf 100644 --- a/app/services/search/project_service.rb +++ b/app/services/search/project_service.rb @@ -8,8 +8,8 @@ module Search attr_accessor :project, :current_user, :params - def initialize(project, user, params) - @project = project + def initialize(project_or_projects, user, params) + @project = project_or_projects @current_user = user @params = params.dup end diff --git a/app/services/search_service.rb b/app/services/search_service.rb index 389cf17e115..cce7821a226 100644 --- a/app/services/search_service.rb +++ b/app/services/search_service.rb @@ -41,6 +41,10 @@ class SearchService end # rubocop: enable CodeReuse/ActiveRecord + def projects + # overridden in EE + end + def show_snippets? return @show_snippets if defined?(@show_snippets) diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml index 52e41946ed1..ca10861115b 100644 --- a/app/views/dashboard/todos/index.html.haml +++ b/app/views/dashboard/todos/index.html.haml @@ -37,7 +37,7 @@ .todos-filters .issues-details-filters.row-content-block.second-block = form_tag todos_filter_path(without: [:project_id, :author_id, :type, :action_id]), method: :get, class: 'filter-form gl-display-flex gl-flex-direction-column gl-sm-flex-direction-row' do - .filter-categories.gl-display-flex.gl-flex-direction-column.gl-md-flex-direction-row.gl-flex-fill-1.gl-flex-wrap.gl-mx-n2 + .filter-categories.gl-display-flex.gl-flex-direction-column.gl-md-flex-direction-row.gl-flex-grow-1.gl-flex-wrap.gl-mx-n2 .filter-item.gl-m-2 - if params[:group_id].present? = hidden_field_tag(:group_id, params[:group_id]) diff --git a/app/views/layouts/fullscreen.html.haml b/app/views/layouts/fullscreen.html.haml index b2536090520..2a865aeda40 100644 --- a/app/views/layouts/fullscreen.html.haml +++ b/app/views/layouts/fullscreen.html.haml @@ -13,5 +13,5 @@ = render "layouts/flash" .content-wrapper.hide-when-top-nav-responsive-open{ id: "content-body", class: "d-flex flex-column align-items-stretch" } = yield - = render "layouts/nav/top_nav_responsive", class: "gl-flex-fill-1 gl-overflow-y-auto" + = render "layouts/nav/top_nav_responsive", class: "gl-flex-grow-1 gl-overflow-y-auto" = footer_message diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml index 365f9fb46fa..027b81d6c68 100644 --- a/app/views/projects/empty.html.haml +++ b/app/views/projects/empty.html.haml @@ -44,6 +44,7 @@ :preserve git clone #{ content_tag(:span, default_url_to_repo, class: 'js-clone')} cd #{h @project.path} + git switch -c #{default_branch_name} touch README.md git add README.md git commit -m "add README" @@ -56,7 +57,7 @@ %pre.bg-light :preserve cd existing_folder - git init + git init --initial-branch=#{default_branch_name} git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'js-clone')} git add . git commit -m "Initial commit" diff --git a/app/views/search/_results.html.haml b/app/views/search/_results.html.haml index d5fbee34fa0..4ba906dd02f 100644 --- a/app/views/search/_results.html.haml +++ b/app/views/search/_results.html.haml @@ -4,7 +4,7 @@ .gl-md-display-flex - if %w(issues merge_requests).include?(@scope) #js-search-sidebar{ class: search_bar_classes } - .gl-w-full.gl-flex-fill-1.gl-overflow-x-hidden + .gl-w-full.gl-flex-grow-1.gl-overflow-x-hidden = render partial: "search/results/empty" = render_if_exists 'shared/promotions/promote_advanced_search' - else @@ -14,7 +14,7 @@ .results.gl-md-display-flex.gl-mt-3 - if %w(issues merge_requests).include?(@scope) #js-search-sidebar{ class: search_bar_classes } - .gl-w-full.gl-flex-fill-1.gl-overflow-x-hidden + .gl-w-full.gl-flex-grow-1.gl-overflow-x-hidden - if @scope == 'commits' %ul.content-list.commit-list = render partial: "search/results/commit", collection: @search_objects diff --git a/app/views/shared/wikis/diff.html.haml b/app/views/shared/wikis/diff.html.haml index 19167f04855..0eeceac28c8 100644 --- a/app/views/shared/wikis/diff.html.haml +++ b/app/views/shared/wikis/diff.html.haml @@ -5,7 +5,7 @@ .wiki-page-header.top-area.has-sidebar-toggle.flex-column.flex-lg-row = wiki_sidebar_toggle_button - %h3.page-title.gl-flex-fill-1 + %h3.page-title.gl-flex-grow-1 = link_to_wiki_page @page %span.light · diff --git a/app/views/shared/wikis/edit.html.haml b/app/views/shared/wikis/edit.html.haml index 4bdeee3996f..729646c2731 100644 --- a/app/views/shared/wikis/edit.html.haml +++ b/app/views/shared/wikis/edit.html.haml @@ -7,7 +7,7 @@ .wiki-page-header.top-area.has-sidebar-toggle.flex-column.flex-lg-row = wiki_sidebar_toggle_button - %h3.page-title.gl-flex-fill-1 + %h3.page-title.gl-flex-grow-1 - if @page.persisted? = link_to_wiki_page @page %span.light diff --git a/app/views/shared/wikis/pages.html.haml b/app/views/shared/wikis/pages.html.haml index 1889b6501c9..c1918198594 100644 --- a/app/views/shared/wikis/pages.html.haml +++ b/app/views/shared/wikis/pages.html.haml @@ -5,7 +5,7 @@ - add_page_specific_style 'page_bundles/wiki' .wiki-page-header.top-area.flex-column.flex-lg-row - %h3.page-title.gl-flex-fill-1 + %h3.page-title.gl-flex-grow-1 = s_("Wiki|Wiki Pages") .nav-controls.pb-md-3.pb-lg-0 diff --git a/config/feature_flags/development/remove_legacy_flags.yml b/config/feature_flags/development/advanced_search_multi_project_select.yml index 68723af2de9..4f38955fa71 100644 --- a/config/feature_flags/development/remove_legacy_flags.yml +++ b/config/feature_flags/development/advanced_search_multi_project_select.yml @@ -1,8 +1,8 @@ --- -name: remove_legacy_flags -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62484 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332243 +name: advanced_search_multi_project_select +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62606 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/333011 milestone: '14.0' type: development -group: group::release +group: group::global search default_enabled: false diff --git a/config/feature_flags/development/feature_flag_api.yml b/config/feature_flags/development/feature_flag_api.yml deleted file mode 100644 index 167b5ff4cf2..00000000000 --- a/config/feature_flags/development/feature_flag_api.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: feature_flag_api -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18198 -rollout_issue_url: -milestone: '12.4' -type: development -group: group::release -default_enabled: false diff --git a/config/feature_flags/development/remove_legacy_flags_override.yml b/config/feature_flags/development/remove_legacy_flags_override.yml deleted file mode 100644 index 17b0ae48505..00000000000 --- a/config/feature_flags/development/remove_legacy_flags_override.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: remove_legacy_flags_override -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62484 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332243 -milestone: '14.0' -type: development -group: group::release -default_enabled: false diff --git a/config/metrics/counts_28d/20210421144352_i_code_review_click_single_file_mode_setting_monthly.yml b/config/metrics/counts_28d/20210421144352_i_code_review_click_single_file_mode_setting_monthly.yml index 2bcd2a448ec..a3d27ec7fd9 100644 --- a/config/metrics/counts_28d/20210421144352_i_code_review_click_single_file_mode_setting_monthly.yml +++ b/config/metrics/counts_28d/20210421144352_i_code_review_click_single_file_mode_setting_monthly.yml @@ -6,7 +6,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979 time_frame: 28d diff --git a/config/metrics/counts_28d/20210421145818_i_code_review_click_file_browser_setting_monthly.yml b/config/metrics/counts_28d/20210421145818_i_code_review_click_file_browser_setting_monthly.yml index 3b7c5be9b84..1bacc4d30dc 100644 --- a/config/metrics/counts_28d/20210421145818_i_code_review_click_file_browser_setting_monthly.yml +++ b/config/metrics/counts_28d/20210421145818_i_code_review_click_file_browser_setting_monthly.yml @@ -6,7 +6,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979 time_frame: 28d diff --git a/config/metrics/counts_28d/20210421145945_i_code_review_click_whitespace_setting_monthly.yml b/config/metrics/counts_28d/20210421145945_i_code_review_click_whitespace_setting_monthly.yml index 31fe497fe0e..b9c7d00b8b3 100644 --- a/config/metrics/counts_28d/20210421145945_i_code_review_click_whitespace_setting_monthly.yml +++ b/config/metrics/counts_28d/20210421145945_i_code_review_click_whitespace_setting_monthly.yml @@ -6,7 +6,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979 time_frame: 28d diff --git a/config/metrics/counts_28d/20210422101516_i_code_review_diff_view_inline_monthly.yml b/config/metrics/counts_28d/20210422101516_i_code_review_diff_view_inline_monthly.yml index 821f7244209..dc7f22008a7 100644 --- a/config/metrics/counts_28d/20210422101516_i_code_review_diff_view_inline_monthly.yml +++ b/config/metrics/counts_28d/20210422101516_i_code_review_diff_view_inline_monthly.yml @@ -6,7 +6,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979 time_frame: 28d diff --git a/config/metrics/counts_28d/20210422101613_i_code_review_diff_view_parallel_monthly.yml b/config/metrics/counts_28d/20210422101613_i_code_review_diff_view_parallel_monthly.yml index 04ff06143af..a6102f8f936 100644 --- a/config/metrics/counts_28d/20210422101613_i_code_review_diff_view_parallel_monthly.yml +++ b/config/metrics/counts_28d/20210422101613_i_code_review_diff_view_parallel_monthly.yml @@ -6,7 +6,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979 time_frame: 28d diff --git a/config/metrics/counts_28d/20210422101753_i_code_review_file_browser_tree_view_monthly.yml b/config/metrics/counts_28d/20210422101753_i_code_review_file_browser_tree_view_monthly.yml index ad5b5e835c1..e8539fa483b 100644 --- a/config/metrics/counts_28d/20210422101753_i_code_review_file_browser_tree_view_monthly.yml +++ b/config/metrics/counts_28d/20210422101753_i_code_review_file_browser_tree_view_monthly.yml @@ -6,7 +6,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979 time_frame: 28d diff --git a/config/metrics/counts_28d/20210422101852_i_code_review_file_browser_list_view_monthly.yml b/config/metrics/counts_28d/20210422101852_i_code_review_file_browser_list_view_monthly.yml index c71bacd6004..b3b1cb0b54e 100644 --- a/config/metrics/counts_28d/20210422101852_i_code_review_file_browser_list_view_monthly.yml +++ b/config/metrics/counts_28d/20210422101852_i_code_review_file_browser_list_view_monthly.yml @@ -6,7 +6,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979 time_frame: 28d diff --git a/config/metrics/counts_28d/20210422101928_i_code_review_diff_show_whitespace_monthly.yml b/config/metrics/counts_28d/20210422101928_i_code_review_diff_show_whitespace_monthly.yml index 0d17fa0d965..006e345f0f0 100644 --- a/config/metrics/counts_28d/20210422101928_i_code_review_diff_show_whitespace_monthly.yml +++ b/config/metrics/counts_28d/20210422101928_i_code_review_diff_show_whitespace_monthly.yml @@ -6,7 +6,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979 time_frame: 28d diff --git a/config/metrics/counts_28d/20210422102010_i_code_review_diff_hide_whitespace_monthly.yml b/config/metrics/counts_28d/20210422102010_i_code_review_diff_hide_whitespace_monthly.yml index 6038bb5cda8..273a98da172 100644 --- a/config/metrics/counts_28d/20210422102010_i_code_review_diff_hide_whitespace_monthly.yml +++ b/config/metrics/counts_28d/20210422102010_i_code_review_diff_hide_whitespace_monthly.yml @@ -6,7 +6,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979 time_frame: 28d diff --git a/config/metrics/counts_28d/20210422102121_i_code_review_diff_single_file_monthly.yml b/config/metrics/counts_28d/20210422102121_i_code_review_diff_single_file_monthly.yml index 3cfcdf23a47..17ce7101133 100644 --- a/config/metrics/counts_28d/20210422102121_i_code_review_diff_single_file_monthly.yml +++ b/config/metrics/counts_28d/20210422102121_i_code_review_diff_single_file_monthly.yml @@ -6,7 +6,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979 time_frame: 28d diff --git a/config/metrics/counts_28d/20210422102202_i_code_review_diff_multiple_files_monthly.yml b/config/metrics/counts_28d/20210422102202_i_code_review_diff_multiple_files_monthly.yml index 16784a0c408..cde5800cf60 100644 --- a/config/metrics/counts_28d/20210422102202_i_code_review_diff_multiple_files_monthly.yml +++ b/config/metrics/counts_28d/20210422102202_i_code_review_diff_multiple_files_monthly.yml @@ -6,7 +6,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979 time_frame: 28d diff --git a/config/metrics/counts_28d/20210427102618_code_review_category_monthly_active_users.yml b/config/metrics/counts_28d/20210427102618_code_review_category_monthly_active_users.yml index 224fd6477cc..53757c27ca2 100644 --- a/config/metrics/counts_28d/20210427102618_code_review_category_monthly_active_users.yml +++ b/config/metrics/counts_28d/20210427102618_code_review_category_monthly_active_users.yml @@ -7,7 +7,7 @@ product_stage: product_group: product_category: value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: time_frame: 28d diff --git a/config/metrics/counts_28d/20210427103010_code_review_extension_category_monthly_active_users.yml b/config/metrics/counts_28d/20210427103010_code_review_extension_category_monthly_active_users.yml index ba872d725df..9d79661bf27 100644 --- a/config/metrics/counts_28d/20210427103010_code_review_extension_category_monthly_active_users.yml +++ b/config/metrics/counts_28d/20210427103010_code_review_extension_category_monthly_active_users.yml @@ -7,7 +7,7 @@ product_stage: product_group: product_category: value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: time_frame: 28d diff --git a/config/metrics/counts_28d/20210427103119_code_review_group_monthly_active_users.yml b/config/metrics/counts_28d/20210427103119_code_review_group_monthly_active_users.yml index e0e6bb0567d..492c50c4838 100644 --- a/config/metrics/counts_28d/20210427103119_code_review_group_monthly_active_users.yml +++ b/config/metrics/counts_28d/20210427103119_code_review_group_monthly_active_users.yml @@ -7,7 +7,7 @@ product_stage: product_group: product_category: value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: time_frame: 28d diff --git a/config/metrics/counts_28d/20210427105033_pipeline_authoring_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210427105033_pipeline_authoring_total_unique_counts_monthly.yml index 594df7ebe26..edd385da9ce 100644 --- a/config/metrics/counts_28d/20210427105033_pipeline_authoring_total_unique_counts_monthly.yml +++ b/config/metrics/counts_28d/20210427105033_pipeline_authoring_total_unique_counts_monthly.yml @@ -7,7 +7,7 @@ product_stage: product_group: product_category: value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: time_frame: 28d diff --git a/config/metrics/counts_28d/20210427213346_geo_secondary_web_oauth_users.yml b/config/metrics/counts_28d/20210427213346_geo_secondary_web_oauth_users.yml index 0f68989cc1d..dc08952bb18 100644 --- a/config/metrics/counts_28d/20210427213346_geo_secondary_web_oauth_users.yml +++ b/config/metrics/counts_28d/20210427213346_geo_secondary_web_oauth_users.yml @@ -7,7 +7,7 @@ product_stage: product_group: product_category: value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: time_frame: 28d diff --git a/config/metrics/counts_28d/20210514013545_i_code_review_user_resolve_conflict_monthly.yml b/config/metrics/counts_28d/20210514013545_i_code_review_user_resolve_conflict_monthly.yml index 2a39317f76c..c685e277215 100644 --- a/config/metrics/counts_28d/20210514013545_i_code_review_user_resolve_conflict_monthly.yml +++ b/config/metrics/counts_28d/20210514013545_i_code_review_user_resolve_conflict_monthly.yml @@ -7,7 +7,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: "13.12" time_frame: 28d data_source: redis_hll diff --git a/config/metrics/counts_28d/20210514013549_i_code_review_user_load_conflict_ui_monthly.yml b/config/metrics/counts_28d/20210514013549_i_code_review_user_load_conflict_ui_monthly.yml index f031fb33c88..e421203a195 100644 --- a/config/metrics/counts_28d/20210514013549_i_code_review_user_load_conflict_ui_monthly.yml +++ b/config/metrics/counts_28d/20210514013549_i_code_review_user_load_conflict_ui_monthly.yml @@ -7,7 +7,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: "13.12" time_frame: 28d data_source: redis_hll diff --git a/config/metrics/counts_28d/20210607113556_i_code_review_click_diff_view_setting_monthly.yml b/config/metrics/counts_28d/20210607113556_i_code_review_click_diff_view_setting_monthly.yml index b172f85dc1f..04edbaf1ec1 100644 --- a/config/metrics/counts_28d/20210607113556_i_code_review_click_diff_view_setting_monthly.yml +++ b/config/metrics/counts_28d/20210607113556_i_code_review_click_diff_view_setting_monthly.yml @@ -6,7 +6,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979 time_frame: 28d diff --git a/config/metrics/counts_7d/20210421144349_i_code_review_click_single_file_mode_setting_weekly.yml b/config/metrics/counts_7d/20210421144349_i_code_review_click_single_file_mode_setting_weekly.yml index 179d2fa6e47..050ca64f03c 100644 --- a/config/metrics/counts_7d/20210421144349_i_code_review_click_single_file_mode_setting_weekly.yml +++ b/config/metrics/counts_7d/20210421144349_i_code_review_click_single_file_mode_setting_weekly.yml @@ -6,7 +6,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979 time_frame: 7d diff --git a/config/metrics/counts_7d/20210421145814_i_code_review_click_file_browser_setting_weekly.yml b/config/metrics/counts_7d/20210421145814_i_code_review_click_file_browser_setting_weekly.yml index 50264bf27cf..eb73d4841b4 100644 --- a/config/metrics/counts_7d/20210421145814_i_code_review_click_file_browser_setting_weekly.yml +++ b/config/metrics/counts_7d/20210421145814_i_code_review_click_file_browser_setting_weekly.yml @@ -6,7 +6,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979 time_frame: 7d diff --git a/config/metrics/counts_7d/20210421145942_i_code_review_click_whitespace_setting_weekly.yml b/config/metrics/counts_7d/20210421145942_i_code_review_click_whitespace_setting_weekly.yml index 3206bac8b49..4159716f919 100644 --- a/config/metrics/counts_7d/20210421145942_i_code_review_click_whitespace_setting_weekly.yml +++ b/config/metrics/counts_7d/20210421145942_i_code_review_click_whitespace_setting_weekly.yml @@ -6,7 +6,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979 time_frame: 7d diff --git a/config/metrics/counts_7d/20210422101512_i_code_review_diff_view_inline_weekly.yml b/config/metrics/counts_7d/20210422101512_i_code_review_diff_view_inline_weekly.yml index 7a3a606c886..0c53c7733b1 100644 --- a/config/metrics/counts_7d/20210422101512_i_code_review_diff_view_inline_weekly.yml +++ b/config/metrics/counts_7d/20210422101512_i_code_review_diff_view_inline_weekly.yml @@ -6,7 +6,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979 time_frame: 7d diff --git a/config/metrics/counts_7d/20210422101609_i_code_review_diff_view_parallel_weekly.yml b/config/metrics/counts_7d/20210422101609_i_code_review_diff_view_parallel_weekly.yml index 36dbeae82e7..3d956eea357 100644 --- a/config/metrics/counts_7d/20210422101609_i_code_review_diff_view_parallel_weekly.yml +++ b/config/metrics/counts_7d/20210422101609_i_code_review_diff_view_parallel_weekly.yml @@ -6,7 +6,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979 time_frame: 7d diff --git a/config/metrics/counts_7d/20210422101750_i_code_review_file_browser_tree_view_weekly.yml b/config/metrics/counts_7d/20210422101750_i_code_review_file_browser_tree_view_weekly.yml index ef74ff6613f..97067bcc02f 100644 --- a/config/metrics/counts_7d/20210422101750_i_code_review_file_browser_tree_view_weekly.yml +++ b/config/metrics/counts_7d/20210422101750_i_code_review_file_browser_tree_view_weekly.yml @@ -6,7 +6,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979 time_frame: 7d diff --git a/config/metrics/counts_7d/20210422101849_i_code_review_file_browser_list_view_weekly.yml b/config/metrics/counts_7d/20210422101849_i_code_review_file_browser_list_view_weekly.yml index e2b9f141bb7..094d2ee6ce8 100644 --- a/config/metrics/counts_7d/20210422101849_i_code_review_file_browser_list_view_weekly.yml +++ b/config/metrics/counts_7d/20210422101849_i_code_review_file_browser_list_view_weekly.yml @@ -6,7 +6,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979 time_frame: 7d diff --git a/config/metrics/counts_7d/20210422101925_i_code_review_diff_show_whitespace_weekly.yml b/config/metrics/counts_7d/20210422101925_i_code_review_diff_show_whitespace_weekly.yml index 6cca3840faa..c58b03ce909 100644 --- a/config/metrics/counts_7d/20210422101925_i_code_review_diff_show_whitespace_weekly.yml +++ b/config/metrics/counts_7d/20210422101925_i_code_review_diff_show_whitespace_weekly.yml @@ -6,7 +6,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979 time_frame: 7d diff --git a/config/metrics/counts_7d/20210422102007_i_code_review_diff_hide_whitespace_weekly.yml b/config/metrics/counts_7d/20210422102007_i_code_review_diff_hide_whitespace_weekly.yml index c1fccc9f774..b0a04b9bff5 100644 --- a/config/metrics/counts_7d/20210422102007_i_code_review_diff_hide_whitespace_weekly.yml +++ b/config/metrics/counts_7d/20210422102007_i_code_review_diff_hide_whitespace_weekly.yml @@ -6,7 +6,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979 time_frame: 7d diff --git a/config/metrics/counts_7d/20210422102118_i_code_review_diff_single_file_weekly.yml b/config/metrics/counts_7d/20210422102118_i_code_review_diff_single_file_weekly.yml index 3b1abf6e0e1..64f3f452d79 100644 --- a/config/metrics/counts_7d/20210422102118_i_code_review_diff_single_file_weekly.yml +++ b/config/metrics/counts_7d/20210422102118_i_code_review_diff_single_file_weekly.yml @@ -6,7 +6,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979 time_frame: 7d diff --git a/config/metrics/counts_7d/20210422102159_i_code_review_diff_multiple_files_weekly.yml b/config/metrics/counts_7d/20210422102159_i_code_review_diff_multiple_files_weekly.yml index b3105b041f8..fe0bd0ba906 100644 --- a/config/metrics/counts_7d/20210422102159_i_code_review_diff_multiple_files_weekly.yml +++ b/config/metrics/counts_7d/20210422102159_i_code_review_diff_multiple_files_weekly.yml @@ -6,7 +6,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979 time_frame: 7d diff --git a/config/metrics/counts_7d/20210427103328_code_review_group_monthly_active_users.yml b/config/metrics/counts_7d/20210427103328_code_review_group_monthly_active_users.yml index 31b36bc8ad7..eb1a803ad08 100644 --- a/config/metrics/counts_7d/20210427103328_code_review_group_monthly_active_users.yml +++ b/config/metrics/counts_7d/20210427103328_code_review_group_monthly_active_users.yml @@ -7,7 +7,7 @@ product_stage: product_group: product_category: value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: time_frame: 7d diff --git a/config/metrics/counts_7d/20210427103407_code_review_category_monthly_active_users.yml b/config/metrics/counts_7d/20210427103407_code_review_category_monthly_active_users.yml index aaf9350cdaa..efed507fca3 100644 --- a/config/metrics/counts_7d/20210427103407_code_review_category_monthly_active_users.yml +++ b/config/metrics/counts_7d/20210427103407_code_review_category_monthly_active_users.yml @@ -7,7 +7,7 @@ product_stage: product_group: product_category: value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: time_frame: 7d diff --git a/config/metrics/counts_7d/20210427103452_code_review_extension_category_monthly_active_users.yml b/config/metrics/counts_7d/20210427103452_code_review_extension_category_monthly_active_users.yml index ded67e19e10..0452b4a418b 100644 --- a/config/metrics/counts_7d/20210427103452_code_review_extension_category_monthly_active_users.yml +++ b/config/metrics/counts_7d/20210427103452_code_review_extension_category_monthly_active_users.yml @@ -7,7 +7,7 @@ product_stage: product_group: product_category: value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: time_frame: 7d diff --git a/config/metrics/counts_7d/20210427105030_pipeline_authoring_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210427105030_pipeline_authoring_total_unique_counts_weekly.yml index 7f782d90f8d..da3b2f7bccd 100644 --- a/config/metrics/counts_7d/20210427105030_pipeline_authoring_total_unique_counts_weekly.yml +++ b/config/metrics/counts_7d/20210427105030_pipeline_authoring_total_unique_counts_weekly.yml @@ -7,7 +7,7 @@ product_stage: product_group: product_category: value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: time_frame: 7d diff --git a/config/metrics/counts_7d/20210514013544_i_code_review_user_load_conflict_ui_weekly.yml b/config/metrics/counts_7d/20210514013544_i_code_review_user_load_conflict_ui_weekly.yml index 0a2410b9ed5..0ab87e2917e 100644 --- a/config/metrics/counts_7d/20210514013544_i_code_review_user_load_conflict_ui_weekly.yml +++ b/config/metrics/counts_7d/20210514013544_i_code_review_user_load_conflict_ui_weekly.yml @@ -7,7 +7,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: "13.12" time_frame: 7d data_source: redis_hll diff --git a/config/metrics/counts_7d/20210514013545_i_code_review_user_resolve_conflict_weekly.yml b/config/metrics/counts_7d/20210514013545_i_code_review_user_resolve_conflict_weekly.yml index 4ea6c847c49..417483200e3 100644 --- a/config/metrics/counts_7d/20210514013545_i_code_review_user_resolve_conflict_weekly.yml +++ b/config/metrics/counts_7d/20210514013545_i_code_review_user_resolve_conflict_weekly.yml @@ -7,7 +7,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: "13.12" time_frame: 28d data_source: redis_hll diff --git a/config/metrics/counts_7d/20210607113552_i_code_review_click_diff_view_setting_weekly.yml b/config/metrics/counts_7d/20210607113552_i_code_review_click_diff_view_setting_weekly.yml index 1770980aa3a..6d7f47cede4 100644 --- a/config/metrics/counts_7d/20210607113552_i_code_review_click_diff_view_setting_weekly.yml +++ b/config/metrics/counts_7d/20210607113552_i_code_review_click_diff_view_setting_weekly.yml @@ -6,7 +6,7 @@ product_stage: create product_group: group::code review product_category: code_review value_type: number -status: implemented +status: data_available milestone: '13.12' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59979 time_frame: 7d diff --git a/config/metrics/counts_all/20210423005644_i_analytics_dev_ops_adoption.yml b/config/metrics/counts_all/20210423005644_i_analytics_dev_ops_adoption.yml index 54dffb5573a..25b6c0f4e93 100644 --- a/config/metrics/counts_all/20210423005644_i_analytics_dev_ops_adoption.yml +++ b/config/metrics/counts_all/20210423005644_i_analytics_dev_ops_adoption.yml @@ -7,7 +7,7 @@ product_stage: product_group: product_category: value_type: number -status: implemented +status: data_available milestone: "13.11" introduced_by_url: time_frame: all diff --git a/config/metrics/counts_all/20210427212450_geo_secondary_web_oauth_users.yml b/config/metrics/counts_all/20210427212450_geo_secondary_web_oauth_users.yml index 0ce05fb84e2..d1a818fe3e1 100644 --- a/config/metrics/counts_all/20210427212450_geo_secondary_web_oauth_users.yml +++ b/config/metrics/counts_all/20210427212450_geo_secondary_web_oauth_users.yml @@ -7,7 +7,7 @@ product_stage: product_group: product_category: value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: time_frame: all diff --git a/config/metrics/counts_all/20210428142406_users_viewing_analytics_group_devops_adoption.yml b/config/metrics/counts_all/20210428142406_users_viewing_analytics_group_devops_adoption.yml index c3fb808541a..2a6a56a1f5a 100644 --- a/config/metrics/counts_all/20210428142406_users_viewing_analytics_group_devops_adoption.yml +++ b/config/metrics/counts_all/20210428142406_users_viewing_analytics_group_devops_adoption.yml @@ -7,7 +7,7 @@ product_stage: product_group: product_category: value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: time_frame: all diff --git a/config/metrics/counts_all/20210502045402_ci_runners_instance_type_active.yml b/config/metrics/counts_all/20210502045402_ci_runners_instance_type_active.yml index 425869d5a81..f66bb2c85c9 100644 --- a/config/metrics/counts_all/20210502045402_ci_runners_instance_type_active.yml +++ b/config/metrics/counts_all/20210502045402_ci_runners_instance_type_active.yml @@ -7,7 +7,7 @@ product_stage: verify product_group: group::pipeline execution product_category: continuous_integration value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58197 time_frame: all diff --git a/config/metrics/counts_all/20210502050341_ci_runners_group_type_active.yml b/config/metrics/counts_all/20210502050341_ci_runners_group_type_active.yml index 7896738aab6..c6abe0905a4 100644 --- a/config/metrics/counts_all/20210502050341_ci_runners_group_type_active.yml +++ b/config/metrics/counts_all/20210502050341_ci_runners_group_type_active.yml @@ -7,7 +7,7 @@ product_stage: verify product_group: group::pipeline execution product_category: continuous_integration value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58197 time_frame: all diff --git a/config/metrics/counts_all/20210502050834_ci_runners_project_type_active.yml b/config/metrics/counts_all/20210502050834_ci_runners_project_type_active.yml index 94d4956899d..fda2b529b30 100644 --- a/config/metrics/counts_all/20210502050834_ci_runners_project_type_active.yml +++ b/config/metrics/counts_all/20210502050834_ci_runners_project_type_active.yml @@ -7,7 +7,7 @@ product_stage: verify product_group: group::pipeline execution product_category: continuous_integration value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58197 time_frame: all diff --git a/config/metrics/counts_all/20210502050942_ci_runners_online.yml b/config/metrics/counts_all/20210502050942_ci_runners_online.yml index 8922524c4c2..201ffaeb415 100644 --- a/config/metrics/counts_all/20210502050942_ci_runners_online.yml +++ b/config/metrics/counts_all/20210502050942_ci_runners_online.yml @@ -7,7 +7,7 @@ product_stage: verify product_group: group::pipeline execution product_category: continuous_integration value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58197 time_frame: all diff --git a/config/metrics/counts_all/20210502051651_ci_runners_instance_type_active_online.yml b/config/metrics/counts_all/20210502051651_ci_runners_instance_type_active_online.yml index 04f9bc3e762..920ec24e9e7 100644 --- a/config/metrics/counts_all/20210502051651_ci_runners_instance_type_active_online.yml +++ b/config/metrics/counts_all/20210502051651_ci_runners_instance_type_active_online.yml @@ -7,7 +7,7 @@ product_stage: verify product_group: group::pipeline execution product_category: continuous_integration value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58197 time_frame: all diff --git a/config/metrics/counts_all/20210502051922_ci_runners_group_type_active_online.yml b/config/metrics/counts_all/20210502051922_ci_runners_group_type_active_online.yml index 9c24740eca1..e88530d97c8 100644 --- a/config/metrics/counts_all/20210502051922_ci_runners_group_type_active_online.yml +++ b/config/metrics/counts_all/20210502051922_ci_runners_group_type_active_online.yml @@ -7,7 +7,7 @@ product_stage: verify product_group: group::pipeline execution product_category: continuous_integration value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58197 time_frame: all diff --git a/config/metrics/counts_all/20210502052036_ci_runners_project_type_active_online.yml b/config/metrics/counts_all/20210502052036_ci_runners_project_type_active_online.yml index 64c39337be2..7ce3ee6ce8b 100644 --- a/config/metrics/counts_all/20210502052036_ci_runners_project_type_active_online.yml +++ b/config/metrics/counts_all/20210502052036_ci_runners_project_type_active_online.yml @@ -7,7 +7,7 @@ product_stage: verify product_group: group::pipeline execution product_category: continuous_integration value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58197 time_frame: all diff --git a/config/metrics/counts_all/20210510201537_in_product_marketing_email_create_0_sent.yml b/config/metrics/counts_all/20210510201537_in_product_marketing_email_create_0_sent.yml index bbfae3eb114..52dd38bab8d 100644 --- a/config/metrics/counts_all/20210510201537_in_product_marketing_email_create_0_sent.yml +++ b/config/metrics/counts_all/20210510201537_in_product_marketing_email_create_0_sent.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all diff --git a/config/metrics/counts_all/20210510201919_in_product_marketing_email_create_0_cta_clicked.yml b/config/metrics/counts_all/20210510201919_in_product_marketing_email_create_0_cta_clicked.yml index a2cf7c6d813..65440e73542 100644 --- a/config/metrics/counts_all/20210510201919_in_product_marketing_email_create_0_cta_clicked.yml +++ b/config/metrics/counts_all/20210510201919_in_product_marketing_email_create_0_cta_clicked.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all diff --git a/config/metrics/counts_all/20210510202148_in_product_marketing_email_create_1_sent.yml b/config/metrics/counts_all/20210510202148_in_product_marketing_email_create_1_sent.yml index 85552f42431..3701f0a3ba3 100644 --- a/config/metrics/counts_all/20210510202148_in_product_marketing_email_create_1_sent.yml +++ b/config/metrics/counts_all/20210510202148_in_product_marketing_email_create_1_sent.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all diff --git a/config/metrics/counts_all/20210510202356_in_product_marketing_email_create_1_cta_clicked.yml b/config/metrics/counts_all/20210510202356_in_product_marketing_email_create_1_cta_clicked.yml index 7a1e5f28c22..70c0257481d 100644 --- a/config/metrics/counts_all/20210510202356_in_product_marketing_email_create_1_cta_clicked.yml +++ b/config/metrics/counts_all/20210510202356_in_product_marketing_email_create_1_cta_clicked.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all diff --git a/config/metrics/counts_all/20210510202604_in_product_marketing_email_create_2_sent.yml b/config/metrics/counts_all/20210510202604_in_product_marketing_email_create_2_sent.yml index 02d5ae115bb..8d8eb4630d3 100644 --- a/config/metrics/counts_all/20210510202604_in_product_marketing_email_create_2_sent.yml +++ b/config/metrics/counts_all/20210510202604_in_product_marketing_email_create_2_sent.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all diff --git a/config/metrics/counts_all/20210510202724_in_product_marketing_email_create_2_cta_clicked.yml b/config/metrics/counts_all/20210510202724_in_product_marketing_email_create_2_cta_clicked.yml index 75eafa3a54f..965efa41883 100644 --- a/config/metrics/counts_all/20210510202724_in_product_marketing_email_create_2_cta_clicked.yml +++ b/config/metrics/counts_all/20210510202724_in_product_marketing_email_create_2_cta_clicked.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all diff --git a/config/metrics/counts_all/20210510202807_in_product_marketing_email_verify_0_sent.yml b/config/metrics/counts_all/20210510202807_in_product_marketing_email_verify_0_sent.yml index 0a5a9ef936f..2e5bbc29d2c 100644 --- a/config/metrics/counts_all/20210510202807_in_product_marketing_email_verify_0_sent.yml +++ b/config/metrics/counts_all/20210510202807_in_product_marketing_email_verify_0_sent.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all diff --git a/config/metrics/counts_all/20210510202943_in_product_marketing_email_verify_0_cta_clicked.yml b/config/metrics/counts_all/20210510202943_in_product_marketing_email_verify_0_cta_clicked.yml index 17e677ba29d..23ed471a295 100644 --- a/config/metrics/counts_all/20210510202943_in_product_marketing_email_verify_0_cta_clicked.yml +++ b/config/metrics/counts_all/20210510202943_in_product_marketing_email_verify_0_cta_clicked.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all diff --git a/config/metrics/counts_all/20210510202955_in_product_marketing_email_verify_1_sent.yml b/config/metrics/counts_all/20210510202955_in_product_marketing_email_verify_1_sent.yml index 2bad6d31db2..992b39fbd1c 100644 --- a/config/metrics/counts_all/20210510202955_in_product_marketing_email_verify_1_sent.yml +++ b/config/metrics/counts_all/20210510202955_in_product_marketing_email_verify_1_sent.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all diff --git a/config/metrics/counts_all/20210510203005_in_product_marketing_email_verify_1_cta_clicked.yml b/config/metrics/counts_all/20210510203005_in_product_marketing_email_verify_1_cta_clicked.yml index 66080d46e7f..bd9378867e6 100644 --- a/config/metrics/counts_all/20210510203005_in_product_marketing_email_verify_1_cta_clicked.yml +++ b/config/metrics/counts_all/20210510203005_in_product_marketing_email_verify_1_cta_clicked.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all diff --git a/config/metrics/counts_all/20210510203015_in_product_marketing_email_verify_2_sent.yml b/config/metrics/counts_all/20210510203015_in_product_marketing_email_verify_2_sent.yml index 2beabb8b007..5b74bfd8d8c 100644 --- a/config/metrics/counts_all/20210510203015_in_product_marketing_email_verify_2_sent.yml +++ b/config/metrics/counts_all/20210510203015_in_product_marketing_email_verify_2_sent.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all diff --git a/config/metrics/counts_all/20210510203025_in_product_marketing_email_verify_2_cta_clicked.yml b/config/metrics/counts_all/20210510203025_in_product_marketing_email_verify_2_cta_clicked.yml index 7213c463fa9..e30f41d003a 100644 --- a/config/metrics/counts_all/20210510203025_in_product_marketing_email_verify_2_cta_clicked.yml +++ b/config/metrics/counts_all/20210510203025_in_product_marketing_email_verify_2_cta_clicked.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all diff --git a/config/metrics/counts_all/20210510203035_in_product_marketing_email_trial_0_sent.yml b/config/metrics/counts_all/20210510203035_in_product_marketing_email_trial_0_sent.yml index dc566f03898..555c0f1e47f 100644 --- a/config/metrics/counts_all/20210510203035_in_product_marketing_email_trial_0_sent.yml +++ b/config/metrics/counts_all/20210510203035_in_product_marketing_email_trial_0_sent.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all diff --git a/config/metrics/counts_all/20210510203044_in_product_marketing_email_trial_0_cta_clicked.yml b/config/metrics/counts_all/20210510203044_in_product_marketing_email_trial_0_cta_clicked.yml index a3cf714e5ad..23d8a6be343 100644 --- a/config/metrics/counts_all/20210510203044_in_product_marketing_email_trial_0_cta_clicked.yml +++ b/config/metrics/counts_all/20210510203044_in_product_marketing_email_trial_0_cta_clicked.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all diff --git a/config/metrics/counts_all/20210510203054_in_product_marketing_email_trial_1_sent.yml b/config/metrics/counts_all/20210510203054_in_product_marketing_email_trial_1_sent.yml index f5215090b7e..794eaaf01c8 100644 --- a/config/metrics/counts_all/20210510203054_in_product_marketing_email_trial_1_sent.yml +++ b/config/metrics/counts_all/20210510203054_in_product_marketing_email_trial_1_sent.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all diff --git a/config/metrics/counts_all/20210510203104_in_product_marketing_email_trial_1_cta_clicked.yml b/config/metrics/counts_all/20210510203104_in_product_marketing_email_trial_1_cta_clicked.yml index 651c5426e2a..d8172d035b3 100644 --- a/config/metrics/counts_all/20210510203104_in_product_marketing_email_trial_1_cta_clicked.yml +++ b/config/metrics/counts_all/20210510203104_in_product_marketing_email_trial_1_cta_clicked.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all diff --git a/config/metrics/counts_all/20210510203114_in_product_marketing_email_trial_2_sent.yml b/config/metrics/counts_all/20210510203114_in_product_marketing_email_trial_2_sent.yml index 4be98d45ce2..f781a32cd65 100644 --- a/config/metrics/counts_all/20210510203114_in_product_marketing_email_trial_2_sent.yml +++ b/config/metrics/counts_all/20210510203114_in_product_marketing_email_trial_2_sent.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all diff --git a/config/metrics/counts_all/20210510203124_in_product_marketing_email_trial_2_cta_clicked.yml b/config/metrics/counts_all/20210510203124_in_product_marketing_email_trial_2_cta_clicked.yml index 6be928da906..a79425144ac 100644 --- a/config/metrics/counts_all/20210510203124_in_product_marketing_email_trial_2_cta_clicked.yml +++ b/config/metrics/counts_all/20210510203124_in_product_marketing_email_trial_2_cta_clicked.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all diff --git a/config/metrics/counts_all/20210510203134_in_product_marketing_email_team_0_sent.yml b/config/metrics/counts_all/20210510203134_in_product_marketing_email_team_0_sent.yml index ac9ffa730f1..d84f9b6d794 100644 --- a/config/metrics/counts_all/20210510203134_in_product_marketing_email_team_0_sent.yml +++ b/config/metrics/counts_all/20210510203134_in_product_marketing_email_team_0_sent.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all diff --git a/config/metrics/counts_all/20210510203143_in_product_marketing_email_team_0_cta_clicked.yml b/config/metrics/counts_all/20210510203143_in_product_marketing_email_team_0_cta_clicked.yml index cf51512c6eb..35a9797f2fe 100644 --- a/config/metrics/counts_all/20210510203143_in_product_marketing_email_team_0_cta_clicked.yml +++ b/config/metrics/counts_all/20210510203143_in_product_marketing_email_team_0_cta_clicked.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all diff --git a/config/metrics/counts_all/20210510203153_in_product_marketing_email_team_1_sent.yml b/config/metrics/counts_all/20210510203153_in_product_marketing_email_team_1_sent.yml index b860b08e391..79c2b1362c0 100644 --- a/config/metrics/counts_all/20210510203153_in_product_marketing_email_team_1_sent.yml +++ b/config/metrics/counts_all/20210510203153_in_product_marketing_email_team_1_sent.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all diff --git a/config/metrics/counts_all/20210510203203_in_product_marketing_email_team_1_cta_clicked.yml b/config/metrics/counts_all/20210510203203_in_product_marketing_email_team_1_cta_clicked.yml index c0f63cadbf2..b4e08bd5d90 100644 --- a/config/metrics/counts_all/20210510203203_in_product_marketing_email_team_1_cta_clicked.yml +++ b/config/metrics/counts_all/20210510203203_in_product_marketing_email_team_1_cta_clicked.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all diff --git a/config/metrics/counts_all/20210510203213_in_product_marketing_email_team_2_sent.yml b/config/metrics/counts_all/20210510203213_in_product_marketing_email_team_2_sent.yml index 887334c65c7..175c7171dba 100644 --- a/config/metrics/counts_all/20210510203213_in_product_marketing_email_team_2_sent.yml +++ b/config/metrics/counts_all/20210510203213_in_product_marketing_email_team_2_sent.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all diff --git a/config/metrics/counts_all/20210510203223_in_product_marketing_email_team_2_cta_clicked.yml b/config/metrics/counts_all/20210510203223_in_product_marketing_email_team_2_cta_clicked.yml index 6dac2db454a..d6ec214b836 100644 --- a/config/metrics/counts_all/20210510203223_in_product_marketing_email_team_2_cta_clicked.yml +++ b/config/metrics/counts_all/20210510203223_in_product_marketing_email_team_2_cta_clicked.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752 time_frame: all diff --git a/config/metrics/counts_all/20210518081225_in_product_marketing_email_experience_0_sent.yml b/config/metrics/counts_all/20210518081225_in_product_marketing_email_experience_0_sent.yml index 816fee89f4c..f8a2b99b87e 100644 --- a/config/metrics/counts_all/20210518081225_in_product_marketing_email_experience_0_sent.yml +++ b/config/metrics/counts_all/20210518081225_in_product_marketing_email_experience_0_sent.yml @@ -7,7 +7,7 @@ product_stage: growth product_group: group::activation product_category: onboarding value_type: number -status: implemented +status: data_available milestone: "13.12" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61347 time_frame: all diff --git a/config/metrics/schema.json b/config/metrics/schema.json index 300a56a0b94..476e292e5c0 100644 --- a/config/metrics/schema.json +++ b/config/metrics/schema.json @@ -57,6 +57,10 @@ "type": "string", "enum": ["database", "redis", "redis_hll", "prometheus", "system", "license"] }, + "data_category": { + "type": "string", + "enum": ["Operational", "Optional", "Subscription", "Standard"] + }, "instrumentation_class": { "type": "string", "pattern": "^(([A-Z][a-z]+)+::)*(([A-Z]+[a-z]+)+)$" diff --git a/danger/commit_messages/Dangerfile b/danger/commit_messages/Dangerfile deleted file mode 100644 index ac3d41adcf4..00000000000 --- a/danger/commit_messages/Dangerfile +++ /dev/null @@ -1,147 +0,0 @@ -# frozen_string_literal: true - -require 'gitlab/dangerfiles/commit_linter' -require 'gitlab/dangerfiles/merge_request_linter' - -COMMIT_MESSAGE_GUIDELINES = "https://docs.gitlab.com/ee/development/contributing/merge_request_workflow.html#commit-messages-guidelines" -MORE_INFO = "For more information, take a look at our [Commit message guidelines](#{COMMIT_MESSAGE_GUIDELINES})." -THE_DANGER_JOB_TEXT = "the `danger-review` job" -MAX_COMMITS_COUNT = 10 -MAX_COMMITS_COUNT_EXCEEDED_MESSAGE = <<~MSG -This merge request includes more than %<max_commits_count>d commits. Each commit should meet the following criteria: - -1. Have a well-written commit message. -1. Has all tests passing when used on its own (e.g. when using git checkout SHA). -1. Can be reverted on its own without also requiring the revert of commit that came before it. -1. Is small enough that it can be reviewed in isolation in under 30 minutes or so. - -If this merge request contains commits that do not meet this criteria and/or contains intermediate work, please rebase these commits into a smaller number of commits or split this merge request into multiple smaller merge requests. -MSG - -def fail_commit(commit, message, more_info: true) - self.fail(build_message(commit, message, more_info: more_info)) -end - -def warn_commit(commit, message, more_info: true) - self.warn(build_message(commit, message, more_info: more_info)) -end - -def build_message(commit, message, more_info: true) - [message].tap do |full_message| - full_message << ". #{MORE_INFO}" if more_info - full_message.unshift("#{commit.sha}: ") if commit.sha - end.join -end - -def squash_mr? - # Locally, we assume the MR is set to be squashed so that the user only sees warnings instead of errors. - helper.ci? ? gitlab.mr_json['squash'] : true -end - -def wip_mr? - helper.ci? ? gitlab.mr_json['work_in_progress'] : false -end - -def danger_job_link - helper.ci? ? "[#{THE_DANGER_JOB_TEXT}](#{ENV['CI_JOB_URL']})" : THE_DANGER_JOB_TEXT -end - -# Perform various checks against commits. We're not using -# https://github.com/jonallured/danger-commit_lint because its output is not -# very helpful, and it doesn't offer the means of ignoring merge commits. -def lint_commit(commit) - linter = Gitlab::Dangerfiles::CommitLinter.new(commit) - - # For now we'll ignore merge commits, as getting rid of those is a problem - # separate from enforcing good commit messages. - return linter if linter.merge? - - # We ignore revert commits as they are well structured by Git already - return linter if linter.revert? - - # If MR is set to squash, we ignore fixup commits - return linter if linter.fixup? && squash_mr? - - if linter.fixup? - msg = "Squash or fixup commits must be squashed before merge, or enable squash merge option and re-run #{danger_job_link}." - if wip_mr? || squash_mr? - warn_commit(commit, msg, more_info: false) - else - fail_commit(commit, msg, more_info: false) - end - - # Makes no sense to process other rules for fixup commits, they trigger just more noise - return linter - end - - # Fail if a suggestion commit is used and squash is not enabled - if linter.suggestion? - unless squash_mr? - fail_commit(commit, "If you are applying suggestions, enable squash in the merge request and re-run #{danger_job_link}.", more_info: false) - end - - return linter - end - - linter.lint -end - -def lint_mr_title(mr_title) - commit = Struct.new(:message, :sha).new(mr_title) - - Gitlab::Dangerfiles::MergeRequestLinter.new(commit).lint -end - -def count_non_fixup_commits(commit_linters) - commit_linters.count { |commit_linter| !commit_linter.fixup? } -end - -def lint_commits(commits) - commit_linters = commits.map { |commit| lint_commit(commit) } - - if squash_mr? - multi_line_commit_linter = commit_linters.detect { |commit_linter| !commit_linter.merge? && commit_linter.multi_line? } - - if multi_line_commit_linter && multi_line_commit_linter.failed? - warn_or_fail_commits(multi_line_commit_linter) - commit_linters.delete(multi_line_commit_linter) # Don't show an error (here) and a warning (below) - elsif helper.ci? # We don't have access to the MR title locally - title_linter = lint_mr_title(gitlab.mr_json['title']) - if title_linter.failed? - warn_or_fail_commits(title_linter) - end - end - else - if count_non_fixup_commits(commit_linters) > MAX_COMMITS_COUNT - self.warn(format(MAX_COMMITS_COUNT_EXCEEDED_MESSAGE, max_commits_count: MAX_COMMITS_COUNT)) - end - end - - failed_commit_linters = commit_linters.select { |commit_linter| commit_linter.failed? } - warn_or_fail_commits(failed_commit_linters, default_to_fail: !squash_mr?) -end - -def warn_or_fail_commits(failed_linters, default_to_fail: true) - level = default_to_fail ? :fail : :warn - - Array(failed_linters).each do |linter| - linter.problems.each do |problem_key, problem_desc| - case problem_key - when :subject_too_short, :subject_above_warning, :details_too_many_changes, :details_line_too_long - warn_commit(linter.commit, problem_desc) - else - self.__send__("#{level}_commit", linter.commit, problem_desc) # rubocop:disable GitlabSecurity/PublicSend - end - end - end -end - -# As part of https://gitlab.com/groups/gitlab-org/-/epics/4826 we are -# vendoring workhorse commits from the stand-alone gitlab-workhorse -# repo. There is no point in linting commits that we want to vendor as -# is. -def workhorse_changes? - git.diff.any? { |file| file.path.start_with?('workhorse/') } -end - -lint_commits(git.commits) unless workhorse_changes? diff --git a/doc/api/deployments.md b/doc/api/deployments.md index b7aa7e12e16..586f3edf51e 100644 --- a/doc/api/deployments.md +++ b/doc/api/deployments.md @@ -9,6 +9,9 @@ type: concepts, howto ## List project deployments +> The `updated_after` and `updated_before` attributes were removed and replaced + by `finished_after` and `finished_before` respectively in GitLab 14.0. + Get a list of deployments in a project. ```plaintext @@ -17,27 +20,19 @@ GET /projects/:id/deployments | Attribute | Type | Required | Description | |------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------| -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | -| `order_by` | string | no | Return deployments ordered by `id` or `iid` or `created_at` or `updated_at` or `ref` fields. Default is `id` | -| `sort` | string | no | Return deployments sorted in `asc` or `desc` order. Default is `asc` | -| `updated_after` | datetime | no | Return deployments updated after the specified date. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | -| `updated_before` | datetime | no | Return deployments updated before the specified date. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | -| `environment` | string | no | The [name of the environment](../ci/environments/index.md) to filter deployments by | -| `status` | string | no | The status to filter deployments by | - -The status attribute can be one of the following values: - -- created -- running -- success -- failed -- canceled +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `order_by` | string | no | Return deployments ordered by either one of `id`, `iid`, `created_at`, `updated_at` or `ref` fields. Default is `id`. | +| `sort` | string | no | Return deployments sorted in `asc` or `desc` order. Default is `asc`. | +| `finished_after` | datetime | no | Return deployments updated after the specified date. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | +| `finished_before` | datetime | no | Return deployments updated before the specified date. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | +| `environment` | string | no | The [name of the environment](../ci/environments/index.md) to filter deployments by. | +| `status` | string | no | The status to filter deployments by. One of `created`, `running`, `success`, `failed`, `canceled`. ```shell curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deployments" ``` -Example of response +Example response: ```json [ @@ -51,16 +46,16 @@ Example of response "author_name": "Administrator", "created_at": "2016-08-11T09:36:01.000+02:00", "id": "99d03678b90d914dbb1b109132516d71a4a03ea8", - "message": "Merge branch 'new-title' into 'master'\r\n\r\nUpdate README\r\n\r\n\r\n\r\nSee merge request !1", + "message": "Merge branch 'new-title' into 'main'\r\n\r\nUpdate README\r\n\r\n\r\n\r\nSee merge request !1", "short_id": "99d03678", - "title": "Merge branch 'new-title' into 'master'\r" + "title": "Merge branch 'new-title' into 'main'\r" }, "coverage": null, "created_at": "2016-08-11T07:36:27.357Z", "finished_at": "2016-08-11T07:36:39.851Z", "id": 657, "name": "deploy", - "ref": "master", + "ref": "main", "runner": null, "stage": "deploy", "started_at": null, @@ -86,7 +81,7 @@ Example of response "pipeline": { "created_at": "2016-08-11T02:12:10.222Z", "id": 36, - "ref": "master", + "ref": "main", "sha": "99d03678b90d914dbb1b109132516d71a4a03ea8", "status": "success", "updated_at": "2016-08-11T02:12:10.222Z", @@ -100,7 +95,7 @@ Example of response }, "id": 41, "iid": 1, - "ref": "master", + "ref": "main", "sha": "99d03678b90d914dbb1b109132516d71a4a03ea8", "user": { "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", @@ -121,16 +116,16 @@ Example of response "author_name": "Administrator", "created_at": "2016-08-11T13:28:26.000+02:00", "id": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", - "message": "Merge branch 'rename-readme' into 'master'\r\n\r\nRename README\r\n\r\n\r\n\r\nSee merge request !2", + "message": "Merge branch 'rename-readme' into 'main'\r\n\r\nRename README\r\n\r\n\r\n\r\nSee merge request !2", "short_id": "a91957a8", - "title": "Merge branch 'rename-readme' into 'master'\r" + "title": "Merge branch 'rename-readme' into 'main'\r" }, "coverage": null, "created_at": "2016-08-11T11:32:24.456Z", "finished_at": "2016-08-11T11:32:35.145Z", "id": 664, "name": "deploy", - "ref": "master", + "ref": "main", "runner": null, "stage": "deploy", "started_at": null, @@ -156,7 +151,7 @@ Example of response "pipeline": { "created_at": "2016-08-11T07:43:52.143Z", "id": 37, - "ref": "master", + "ref": "main", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "status": "success", "updated_at": "2016-08-11T07:43:52.143Z", @@ -170,7 +165,7 @@ Example of response }, "id": 42, "iid": 2, - "ref": "master", + "ref": "main", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "user": { "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", @@ -199,13 +194,13 @@ GET /projects/:id/deployments/:deployment_id curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deployments/1" ``` -Example of response +Example response: ```json { "id": 42, "iid": 2, - "ref": "master", + "ref": "main", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "created_at": "2016-08-11T11:32:35.444Z", "updated_at": "2016-08-11T11:34:01.123Z", @@ -227,7 +222,7 @@ Example of response "status": "success", "stage": "deploy", "name": "deploy", - "ref": "master", + "ref": "main", "tag": false, "coverage": null, "created_at": "2016-08-11T11:32:24.456Z", @@ -252,16 +247,16 @@ Example of response "commit": { "id": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "short_id": "a91957a8", - "title": "Merge branch 'rename-readme' into 'master'\r", + "title": "Merge branch 'rename-readme' into 'main'\r", "author_name": "Administrator", "author_email": "admin@example.com", "created_at": "2016-08-11T13:28:26.000+02:00", - "message": "Merge branch 'rename-readme' into 'master'\r\n\r\nRename README\r\n\r\n\r\n\r\nSee merge request !2" + "message": "Merge branch 'rename-readme' into 'main'\r\n\r\nRename README\r\n\r\n\r\n\r\nSee merge request !2" }, "pipeline": { "created_at": "2016-08-11T07:43:52.143Z", "id": 42, - "ref": "master", + "ref": "main", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "status": "success", "updated_at": "2016-08-11T07:43:52.143Z", @@ -280,33 +275,25 @@ POST /projects/:id/deployments | Attribute | Type | Required | Description | |---------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------| -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | -| `environment` | string | yes | The [name of the environment](../ci/environments/index.md) to create the deployment for | -| `sha` | string | yes | The SHA of the commit that is deployed | -| `ref` | string | yes | The name of the branch or tag that is deployed | -| `tag` | boolean | yes | A boolean that indicates if the deployed ref is a tag (true) or not (false) | -| `status` | string | yes | The status of the deployment | - -The status can be one of the following values: - -- created -- running -- success -- failed -- canceled +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user.| +| `environment` | string | yes | The [name of the environment](../ci/environments/index.md) to create the deployment for. | +| `sha` | string | yes | The SHA of the commit that is deployed. | +| `ref` | string | yes | The name of the branch or tag that is deployed. | +| `tag` | boolean | yes | A boolean that indicates if the deployed ref is a tag (`true`) or not (`false`). | +| `status` | string | no | The status to filter deployments by. One of `created`, `running`, `success`, `failed`, or `canceled`. | ```shell -curl --data "environment=production&sha=a91957a858320c0e17f3a0eca7cfacbff50ea29a&ref=master&tag=false&status=success" \ +curl --data "environment=production&sha=a91957a858320c0e17f3a0eca7cfacbff50ea29a&ref=main&tag=false&status=success" \ --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deployments" ``` -Example of a response: +Example response: ```json { "id": 42, "iid": 2, - "ref": "master", + "ref": "main", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "created_at": "2016-08-11T11:32:35.444Z", "status": "success", @@ -327,7 +314,7 @@ Example of a response: } ``` -## Updating a deployment +## Update a deployment ```plaintext PUT /projects/:id/deployments/:deployment_id @@ -335,21 +322,21 @@ PUT /projects/:id/deployments/:deployment_id | Attribute | Type | Required | Description | |------------------|----------------|----------|---------------------| -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | -| `deployment_id` | integer | yes | The ID of the deployment to update | -| `status` | string | yes | The new status of the deployment | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `deployment_id` | integer | yes | The ID of the deployment to update. | +| `status` | string | no | The new status of the deployment. One of `created`, `running`, `success`, `failed`, or `canceled`. | ```shell curl --request PUT --data "status=success" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deployments/42" ``` -Example of a response: +Example response: ```json { "id": 42, "iid": 2, - "ref": "master", + "ref": "main", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "created_at": "2016-08-11T11:32:35.444Z", "status": "success", @@ -383,5 +370,5 @@ GET /projects/:id/deployments/:deployment_id/merge_requests It supports the same parameters as the [Merge Requests API](merge_requests.md#list-merge-requests) and returns a response using the same format: ```shell -curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deployments/42" +curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deployments/42/merge_requests" ``` diff --git a/doc/api/feature_flag_specs.md b/doc/api/feature_flag_specs.md index 45db47f5ffe..33e454d50c4 100644 --- a/doc/api/feature_flag_specs.md +++ b/doc/api/feature_flag_specs.md @@ -8,293 +8,5 @@ info: To determine the technical writer assigned to the Stage/Group associated w > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9566) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.5. -WARNING: -This API is deprecated and [scheduled for removal in GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/213369). - -The API for creating, updating, reading and deleting Feature Flag Specs. -Automation engineers benefit from this API by being able to modify Feature Flag Specs without accessing user interface. -To manage the [Feature Flag](../operations/feature_flags.md) resources via public API, please refer to the [Feature Flags API](feature_flags.md) document. - -Users with Developer or higher [permissions](../user/permissions.md) can access Feature Flag Specs API. - -## List all effective feature flag specs under the specified environment - -Get all effective feature flag specs under the specified [environment](../ci/environments/index.md). - -For instance, there are two specs, `staging` and `production`, for a feature flag. -When you pass `production` as a parameter to this endpoint, the system returns -the `production` feature flag spec only. - -```plaintext -GET /projects/:id/feature_flag_scopes -``` - -| Attribute | Type | Required | Description | -| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------- | -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). | -| `environment` | string | yes | The [environment](../ci/environments/index.md) name | - -```shell -curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/feature_flag_scopes?environment=production" -``` - -Example response: - -```json -[ - { - "id": 88, - "active": true, - "environment_scope": "production", - "strategies": [ - { - "name": "userWithId", - "parameters": { - "userIds": "1,2,3" - } - } - ], - "created_at": "2019-11-04T08:36:41.327Z", - "updated_at": "2019-11-04T08:36:41.327Z", - "name": "awesome_feature" - }, - { - "id": 82, - "active": true, - "environment_scope": "*", - "strategies": [ - { - "name": "default", - "parameters": {} - } - ], - "created_at": "2019-11-04T08:13:51.425Z", - "updated_at": "2019-11-04T08:39:45.751Z", - "name": "merge_train" - }, - { - "id": 81, - "active": false, - "environment_scope": "production", - "strategies": [ - { - "name": "default", - "parameters": {} - } - ], - "created_at": "2019-11-04T08:13:10.527Z", - "updated_at": "2019-11-04T08:13:10.527Z", - "name": "new_live_trace" - } -] -``` - -## List all specs of a feature flag - -Get all specs of a feature flag. - -```plaintext -GET /projects/:id/feature_flags/:name/scopes -``` - -| Attribute | Type | Required | Description | -| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------- | -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). | -| `name` | string | yes | The name of the feature flag. | - -```shell -curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/feature_flags/new_live_trace/scopes" -``` - -Example response: - -```json -[ - { - "id": 79, - "active": false, - "environment_scope": "*", - "strategies": [ - { - "name": "default", - "parameters": {} - } - ], - "created_at": "2019-11-04T08:13:10.516Z", - "updated_at": "2019-11-04T08:13:10.516Z" - }, - { - "id": 80, - "active": true, - "environment_scope": "staging", - "strategies": [ - { - "name": "default", - "parameters": {} - } - ], - "created_at": "2019-11-04T08:13:10.525Z", - "updated_at": "2019-11-04T08:13:10.525Z" - }, - { - "id": 81, - "active": false, - "environment_scope": "production", - "strategies": [ - { - "name": "default", - "parameters": {} - } - ], - "created_at": "2019-11-04T08:13:10.527Z", - "updated_at": "2019-11-04T08:13:10.527Z" - } -] -``` - -## New feature flag spec - -Creates a new feature flag spec. - -```plaintext -POST /projects/:id/feature_flags/:name/scopes -``` - -| Attribute | Type | Required | Description | -| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------- | -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). | -| `name` | string | yes | The name of the feature flag. | -| `environment_scope` | string | yes | The [environment spec](../ci/environments/index.md#scoping-environments-with-specs) of the feature flag. | -| `active` | boolean | yes | Whether the spec is active. | -| `strategies` | JSON | yes | The [strategies](../operations/feature_flags.md#feature-flag-strategies) of the feature flag spec. | - -```shell -curl "https://gitlab.example.com/api/v4/projects/1/feature_flags/new_live_trace/scopes" \ - --header "PRIVATE-TOKEN: <your_access_token>" \ - --header "Content-type: application/json" \ - --data @- << EOF -{ - "environment_scope": "*", - "active": false, - "strategies": [{ "name": "default", "parameters": {} }] -} -EOF -``` - -Example response: - -```json -{ - "id": 81, - "active": false, - "environment_scope": "*", - "strategies": [ - { - "name": "default", - "parameters": {} - } - ], - "created_at": "2019-11-04T08:13:10.527Z", - "updated_at": "2019-11-04T08:13:10.527Z" -} -``` - -## Single feature flag spec - -Gets a single feature flag spec. - -```plaintext -GET /projects/:id/feature_flags/:name/scopes/:environment_scope -``` - -| Attribute | Type | Required | Description | -| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------| -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). | -| `name` | string | yes | The name of the feature flag. | -| `environment_scope` | string | yes | The URL-encoded [environment spec](../ci/environments/index.md#scoping-environments-with-specs) of the feature flag. | - -```shell -curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/:id/feature_flags/new_live_trace/scopes/production" -``` - -Example response: - -```json -{ - "id": 81, - "active": false, - "environment_scope": "production", - "strategies": [ - { - "name": "default", - "parameters": {} - } - ], - "created_at": "2019-11-04T08:13:10.527Z", - "updated_at": "2019-11-04T08:13:10.527Z" -} -``` - -## Edit feature flag spec - -Updates an existing feature flag spec. - -```plaintext -PUT /projects/:id/feature_flags/:name/scopes/:environment_scope -``` - -| Attribute | Type | Required | Description | -| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------- | -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). | -| `name` | string | yes | The name of the feature flag. | -| `environment_scope` | string | yes | The URL-encoded [environment spec](../ci/environments/index.md#scoping-environments-with-specs) of the feature flag. | -| `active` | boolean | yes | Whether the spec is active. | -| `strategies` | JSON | yes | The [strategies](../operations/feature_flags.md#feature-flag-strategies) of the feature flag spec. | - -```shell -curl "https://gitlab.example.com/api/v4/projects/1/feature_flags/new_live_trace/scopes/production" \ - --header "PRIVATE-TOKEN: <your_access_token>" \ - --header "Content-type: application/json" \ - --data @- << EOF -{ - "active": true, - "strategies": [{ "name": "userWithId", "parameters": { "userIds": "1,2,3" } }] -} -EOF -``` - -Example response: - -```json -{ - "id": 81, - "active": true, - "environment_scope": "production", - "strategies": [ - { - "name": "userWithId", - "parameters": { "userIds": "1,2,3" } - } - ], - "created_at": "2019-11-04T08:13:10.527Z", - "updated_at": "2019-11-04T08:13:10.527Z" -} -``` - -## Delete feature flag spec - -Deletes a feature flag spec. - -```plaintext -DELETE /projects/:id/feature_flags/:name/scopes/:environment_scope -``` - -| Attribute | Type | Required | Description | -| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------| -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). | -| `name` | string | yes | The name of the feature flag. | -| `environment_scope` | string | yes | The URL-encoded [environment spec](../ci/environments/index.md#scoping-environments-with-specs) of the feature flag. | - -```shell -curl --header "PRIVATE-TOKEN: <your_access_token>" --request DELETE "https://gitlab.example.com/api/v4/projects/1/feature_flags/new_live_trace/scopes/production" -``` +This API was removed in [GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/213369). +Please use [the new API](feature_flags.md) instead. diff --git a/doc/api/feature_flags_legacy.md b/doc/api/feature_flags_legacy.md index 6e0763b6015..262e1c537a4 100644 --- a/doc/api/feature_flags_legacy.md +++ b/doc/api/feature_flags_legacy.md @@ -9,315 +9,5 @@ info: To determine the technical writer assigned to the Stage/Group associated w > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9566) in GitLab Premium 12.5. > - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to GitLab Free in 13.5. -WARNING: -This API is deprecated and [scheduled for removal in GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/213369). Use [this API](feature_flags.md) instead. - -API for accessing resources of [GitLab Feature Flags](../operations/feature_flags.md). - -Users with Developer or higher [permissions](../user/permissions.md) can access Feature Flag API. - -## Feature Flags pagination - -By default, `GET` requests return 20 results at a time because the API results -are [paginated](README.md#pagination). - -## List feature flags for a project - -Gets all feature flags of the requested project. - -```plaintext -GET /projects/:id/feature_flags -``` - -| Attribute | Type | Required | Description | -| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------- | -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). | -| `scope` | string | no | The condition of feature flags, one of: `enabled`, `disabled`. | - -```shell -curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/feature_flags" -``` - -Example response: - -```json -[ - { - "name":"merge_train", - "description":"This feature is about merge train", - "active": true, - "created_at":"2019-11-04T08:13:51.423Z", - "updated_at":"2019-11-04T08:13:51.423Z", - "scopes":[ - { - "id":82, - "active":false, - "environment_scope":"*", - "strategies":[ - { - "name":"default", - "parameters":{ - - } - } - ], - "created_at":"2019-11-04T08:13:51.425Z", - "updated_at":"2019-11-04T08:13:51.425Z" - }, - { - "id":83, - "active":true, - "environment_scope":"review/*", - "strategies":[ - { - "name":"default", - "parameters":{ - - } - } - ], - "created_at":"2019-11-04T08:13:51.427Z", - "updated_at":"2019-11-04T08:13:51.427Z" - }, - { - "id":84, - "active":false, - "environment_scope":"production", - "strategies":[ - { - "name":"default", - "parameters":{ - - } - } - ], - "created_at":"2019-11-04T08:13:51.428Z", - "updated_at":"2019-11-04T08:13:51.428Z" - } - ] - }, - { - "name":"new_live_trace", - "description":"This is a new live trace feature", - "active": true, - "created_at":"2019-11-04T08:13:10.507Z", - "updated_at":"2019-11-04T08:13:10.507Z", - "scopes":[ - { - "id":79, - "active":false, - "environment_scope":"*", - "strategies":[ - { - "name":"default", - "parameters":{ - - } - } - ], - "created_at":"2019-11-04T08:13:10.516Z", - "updated_at":"2019-11-04T08:13:10.516Z" - }, - { - "id":80, - "active":true, - "environment_scope":"staging", - "strategies":[ - { - "name":"default", - "parameters":{ - - } - } - ], - "created_at":"2019-11-04T08:13:10.525Z", - "updated_at":"2019-11-04T08:13:10.525Z" - }, - { - "id":81, - "active":false, - "environment_scope":"production", - "strategies":[ - { - "name":"default", - "parameters":{ - - } - } - ], - "created_at":"2019-11-04T08:13:10.527Z", - "updated_at":"2019-11-04T08:13:10.527Z" - } - ] - } -] -``` - -## New feature flag - -Creates a new feature flag. - -```plaintext -POST /projects/:id/feature_flags -``` - -| Attribute | Type | Required | Description | -| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------| -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). | -| `name` | string | yes | The name of the feature flag. | -| `description` | string | no | The description of the feature flag. | -| `active` | boolean | no | The active state of the flag. Defaults to true. [Supported](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38350) in GitLab 13.3 and later. | -| `scopes` | JSON | no | The feature flag specs of the feature flag. | -| `scopes:environment_scope` | string | no | The environment spec. | -| `scopes:active` | boolean | no | Whether the spec is active. | -| `scopes:strategies` | JSON | no | The [strategies](../operations/feature_flags.md#feature-flag-strategies) of the feature flag spec. | - -```shell -curl "https://gitlab.example.com/api/v4/projects/1/feature_flags" \ - --header "PRIVATE-TOKEN: <your_access_token>" \ - --header "Content-type: application/json" \ - --data @- << EOF -{ - "name": "awesome_feature", - "scopes": [{ "environment_scope": "*", "active": false, "strategies": [{ "name": "default", "parameters": {} }] }, - { "environment_scope": "production", "active": true, "strategies": [{ "name": "userWithId", "parameters": { "userIds": "1,2,3" } }] }] -} -EOF -``` - -Example response: - -```json -{ - "name":"awesome_feature", - "description":null, - "active": true, - "created_at":"2019-11-04T08:32:27.288Z", - "updated_at":"2019-11-04T08:32:27.288Z", - "scopes":[ - { - "id":85, - "active":false, - "environment_scope":"*", - "strategies":[ - { - "name":"default", - "parameters":{ - - } - } - ], - "created_at":"2019-11-04T08:32:29.324Z", - "updated_at":"2019-11-04T08:32:29.324Z" - }, - { - "id":86, - "active":true, - "environment_scope":"production", - "strategies":[ - { - "name":"userWithId", - "parameters":{ - "userIds":"1,2,3" - } - } - ], - "created_at":"2019-11-04T08:32:29.328Z", - "updated_at":"2019-11-04T08:32:29.328Z" - } - ] -} -``` - -## Single feature flag - -Gets a single feature flag. - -```plaintext -GET /projects/:id/feature_flags/:name -``` - -| Attribute | Type | Required | Description | -| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------| -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). | -| `name` | string | yes | The name of the feature flag. | - -```shell -curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/feature_flags/new_live_trace" -``` - -Example response: - -```json -{ - "name":"new_live_trace", - "description":"This is a new live trace feature", - "active": true, - "created_at":"2019-11-04T08:13:10.507Z", - "updated_at":"2019-11-04T08:13:10.507Z", - "scopes":[ - { - "id":79, - "active":false, - "environment_scope":"*", - "strategies":[ - { - "name":"default", - "parameters":{ - - } - } - ], - "created_at":"2019-11-04T08:13:10.516Z", - "updated_at":"2019-11-04T08:13:10.516Z" - }, - { - "id":80, - "active":true, - "environment_scope":"staging", - "strategies":[ - { - "name":"default", - "parameters":{ - - } - } - ], - "created_at":"2019-11-04T08:13:10.525Z", - "updated_at":"2019-11-04T08:13:10.525Z" - }, - { - "id":81, - "active":false, - "environment_scope":"production", - "strategies":[ - { - "name":"default", - "parameters":{ - - } - } - ], - "created_at":"2019-11-04T08:13:10.527Z", - "updated_at":"2019-11-04T08:13:10.527Z" - } - ] -} -``` - -## Delete feature flag - -Deletes a feature flag. - -```plaintext -DELETE /projects/:id/feature_flags/:name -``` - -| Attribute | Type | Required | Description | -| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------| -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). | -| `name` | string | yes | The name of the feature flag. | - -```shell -curl --header "PRIVATE-TOKEN: <your_access_token>" --request DELETE "https://gitlab.example.com/api/v4/projects/1/feature_flags/awesome_feature" -``` +This API was removed in [GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/213369). +Please use [the new API](feature_flags.md) instead. diff --git a/doc/api/resource_access_tokens.md b/doc/api/resource_access_tokens.md index 2d458cbe2ad..3b443dbb8f8 100644 --- a/doc/api/resource_access_tokens.md +++ b/doc/api/resource_access_tokens.md @@ -10,7 +10,7 @@ You can read more about [project access tokens](../user/project/settings/project ## List project access tokens -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/238991) in GitLab 13.9. +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/238991) in GitLab 13.9. Get a list of project access tokens. @@ -45,7 +45,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a ## Create a project access token -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/238991) in GitLab 13.9. +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55408) in GitLab 13.10. Create a project access token. @@ -86,7 +86,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \ ## Revoke a project access token -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/238991) in GitLab 13.9. +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/238991) in GitLab 13.9. Revoke a project access token. diff --git a/doc/api/status_checks.md b/doc/api/status_checks.md index e4640e26a47..f4e384a2efb 100644 --- a/doc/api/status_checks.md +++ b/doc/api/status_checks.md @@ -195,3 +195,7 @@ Feature.disable(:ff_compliance_approval_gates) # For a single project Feature.disable(:ff_compliance_approval_gates, Project.find(<project id>) ``` + +## Related links + +- [External status checks](../user/project/merge_requests/status_checks.md) diff --git a/doc/development/pipelines.md b/doc/development/pipelines.md index 437b2d04e1e..c3fb66cb085 100644 --- a/doc/development/pipelines.md +++ b/doc/development/pipelines.md @@ -480,7 +480,11 @@ because of 2 reasons: ### PostgreSQL versions testing Our test suite runs against PG12 as GitLab.com runs on PG12 and -[Omnibus defaults to PG12 for new installs and upgrades](https://docs.gitlab.com/omnibus/package-information/postgresql_versions.html). +[Omnibus defaults to PG12 for new installs and upgrades](https://docs.gitlab.com/omnibus/package-information/postgresql_versions.html), +Our test suite is currently running against PG11, since GitLab.com still runs on PG11. + +We do run our test suite against PG11 on nightly scheduled pipelines as well as upon specific +database library changes in MRs and `master` pipelines (with the `rspec db-library-code pg11` job). #### Current versions testing @@ -498,6 +502,7 @@ We follow the [PostgreSQL versions shipped with Omnibus GitLab](https://docs.git | PostgreSQL version | 13.11 (April 2021) | 13.12 (May 2021) | 14.0 (June 2021?) | | -------------------| ---------------------- | ---------------------- | ---------------------- | | PG12 | `nightly` | MRs/`2-hour`/`nightly` | MRs/`2-hour`/`nightly` | +| PG11 | MRs/`2-hour`/`nightly` | `nightly` | `nightly` | ### Test jobs @@ -726,6 +731,8 @@ that are scoped to a single [configuration keyword](../ci/yaml/README.md#job-key | `.qa-cache` | Allows a job to use a default `cache` definition suitable for QA tasks. | | `.yarn-cache` | Allows a job to use a default `cache` definition suitable for frontend jobs that do a `yarn install`. | | `.assets-compile-cache` | Allows a job to use a default `cache` definition suitable for frontend jobs that compile assets. | +| `.use-pg11` | Allows a job to run the `postgres` 11 and `redis` services (see [`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/global.gitlab-ci.yml) for the specific versions of the services). | +| `.use-pg11-ee` | Same as `.use-pg11` but also use an `elasticsearch` service (see [`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/global.gitlab-ci.yml) for the specific version of the service). | | `.use-pg12` | Allows a job to use the `postgres` 12 and `redis` services (see [`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/global.gitlab-ci.yml) for the specific versions of the services). | | `.use-pg12-ee` | Same as `.use-pg12` but also use an `elasticsearch` service (see [`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/global.gitlab-ci.yml) for the specific version of the service). | | `.use-kaniko` | Allows a job to use the `kaniko` tool to build Docker images. | diff --git a/doc/development/usage_ping/dictionary.md b/doc/development/usage_ping/dictionary.md index 4b31fd113e1..e76fb302b9c 100644 --- a/doc/development/usage_ping/dictionary.md +++ b/doc/development/usage_ping/dictionary.md @@ -162,7 +162,7 @@ Missing description Group: `` -Status: `implemented` +Status: `data_available` Tiers: @@ -282,7 +282,7 @@ Missing description Group: `` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -594,7 +594,7 @@ Total active instance Runners Group: `group::pipeline execution` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -606,7 +606,7 @@ Total active and online group Runners Group: `group::pipeline execution` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -618,7 +618,7 @@ Total active group Runners Group: `group::pipeline execution` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -630,7 +630,7 @@ Total active and online instance Runners Group: `group::pipeline execution` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -642,7 +642,7 @@ Total online Runners Group: `group::pipeline execution` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -654,7 +654,7 @@ Total active project Runners Group: `group::pipeline execution` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -666,7 +666,7 @@ Total active and online project Runners Group: `group::pipeline execution` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2118,7 +2118,7 @@ Total clicks on the create track's first email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2130,7 +2130,7 @@ Total sent emails of the create track's first email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2142,7 +2142,7 @@ Total clicks on the create track's second email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2154,7 +2154,7 @@ Total sent emails of the create track's second email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2166,7 +2166,7 @@ Total clicks on the create track's third email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2178,7 +2178,7 @@ Total sent emails of the create track's third email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2190,7 +2190,7 @@ Total sent emails of the experience track's first email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2202,7 +2202,7 @@ Total clicks on the team track's first email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2214,7 +2214,7 @@ Total sent emails of the team track's first email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2226,7 +2226,7 @@ Total clicks on the team track's second email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2238,7 +2238,7 @@ Total sent emails of the team track's second email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2250,7 +2250,7 @@ Total clicks on the team track's third email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2262,7 +2262,7 @@ Total sent emails of the team track's third email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2274,7 +2274,7 @@ Total clicks on the verify trial's first email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2286,7 +2286,7 @@ Total sent emails of the trial track's first email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2298,7 +2298,7 @@ Total clicks on the trial track's second email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2310,7 +2310,7 @@ Total sent emails of the trial track's second email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2322,7 +2322,7 @@ Total clicks on the trial track's third email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2334,7 +2334,7 @@ Total sent emails of the trial track's third email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2346,7 +2346,7 @@ Total clicks on the verify track's first email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2358,7 +2358,7 @@ Total sent emails of the verify track's first email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2370,7 +2370,7 @@ Total clicks on the verify track's second email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2382,7 +2382,7 @@ Total sent emails of the verify track's second email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2394,7 +2394,7 @@ Total clicks on the verify track's third email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -2406,7 +2406,7 @@ Total sent emails of the verify track's third email Group: `group::activation` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -3186,7 +3186,7 @@ Count of Kubernetes API proxy requests Group: `group::configure` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` @@ -6570,7 +6570,7 @@ Missing description Group: `` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -6582,7 +6582,7 @@ Missing description Group: `` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -6594,7 +6594,7 @@ Missing description Group: `` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -6786,7 +6786,7 @@ Missing description Group: `` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -6798,7 +6798,7 @@ Missing description Group: `` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -6810,7 +6810,7 @@ Missing description Group: `` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -8166,7 +8166,7 @@ Counts visits to DevOps Adoption page per month Group: `group::optimize` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` @@ -8178,7 +8178,7 @@ Counts visits to DevOps Adoption page per week Group: `group::optimize` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` @@ -8622,7 +8622,7 @@ Count of users clicking diff view setting Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -8634,7 +8634,7 @@ Count of users clicking diff view setting Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -8646,7 +8646,7 @@ Count of users clicking merge request file browser setting Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -8658,7 +8658,7 @@ Count of users with merge request file list setting Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -8670,7 +8670,7 @@ Count of users clicking single file mode setting Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -8682,7 +8682,7 @@ Count of users clicking single file mode setting Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -8694,7 +8694,7 @@ Count of users clicking merge request whitespae setting Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -8706,7 +8706,7 @@ Count of users clicking merge request whitespae setting Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -8718,7 +8718,7 @@ Count of users with show whitespace disabled Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -8730,7 +8730,7 @@ Count of users with show whitespace disabled Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -8742,7 +8742,7 @@ Count of users with single mode disabled Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -8754,7 +8754,7 @@ Count of users with single mode disabled Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -8766,7 +8766,7 @@ Count of users with show whitespace enabled Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -8778,7 +8778,7 @@ Count of users with show whitespace enabled Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -8790,7 +8790,7 @@ Count of users with single file mode enabled Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -8802,7 +8802,7 @@ Count of users with single file mode enabled Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -8814,7 +8814,7 @@ Count of users with merge request view type as inline Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -8826,7 +8826,7 @@ Count of users with merge request view type as inline Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -8838,7 +8838,7 @@ Count of users with merge request view type as parallel Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -8850,7 +8850,7 @@ Count of users with merge request view type as parallel Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -8910,7 +8910,7 @@ Count of users with merge request file list setting Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -8922,7 +8922,7 @@ Count of users with merge request file list setting Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -8934,7 +8934,7 @@ Count of users with merge request file tree setting Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -8946,7 +8946,7 @@ Count of users with merge request file tree setting Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -9414,7 +9414,7 @@ Count of unique users per week who load the conflict resolution page Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -9426,7 +9426,7 @@ Count of unique users per week who load the conflict resolution page Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -9654,7 +9654,7 @@ Count of unique users per week who attempt to resolve a conflict through the ui Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -9666,7 +9666,7 @@ Count of unique users per week who attempt to resolve a conflict through the ui Group: `group::code review` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -10782,7 +10782,7 @@ Missing description Group: `` -Status: `implemented` +Status: `data_available` Tiers: `ultimate` @@ -10794,7 +10794,7 @@ Missing description Group: `` -Status: `implemented` +Status: `data_available` Tiers: `ultimate` @@ -10806,7 +10806,7 @@ Count of MAU creating epic boards Group: `group::product planning` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` @@ -10818,7 +10818,7 @@ Count of WAU creating epic boards Group: `group::product planning` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` @@ -10830,7 +10830,7 @@ Count of MAU updating epic board names Group: `group::product planning` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` @@ -10842,7 +10842,7 @@ Count of WAU updating epic board names Group: `group::product planning` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` @@ -10854,7 +10854,7 @@ Count of MAU viewing epic boards Group: `group::product planning` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` @@ -10866,7 +10866,7 @@ Count of WAU viewing epic boards Group: `group::product planning` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` @@ -10950,7 +10950,7 @@ Count of MAU cross referencing epics Group: `group::product planning` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` @@ -10962,7 +10962,7 @@ Counts of WAU cross referencing epics Group: `group::product planning` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` @@ -11142,7 +11142,7 @@ Counts of MAU awarding emoji on epic Group: `group::product planning` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` @@ -11154,7 +11154,7 @@ Counts of WAU awarding emoji on epic Group: `group::product planning` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` @@ -11214,7 +11214,7 @@ Number of users creating an issue from an epic Group: `group::product planning` -Status: `implemented` +Status: `data_available` Tiers: `premium` @@ -11226,7 +11226,7 @@ Number of users creating an issue from an epic Group: `group::product planning` -Status: `implemented` +Status: `data_available` Tiers: `premium` @@ -11238,7 +11238,7 @@ Counts of MAU removing emoji on epic Group: `group::product planning` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` @@ -11250,7 +11250,7 @@ Counts of WAU removing emoji on epic Group: `group::product planning` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` @@ -11454,7 +11454,7 @@ Counts of MAU updating parent on epic Group: `group::product planning` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` @@ -11466,7 +11466,7 @@ Counts of WAU updating parent on epic Group: `group::product planning` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` @@ -11550,7 +11550,7 @@ Counts of MAU checking epic task Group: `group::product planning` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` @@ -11562,7 +11562,7 @@ Counts of WAU checking epic task Group: `group::product planning` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` @@ -11574,7 +11574,7 @@ Counts of MAU unchecking epic task Group: `group::product planning` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` @@ -11586,7 +11586,7 @@ Counts of WAU unchecking epic task Group: `group::product planning` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` @@ -12990,7 +12990,7 @@ Missing description Group: `` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -13002,7 +13002,7 @@ Missing description Group: `` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -16304,7 +16304,7 @@ Missing description Group: `` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -16340,7 +16340,7 @@ Total count of all custom compliance framework labels Group: `compliance` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` @@ -18274,7 +18274,7 @@ Missing description Group: `` -Status: `implemented` +Status: `data_available` Tiers: `free`, `premium`, `ultimate` @@ -18310,7 +18310,7 @@ Monthly count of all custom compliance framework labels Group: `compliance` -Status: `implemented` +Status: `data_available` Tiers: `premium`, `ultimate` diff --git a/doc/development/usage_ping/metrics_dictionary.md b/doc/development/usage_ping/metrics_dictionary.md index d927d1fb461..6b5fed4bcca 100644 --- a/doc/development/usage_ping/metrics_dictionary.md +++ b/doc/development/usage_ping/metrics_dictionary.md @@ -37,6 +37,7 @@ Each metric is defined in a separate YAML file consisting of a number of fields: | `status` | yes | `string`; [status](#metric-statuses) of the metric, may be set to `data_available`, `implemented`, `not_used`, `deprecated`, `removed`, `broken`. | | `time_frame` | yes | `string`; may be set to a value like `7d`, `28d`, `all`, `none`. | | `data_source` | yes | `string`; may be set to a value like `database`, `redis`, `redis_hll`, `prometheus`, `system`. | +| `data_category` | yes | `string`; [categories](#data-category) of the metric, may be set to `Operational`, `Optional`, `Subscription`, `Standard`. | | `instrumentation_class` | no | `string`; [the class that implements the metric](metrics_instrumentation.md). | | `distribution` | yes | `array`; may be set to one of `ce, ee` or `ee`. The [distribution](https://about.gitlab.com/handbook/marketing/strategic-marketing/tiers/#definitions) where the tracked feature is available. | | `tier` | yes | `array`; may be set to one of `free, premium, ultimate`, `premium, ultimate` or `ultimate`. The [tier]( https://about.gitlab.com/handbook/marketing/strategic-marketing/tiers/) where the tracked feature is available. | @@ -93,6 +94,15 @@ Metric name suggestions can contain two types of elements: For a metric name to be valid, it must not include any prompt, and no fixed suggestions should be changed. +### Data category + +We use the following categories to classify a metric: + +- `Operational`: Required data for operational purposes. +- `Optional`: Data that is optional to collect. This can be [enabled or disabled](../usage_ping/index.md#disable-usage-ping) in the Admin Area. +- `Subscription`: Data related to licensing. +- `Standard`: Standard set of identifiers that are included when collecting data. + ### Metric name suggestion examples #### Metric with `data_source: database` diff --git a/doc/user/project/merge_requests/img/status_checks_branches_selector_v14_0.png b/doc/user/project/merge_requests/img/status_checks_branches_selector_v14_0.png Binary files differnew file mode 100644 index 00000000000..65009faf426 --- /dev/null +++ b/doc/user/project/merge_requests/img/status_checks_branches_selector_v14_0.png diff --git a/doc/user/project/merge_requests/img/status_checks_create_form_v14_0.png b/doc/user/project/merge_requests/img/status_checks_create_form_v14_0.png Binary files differnew file mode 100644 index 00000000000..9e6d6c552e5 --- /dev/null +++ b/doc/user/project/merge_requests/img/status_checks_create_form_v14_0.png diff --git a/doc/user/project/merge_requests/img/status_checks_delete_modal_v14_0.png b/doc/user/project/merge_requests/img/status_checks_delete_modal_v14_0.png Binary files differnew file mode 100644 index 00000000000..a305f5c73f8 --- /dev/null +++ b/doc/user/project/merge_requests/img/status_checks_delete_modal_v14_0.png diff --git a/doc/user/project/merge_requests/img/status_checks_list_view_v14_0.png b/doc/user/project/merge_requests/img/status_checks_list_view_v14_0.png Binary files differnew file mode 100644 index 00000000000..6be64112ac6 --- /dev/null +++ b/doc/user/project/merge_requests/img/status_checks_list_view_v14_0.png diff --git a/doc/user/project/merge_requests/img/status_checks_update_form_v14_0.png b/doc/user/project/merge_requests/img/status_checks_update_form_v14_0.png Binary files differnew file mode 100644 index 00000000000..fcfe16bcd97 --- /dev/null +++ b/doc/user/project/merge_requests/img/status_checks_update_form_v14_0.png diff --git a/doc/user/project/merge_requests/status_checks.md b/doc/user/project/merge_requests/status_checks.md new file mode 100644 index 00000000000..775820870f3 --- /dev/null +++ b/doc/user/project/merge_requests/status_checks.md @@ -0,0 +1,179 @@ +--- +stage: Manage +group: Compliance +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments" +type: reference, concepts +disqus_identifier: 'https://docs.gitlab.com/ee/user/project/merge_requests/status_checks.html' +--- + +# External Status Checks **(ULTIMATE)** + +> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3869) in GitLab 14.0. +> - It's [deployed behind a feature flag](../../feature_flags.md), disabled by default. +> - It's disabled on GitLab.com. +> - It's not recommended for production use. +> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-status-checks). **(ULTIMATE SELF)** + +WARNING: +This feature might not be available to you. Check the **version history** note above for details. + +You can create a status check that sends merge request data to third-party tools. +When users create, change, or close merge requests, GitLab sends a notification. The users or automated workflows +can then update the status of merge requests from outside of GitLab. + +With this integration, you can integrate with third-party workflow tools, like +ServiceNow, or the custom tool of your choice. The third-party tool +respond with an associated status. This status is then displayed as a non-blocking +widget within the merge request to surface this status to the merge request author or reviewers +at the merge request level itself. + +The lack of a status check response does not block the merging of a merge request. + +You can configure merge request status checks for each individual project. These are not shared between projects. + +To learn more about use cases, feature discovery, and development timelines, +see the [external status checks epic](https://gitlab.com/groups/gitlab-org/-/epics/3869). + +## View the status checks on a project + +Within each project's settings, you can see a list of status checks added to the project: + +1. In your project, go to **Settings > General**. +1. Expand the **Merge requests** section. +1. Scroll down to the **Status checks** sub-section. + +![Status checks list](img/status_checks_list_view_v14_0.png) + +This list shows the service name, API URL, and targeted branch. +It also provides actions to allow you to create, edit, or remove status checks. + +## Add or update a status check + +### Add a status check + +Within the **Status checks** sub-section, select the **Add status check** button. +The **Add status check** form is then shown. + +![Status checks create form](img/status_checks_create_form_v14_0.png) + +Filling in the form and selecting the **Add status check** button creates a new status check. + +### Update a status check + +Within the **Status checks** sub-section, select the **Edit** button +next to the status check you want to edit. +The **Update status check** form is then shown. + +![Status checks update form](img/status_checks_update_form_v14_0.png) + +Changing the values in the form and selecting the **Update status check** button updates the status check. + +### Form values + +For common form errors see the [troubleshooting](#troubleshooting) section below. + +#### Service name + +This name can be any alphanumerical value and **must** be set. The name **must** be unique for +the project. +The name **has** to be unique for the project. + +#### API to check + +This field requires a URL and **must** use either the HTTP or HTTPs protocols. +We **recommend** using HTTPs to protect your merge request data in transit. +The URL **must** be set and **must** be unique for the project. + +#### Target branch + +If you want to restrict the status check to a single branch, +you can use this field to set this limit. + +![Status checks branch selector](img/status_checks_branches_selector_v14_0.png) + +The branches list is populated from the projects [protected branches](../protected_branches.md). + +You can scroll through the list of branches or use the search box +when there are a lot of branches and the branch you are looking +for doesn't appear immediately. The search box requires +**three** alphanumeric characters to be entered for the search to begin. + +If you want the status check to be applied to **all** merge requests, +you can select the **Any branch** option. + +## Delete a status check + +Within the **Status checks** sub-section, select the **Remove...** button +next to the status check you want to delete. +The **Remove status check?** modal is then shown. + +![Status checks delete modal](img/status_checks_delete_modal_v14_0.png) + +To complete the deletion of the status check you must select the +**Remove status check** button. This **permanently** deletes +the status check and it **will not** be recoverable. + +## Troubleshooting + +### Duplicate value errors + +```plaintext +Name is already taken +--- +External API is already in use by another status check +``` + +On a per project basis, status checks can only use a name or API URL once. +These errors mean that either the status checks name or API URL have already +been used in this projects status checks. + +You must either choose a different +value on the current status check or update the value on the existing status check. + +### Invalid URL error + +```plaintext +Please provide a valid URL +``` + +The API to check field requires the URL provided to use either the HTTP or HTTPs protocols. +You must update the value of the field to meet this requirement. + +### Branch list error during retrieval or search + +```plaintext +Unable to fetch branches list, please close the form and try again +``` + +An unexpected response was received from the branches retrieval API. +As suggested, you should close the form and reopen again or refresh the page. This error should be temporary, although +if it persists please check the [GitLab status page](https://status.gitlab.com/) to see if there is a wider outage. + +## Enable or disable status checks **(ULTIMATE SELF)** + +Status checks are under development and not ready for production use. It is +deployed behind a feature flag that is **disabled by default**. +[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md) +can enable it. + +To enable it: + +```ruby +# For the instance +Feature.enable(:ff_compliance_approval_gates) +# For a single project +Feature.enable(:ff_compliance_approval_gates, Project.find(<project id>)) +``` + +To disable it: + +```ruby +# For the instance +Feature.disable(:ff_compliance_approval_gates) +# For a single project +Feature.disable(:ff_compliance_approval_gates, Project.find(<project id>) +``` + +## Related links + +- [External status checks API](../../../api/status_checks.md) diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md index cd9d36bf161..3ea34c35443 100644 --- a/doc/user/project/settings/index.md +++ b/doc/user/project/settings/index.md @@ -249,6 +249,7 @@ Set up your project's merge request settings: - Set up the merge request method (merge commit, [fast-forward merge](../merge_requests/fast_forward_merge.md)). - Add merge request [description templates](../description_templates.md#description-templates). - Enable [merge request approvals](../merge_requests/approvals/index.md). +- Enable [status checks](../merge_requests/status_checks.md). - Enable [merge only if pipeline succeeds](../merge_requests/merge_when_pipeline_succeeds.md). - Enable [merge only when all threads are resolved](../../discussions/index.md#only-allow-merge-requests-to-be-merged-if-all-threads-are-resolved). - Enable [require an associated issue from Jira](../../../integration/jira/issues.md#require-associated-jira-issue-for-merge-requests-to-be-merged). diff --git a/generator_templates/usage_metric_definition/metric_definition.yml b/generator_templates/usage_metric_definition/metric_definition.yml index 89290a0bd89..53ff84fc4ab 100644 --- a/generator_templates/usage_metric_definition/metric_definition.yml +++ b/generator_templates/usage_metric_definition/metric_definition.yml @@ -11,6 +11,7 @@ milestone: "<%= milestone %>" introduced_by_url: time_frame: <%= time_frame %> data_source: +data_category: Operational distribution: <%= distribution %> tier: diff --git a/lib/api/api.rb b/lib/api/api.rb index b551c42d004..2a3033753f7 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -168,7 +168,6 @@ module API mount ::API::ErrorTracking mount ::API::Events mount ::API::FeatureFlags - mount ::API::FeatureFlagScopes mount ::API::FeatureFlagsUserLists mount ::API::Features mount ::API::Files diff --git a/lib/api/feature_flag_scopes.rb b/lib/api/feature_flag_scopes.rb deleted file mode 100644 index 3f3bf4d9f42..00000000000 --- a/lib/api/feature_flag_scopes.rb +++ /dev/null @@ -1,160 +0,0 @@ -# frozen_string_literal: true - -module API - class FeatureFlagScopes < ::API::Base - include PaginationParams - - ENVIRONMENT_SCOPE_ENDPOINT_REQUIREMENTS = FeatureFlags::FEATURE_FLAG_ENDPOINT_REQUIREMENTS - .merge(environment_scope: API::NO_SLASH_URL_PART_REGEX) - - feature_category :feature_flags - - before do - authorize_read_feature_flags! - end - - params do - requires :id, type: String, desc: 'The ID of a project' - end - resource 'projects/:id', requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do - resource :feature_flag_scopes do - desc 'Get all effective feature flags under the environment' do - detail 'This feature was introduced in GitLab 12.5' - success ::API::Entities::FeatureFlag::DetailedLegacyScope - end - params do - requires :environment, type: String, desc: 'The environment name' - end - get do - present scopes_for_environment, with: ::API::Entities::FeatureFlag::DetailedLegacyScope - end - end - - params do - requires :name, type: String, desc: 'The name of the feature flag' - end - resource 'feature_flags/:name', requirements: FeatureFlags::FEATURE_FLAG_ENDPOINT_REQUIREMENTS do - resource :scopes do - desc 'Get all scopes of a feature flag' do - detail 'This feature was introduced in GitLab 12.5' - success ::API::Entities::FeatureFlag::LegacyScope - end - params do - use :pagination - end - get do - present paginate(feature_flag.scopes), with: ::API::Entities::FeatureFlag::LegacyScope - end - - desc 'Create a scope of a feature flag' do - detail 'This feature was introduced in GitLab 12.5' - success ::API::Entities::FeatureFlag::LegacyScope - end - params do - requires :environment_scope, type: String, desc: 'The environment scope of the scope' - requires :active, type: Boolean, desc: 'Whether the scope is active' - requires :strategies, type: JSON, desc: 'The strategies of the scope' - end - post do - authorize_update_feature_flag! - - result = ::FeatureFlags::UpdateService - .new(user_project, current_user, scopes_attributes: [declared_params]) - .execute(feature_flag) - - if result[:status] == :success - present scope, with: ::API::Entities::FeatureFlag::LegacyScope - else - render_api_error!(result[:message], result[:http_status]) - end - end - - params do - requires :environment_scope, type: String, desc: 'URL-encoded environment scope' - end - resource ':environment_scope', requirements: ENVIRONMENT_SCOPE_ENDPOINT_REQUIREMENTS do - desc 'Get a scope of a feature flag' do - detail 'This feature was introduced in GitLab 12.5' - success ::API::Entities::FeatureFlag::LegacyScope - end - get do - present scope, with: ::API::Entities::FeatureFlag::LegacyScope - end - - desc 'Update a scope of a feature flag' do - detail 'This feature was introduced in GitLab 12.5' - success ::API::Entities::FeatureFlag::LegacyScope - end - params do - optional :active, type: Boolean, desc: 'Whether the scope is active' - optional :strategies, type: JSON, desc: 'The strategies of the scope' - end - put do - authorize_update_feature_flag! - - scope_attributes = declared_params.merge(id: scope.id) - - result = ::FeatureFlags::UpdateService - .new(user_project, current_user, scopes_attributes: [scope_attributes]) - .execute(feature_flag) - - if result[:status] == :success - updated_scope = result[:feature_flag].scopes - .find { |scope| scope.environment_scope == params[:environment_scope] } - - present updated_scope, with: ::API::Entities::FeatureFlag::LegacyScope - else - render_api_error!(result[:message], result[:http_status]) - end - end - - desc 'Delete a scope from a feature flag' do - detail 'This feature was introduced in GitLab 12.5' - success ::API::Entities::FeatureFlag::LegacyScope - end - delete do - authorize_update_feature_flag! - - param = { scopes_attributes: [{ id: scope.id, _destroy: true }] } - - result = ::FeatureFlags::UpdateService - .new(user_project, current_user, param) - .execute(feature_flag) - - if result[:status] == :success - status :no_content - else - render_api_error!(result[:message], result[:http_status]) - end - end - end - end - end - end - - helpers do - def authorize_read_feature_flags! - authorize! :read_feature_flag, user_project - end - - def authorize_update_feature_flag! - authorize! :update_feature_flag, feature_flag - end - - def feature_flag - @feature_flag ||= user_project.operations_feature_flags - .find_by_name!(params[:name]) - end - - def scope - @scope ||= feature_flag.scopes - .find_by_environment_scope!(CGI.unescape(params[:environment_scope])) - end - - def scopes_for_environment - Operations::FeatureFlagScope - .for_unleash_client(user_project, params[:environment]) - end - end - end -end diff --git a/lib/api/feature_flags.rb b/lib/api/feature_flags.rb index a08933583fb..fb5858bc10b 100644 --- a/lib/api/feature_flags.rb +++ b/lib/api/feature_flags.rb @@ -95,54 +95,6 @@ module API present_entity(feature_flag) end - desc 'Enable a strategy for a feature flag on an environment' do - detail 'This feature was introduced in GitLab 12.5' - success ::API::Entities::FeatureFlag - end - params do - requires :environment_scope, type: String, desc: 'The environment scope of the feature flag' - requires :strategy, type: JSON, desc: 'The strategy to be enabled on the scope' - end - post :enable do - not_found! unless Feature.enabled?(:feature_flag_api, user_project) - exclude_legacy_flags_check! - render_api_error!('Version 2 flags not supported', :unprocessable_entity) if new_version_flag_present? - - result = ::FeatureFlags::EnableService - .new(user_project, current_user, params).execute - - if result[:status] == :success - status :ok - present_entity(result[:feature_flag]) - else - render_api_error!(result[:message], result[:http_status]) - end - end - - desc 'Disable a strategy for a feature flag on an environment' do - detail 'This feature is going to be introduced in GitLab 12.5 if `feature_flag_api` feature flag is removed' - success ::API::Entities::FeatureFlag - end - params do - requires :environment_scope, type: String, desc: 'The environment scope of the feature flag' - requires :strategy, type: JSON, desc: 'The strategy to be disabled on the scope' - end - post :disable do - not_found! unless Feature.enabled?(:feature_flag_api, user_project) - exclude_legacy_flags_check! - render_api_error!('Version 2 flags not supported', :unprocessable_entity) if feature_flag.new_version_flag? - - result = ::FeatureFlags::DisableService - .new(user_project, current_user, params).execute - - if result[:status] == :success - status :ok - present_entity(result[:feature_flag]) - else - render_api_error!(result[:message], result[:http_status]) - end - end - desc 'Update a feature flag' do detail 'This feature was introduced in GitLab 13.2' success ::API::Entities::FeatureFlag @@ -255,9 +207,7 @@ module API end def exclude_legacy_flags_check! - if Feature.enabled?(:remove_legacy_flags, project, default_enabled: :yaml) && - Feature.disabled?(:remove_legacy_flags_override, project, default_enabled: :yaml) && - feature_flag.legacy_flag? + if feature_flag.legacy_flag? not_found! end end diff --git a/lib/api/unleash.rb b/lib/api/unleash.rb index c622b8a499c..37fe540cde1 100644 --- a/lib/api/unleash.rb +++ b/lib/api/unleash.rb @@ -69,21 +69,7 @@ module API def feature_flags return [] unless unleash_app_name.present? - legacy_flags = - if exclude_legacy_flags? - [] - else - Operations::FeatureFlagScope.for_unleash_client(project, unleash_app_name) - end - - new_version_flags = Operations::FeatureFlag.for_unleash_client(project, unleash_app_name) - - legacy_flags + new_version_flags - end - - def exclude_legacy_flags? - Feature.enabled?(:remove_legacy_flags, project, default_enabled: :yaml) && - Feature.disabled?(:remove_legacy_flags_override, project, default_enabled: :yaml) + Operations::FeatureFlag.for_unleash_client(project, unleash_app_name) end end end diff --git a/lib/gitlab/ci/config/entry/reports.rb b/lib/gitlab/ci/config/entry/reports.rb index b34ab67cf04..4db25fb0930 100644 --- a/lib/gitlab/ci/config/entry/reports.rb +++ b/lib/gitlab/ci/config/entry/reports.rb @@ -43,7 +43,7 @@ module Gitlab validates :cobertura, array_of_strings_or_string: true validates :terraform, array_of_strings_or_string: true validates :accessibility, array_of_strings_or_string: true - validates :cluster_applications, array_of_strings_or_string: true + validates :cluster_applications, array_of_strings_or_string: true # DEPRECATED: https://gitlab.com/gitlab-org/gitlab/-/issues/333441 validates :requirements, array_of_strings_or_string: true end end diff --git a/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml b/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml index be8d56ccf93..ca63e942130 100644 --- a/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml @@ -27,8 +27,6 @@ apply: variables: - $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH artifacts: - reports: - cluster_applications: gl-cluster-applications.json when: on_failure paths: - tiller.log diff --git a/lib/gitlab/kubernetes/helm/parsers/list_v2.rb b/lib/gitlab/kubernetes/helm/parsers/list_v2.rb deleted file mode 100644 index c5c5d198a6c..00000000000 --- a/lib/gitlab/kubernetes/helm/parsers/list_v2.rb +++ /dev/null @@ -1,37 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module Kubernetes - module Helm - module Parsers - # Parses Helm v2 list (JSON) output - class ListV2 - ParserError = Class.new(StandardError) - - attr_reader :contents, :json - - def initialize(contents) - @contents = contents - @json = Gitlab::Json.parse(contents) - rescue JSON::ParserError => e - raise ParserError, e.message - end - - def releases - @releases = helm_releases - end - - private - - def helm_releases - helm_releases = json['Releases'] || [] - - raise ParserError, 'Invalid format for Releases' unless helm_releases.all? { |item| item.is_a?(Hash) } - - helm_releases - end - end - end - end - end -end diff --git a/lib/gitlab/project_search_results.rb b/lib/gitlab/project_search_results.rb index 6719dc8362b..e52023c4612 100644 --- a/lib/gitlab/project_search_results.rb +++ b/lib/gitlab/project_search_results.rb @@ -43,9 +43,20 @@ module Gitlab end end + # rubocop:disable CodeReuse/ActiveRecord def users - super.where(id: @project.team.members) # rubocop:disable CodeReuse/ActiveRecord + results = super + + if @project.is_a?(Array) + team_members_for_projects = User.joins(:project_authorizations).where(project_authorizations: { project_id: @project }) + results = results.where(id: team_members_for_projects) + else + results = results.where(id: @project.team.members) + end + + results end + # rubocop:enable CodeReuse/ActiveRecord def limited_blobs_count @limited_blobs_count ||= blobs(limit: count_limit).count diff --git a/locale/gitlab.pot b/locale/gitlab.pot index db9ce5233b7..bd30ecd1aa6 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -4521,9 +4521,6 @@ msgstr "" msgid "At least one approval from a code owner is required to change files matching the respective CODEOWNER rules." msgstr "" -msgid "At least one logging option is required to be enabled" -msgstr "" - msgid "At least one of group_id or project_id must be specified" msgstr "" @@ -7075,9 +7072,6 @@ msgstr "" msgid "ClusterIntegration|Cluster name is required." msgstr "" -msgid "ClusterIntegration|Cluster_applications artifact too big. Maximum allowable size: %{human_size}" -msgstr "" - msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}" msgstr "" @@ -7282,9 +7276,6 @@ msgstr "" msgid "ClusterIntegration|HTTP Error" msgstr "" -msgid "ClusterIntegration|Helm release failed to install" -msgstr "" - msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}." msgstr "" @@ -7444,12 +7435,6 @@ msgstr "" msgid "ClusterIntegration|No VPCs found" msgstr "" -msgid "ClusterIntegration|No deployment cluster found for this job" -msgstr "" - -msgid "ClusterIntegration|No deployment found for this job" -msgstr "" - msgid "ClusterIntegration|No instance type found" msgstr "" diff --git a/package.json b/package.json index d81030cb666..ba6616fc280 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "@gitlab/favicon-overlay": "2.0.0", "@gitlab/svgs": "1.199.0", "@gitlab/tributejs": "1.0.0", - "@gitlab/ui": "29.34.0", + "@gitlab/ui": "29.34.1", "@gitlab/visual-review-tools": "1.6.1", "@rails/actioncable": "6.1.3-2", "@rails/ujs": "6.1.3-2", diff --git a/spec/controllers/projects/feature_flags_controller_spec.rb b/spec/controllers/projects/feature_flags_controller_spec.rb index 752e8b652e0..f809dd31b3b 100644 --- a/spec/controllers/projects/feature_flags_controller_spec.rb +++ b/spec/controllers/projects/feature_flags_controller_spec.rb @@ -154,60 +154,6 @@ RSpec.describe Projects::FeatureFlagsController do end end - context 'when feature flags have additional scopes' do - let!(:feature_flag_active_scope) do - create(:operations_feature_flag_scope, - feature_flag: feature_flag_active, - environment_scope: 'production', - active: false) - end - - let!(:feature_flag_inactive_scope) do - create(:operations_feature_flag_scope, - feature_flag: feature_flag_inactive, - environment_scope: 'staging', - active: false) - end - - it 'returns a correct summary' do - subject - - expect(json_response['count']['all']).to eq(2) - expect(json_response['count']['enabled']).to eq(1) - expect(json_response['count']['disabled']).to eq(1) - end - - it 'recognizes feature flag 1 as active' do - subject - - expect(json_response['feature_flags'].first['active']).to be_truthy - end - - it 'recognizes feature flag 2 as inactive' do - subject - - expect(json_response['feature_flags'].second['active']).to be_falsy - end - - it 'has ordered scopes' do - subject - - expect(json_response['feature_flags'][0]['scopes'][0]['id']) - .to be < json_response['feature_flags'][0]['scopes'][1]['id'] - expect(json_response['feature_flags'][1]['scopes'][0]['id']) - .to be < json_response['feature_flags'][1]['scopes'][1]['id'] - end - - it 'does not have N+1 problem' do - recorded = ActiveRecord::QueryRecorder.new { subject } - - related_count = recorded.log - .count { |query| query.include?('operations_feature_flag') } - - expect(related_count).to be_within(5).of(2) - end - end - context 'with version 1 and 2 feature flags' do let!(:new_version_feature_flag) do create(:operations_feature_flag, :new_version_flag, project: project, name: 'feature_flag_c') @@ -235,7 +181,7 @@ RSpec.describe Projects::FeatureFlagsController do subject { get(:show, params: params, format: :json) } let!(:feature_flag) do - create(:operations_feature_flag, project: project) + create(:operations_feature_flag, :legacy_flag, project: project) end let(:params) do @@ -375,7 +321,7 @@ RSpec.describe Projects::FeatureFlagsController do subject { get(:edit, params: params) } context 'with legacy flags' do - let!(:feature_flag) { create(:operations_feature_flag, project: project) } + let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag, project: project) } let(:params) do { @@ -385,29 +331,13 @@ RSpec.describe Projects::FeatureFlagsController do } end - context 'removed' do - before do - stub_feature_flags(remove_legacy_flags: true, remove_legacy_flags_override: false) - end - - it 'returns not found' do - is_expected.to have_gitlab_http_status(:not_found) - end - end - - context 'removed' do - before do - stub_feature_flags(remove_legacy_flags: false) - end - - it 'returns ok' do - is_expected.to have_gitlab_http_status(:ok) - end + it 'returns not found' do + is_expected.to have_gitlab_http_status(:not_found) end end context 'with new version flags' do - let!(:feature_flag) { create(:operations_feature_flag, :new_version_flag, project: project) } + let!(:feature_flag) { create(:operations_feature_flag, project: project) } let(:params) do { @@ -814,7 +744,7 @@ RSpec.describe Projects::FeatureFlagsController do describe 'DELETE destroy.json' do subject { delete(:destroy, params: params, format: :json) } - let!(:feature_flag) { create(:operations_feature_flag, project: project) } + let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag, project: project) } let(:params) do { diff --git a/spec/factories/ci/job_artifacts.rb b/spec/factories/ci/job_artifacts.rb index 17cd495e217..642437b1119 100644 --- a/spec/factories/ci/job_artifacts.rb +++ b/spec/factories/ci/job_artifacts.rb @@ -317,21 +317,6 @@ FactoryBot.define do end end - trait :cluster_applications do - file_type { :cluster_applications } - file_format { :gzip } - - transient do - file do - fixture_file_upload(Rails.root.join('spec/fixtures/helm/helm_list_v2_prometheus_missing.json.gz'), 'application/x-gzip') - end - end - - after(:build) do |artifact, evaluator| - artifact.file = evaluator.file - end - end - trait :correct_checksum do after(:build) do |artifact, evaluator| artifact.file_sha256 = Digest::SHA256.file(artifact.file.path).hexdigest diff --git a/spec/factories/clusters/applications/helm.rb b/spec/factories/clusters/applications/helm.rb index 73103956ee8..29197768ec0 100644 --- a/spec/factories/clusters/applications/helm.rb +++ b/spec/factories/clusters/applications/helm.rb @@ -132,12 +132,6 @@ FactoryBot.define do cluster factory: %i(cluster with_installed_helm provided_by_gcp project) end - factory :clusters_applications_fluentd, class: 'Clusters::Applications::Fluentd' do - host { 'example.com' } - cilium_log_enabled { true } - cluster factory: %i(cluster with_installed_helm provided_by_gcp) - end - factory :clusters_applications_cilium, class: 'Clusters::Applications::Cilium' do cluster factory: %i(cluster with_installed_helm provided_by_gcp) end diff --git a/spec/factories/clusters/clusters.rb b/spec/factories/clusters/clusters.rb index 3d0435cfe1d..dfe1b587951 100644 --- a/spec/factories/clusters/clusters.rb +++ b/spec/factories/clusters/clusters.rb @@ -101,7 +101,6 @@ FactoryBot.define do application_jupyter factory: %i(clusters_applications_jupyter installed) application_knative factory: %i(clusters_applications_knative installed) application_elastic_stack factory: %i(clusters_applications_elastic_stack installed) - application_fluentd factory: %i(clusters_applications_fluentd installed) application_cilium factory: %i(clusters_applications_cilium installed) end diff --git a/spec/factories/operations/feature_flag_scopes.rb b/spec/factories/operations/feature_flag_scopes.rb index a98c397b8b5..4ca9b53f320 100644 --- a/spec/factories/operations/feature_flag_scopes.rb +++ b/spec/factories/operations/feature_flag_scopes.rb @@ -2,7 +2,7 @@ FactoryBot.define do factory :operations_feature_flag_scope, class: 'Operations::FeatureFlagScope' do - association :feature_flag, factory: :operations_feature_flag + association :feature_flag, factory: [:operations_feature_flag, :legacy_flag] active { true } strategies { [{ name: "default", parameters: {} }] } sequence(:environment_scope) { |n| "review/patch-#{n}" } diff --git a/spec/factories/operations/feature_flags.rb b/spec/factories/operations/feature_flags.rb index 7e43d38a04f..32e5ec9fb26 100644 --- a/spec/factories/operations/feature_flags.rb +++ b/spec/factories/operations/feature_flags.rb @@ -5,6 +5,7 @@ FactoryBot.define do sequence(:name) { |n| "feature_flag_#{n}" } project active { true } + version { :new_version_flag } trait :legacy_flag do version { Operations::FeatureFlag.versions['legacy_flag'] } diff --git a/spec/features/projects/feature_flags/user_sees_feature_flag_list_spec.rb b/spec/features/projects/feature_flags/user_sees_feature_flag_list_spec.rb index 50fc7bb0753..d922bc1f4a0 100644 --- a/spec/features/projects/feature_flags/user_sees_feature_flag_list_spec.rb +++ b/spec/features/projects/feature_flags/user_sees_feature_flag_list_spec.rb @@ -18,65 +18,21 @@ RSpec.describe 'User sees feature flag list', :js do context 'with legacy feature flags' do before do - create_flag(project, 'ci_live_trace', false).tap do |feature_flag| + create_flag(project, 'ci_live_trace', false, version: :legacy_flag).tap do |feature_flag| create_scope(feature_flag, 'review/*', true) end - create_flag(project, 'drop_legacy_artifacts', false) - create_flag(project, 'mr_train', true).tap do |feature_flag| + create_flag(project, 'drop_legacy_artifacts', false, version: :legacy_flag) + create_flag(project, 'mr_train', true, version: :legacy_flag).tap do |feature_flag| create_scope(feature_flag, 'production', false) end end - it 'user sees the first flag' do - visit(project_feature_flags_path(project)) - - within_feature_flag_row(1) do - expect(page.find('.js-feature-flag-id')).to have_content('^1') - expect(page.find('.feature-flag-name')).to have_content('ci_live_trace') - expect_status_toggle_button_not_to_be_checked - - within_feature_flag_scopes do - expect(page.find('[data-qa-selector="feature-flag-scope-muted-badge"]:nth-child(1)')).to have_content('*') - expect(page.find('[data-qa-selector="feature-flag-scope-info-badge"]:nth-child(2)')).to have_content('review/*') - end - end - end - - it 'user sees the second flag' do - visit(project_feature_flags_path(project)) - - within_feature_flag_row(2) do - expect(page.find('.js-feature-flag-id')).to have_content('^2') - expect(page.find('.feature-flag-name')).to have_content('drop_legacy_artifacts') - expect_status_toggle_button_not_to_be_checked - - within_feature_flag_scopes do - expect(page.find('[data-qa-selector="feature-flag-scope-muted-badge"]:nth-child(1)')).to have_content('*') - end - end - end - - it 'user sees the third flag' do - visit(project_feature_flags_path(project)) - - within_feature_flag_row(3) do - expect(page.find('.js-feature-flag-id')).to have_content('^3') - expect(page.find('.feature-flag-name')).to have_content('mr_train') - expect_status_toggle_button_to_be_checked - - within_feature_flag_scopes do - expect(page.find('[data-qa-selector="feature-flag-scope-info-badge"]:nth-child(1)')).to have_content('*') - expect(page.find('[data-qa-selector="feature-flag-scope-muted-badge"]:nth-child(2)')).to have_content('production') - end - end - end - - it 'user sees the status toggle disabled' do + it 'shows empty page' do visit(project_feature_flags_path(project)) - within_feature_flag_row(1) do - expect_status_toggle_button_to_be_disabled - end + expect(page).to have_text 'Get started with feature flags' + expect(page).to have_selector('.btn-confirm', text: 'New feature flag') + expect(page).to have_selector('[data-qa-selector="configure_feature_flags_button"]', text: 'Configure') end end diff --git a/spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb b/spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb index a435e565ff1..9c03a26abc8 100644 --- a/spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb +++ b/spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb @@ -73,16 +73,16 @@ RSpec.describe 'User updates feature flag', :js do context 'with a legacy feature flag' do let!(:feature_flag) do create_flag(project, 'ci_live_trace', true, - description: 'For live trace feature') + description: 'For live trace feature', + version: :legacy_flag) end let!(:scope) { create_scope(feature_flag, 'review/*', true) } - it 'the user cannot edit the flag' do + it 'shows not found error' do visit(edit_project_feature_flag_path(project, feature_flag)) - expect(page).to have_text 'This feature flag is read-only, and it will be removed in 14.0.' - expect(page).to have_css('button.js-ff-submit.disabled') + expect(page).to have_text 'Page Not Found' end end end diff --git a/spec/finders/feature_flags_finder_spec.rb b/spec/finders/feature_flags_finder_spec.rb index 4da5e954157..4faa6a62a1f 100644 --- a/spec/finders/feature_flags_finder_spec.rb +++ b/spec/finders/feature_flags_finder_spec.rb @@ -24,10 +24,6 @@ RSpec.describe FeatureFlagsFinder do let!(:feature_flag_2) { create(:operations_feature_flag, name: 'flag-b', project: project) } let(:args) { {} } - before do - stub_feature_flags(remove_legacy_flags: false) - end - it 'returns feature flags ordered by name' do is_expected.to eq([feature_flag_1, feature_flag_2]) end @@ -77,21 +73,11 @@ RSpec.describe FeatureFlagsFinder do end end - context 'when new version flags are enabled' do - let!(:feature_flag_3) { create(:operations_feature_flag, :new_version_flag, name: 'flag-c', project: project) } - - it 'returns new and legacy flags' do - is_expected.to eq([feature_flag_1, feature_flag_2, feature_flag_3]) - end + context 'with a legacy flag' do + let!(:feature_flag_3) { create(:operations_feature_flag, :legacy_flag, name: 'flag-c', project: project) } - context 'when legacy flags are disabled' do - before do - stub_feature_flags(remove_legacy_flags_override: false, remove_legacy_flags: true) - end - - it 'returns only new flags' do - is_expected.to eq([feature_flag_3]) - end + it 'returns new flags' do + is_expected.to eq([feature_flag_1, feature_flag_2]) end end end diff --git a/spec/fixtures/api/schemas/cluster_status.json b/spec/fixtures/api/schemas/cluster_status.json index c919cd54a28..ce62655648b 100644 --- a/spec/fixtures/api/schemas/cluster_status.json +++ b/spec/fixtures/api/schemas/cluster_status.json @@ -42,7 +42,6 @@ "host": {"type": ["string", "null"]}, "port": {"type": ["integer", "514"]}, "protocol": {"type": ["integer", "0"]}, - "cilium_log_enabled": {"type": ["boolean", "true"]}, "update_available": { "type": ["boolean", "null"] }, "can_uninstall": { "type": "boolean" }, "available_domains": { diff --git a/spec/fixtures/helm/helm_list_v2_cilium_deployed.json.gz b/spec/fixtures/helm/helm_list_v2_cilium_deployed.json.gz Binary files differdeleted file mode 100644 index a343356c95c..00000000000 --- a/spec/fixtures/helm/helm_list_v2_cilium_deployed.json.gz +++ /dev/null diff --git a/spec/fixtures/helm/helm_list_v2_cilium_failed.json.gz b/spec/fixtures/helm/helm_list_v2_cilium_failed.json.gz Binary files differdeleted file mode 100644 index f7faff2ca19..00000000000 --- a/spec/fixtures/helm/helm_list_v2_cilium_failed.json.gz +++ /dev/null diff --git a/spec/fixtures/helm/helm_list_v2_cilium_missing.json.gz b/spec/fixtures/helm/helm_list_v2_cilium_missing.json.gz Binary files differdeleted file mode 100644 index 20cac36287b..00000000000 --- a/spec/fixtures/helm/helm_list_v2_cilium_missing.json.gz +++ /dev/null diff --git a/spec/fixtures/helm/helm_list_v2_empty_blob.json.gz b/spec/fixtures/helm/helm_list_v2_empty_blob.json.gz Binary files differdeleted file mode 100644 index 5647f052c3b..00000000000 --- a/spec/fixtures/helm/helm_list_v2_empty_blob.json.gz +++ /dev/null diff --git a/spec/fixtures/helm/helm_list_v2_prometheus_deployed.json.gz b/spec/fixtures/helm/helm_list_v2_prometheus_deployed.json.gz Binary files differdeleted file mode 100644 index bcbbba8dc00..00000000000 --- a/spec/fixtures/helm/helm_list_v2_prometheus_deployed.json.gz +++ /dev/null diff --git a/spec/fixtures/helm/helm_list_v2_prometheus_failed.json.gz b/spec/fixtures/helm/helm_list_v2_prometheus_failed.json.gz Binary files differdeleted file mode 100644 index 0b39b42bdfa..00000000000 --- a/spec/fixtures/helm/helm_list_v2_prometheus_failed.json.gz +++ /dev/null diff --git a/spec/fixtures/helm/helm_list_v2_prometheus_missing.json.gz b/spec/fixtures/helm/helm_list_v2_prometheus_missing.json.gz Binary files differdeleted file mode 100644 index 20cac36287b..00000000000 --- a/spec/fixtures/helm/helm_list_v2_prometheus_missing.json.gz +++ /dev/null diff --git a/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric.yml b/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric.yml index 90d395e1eda..f694e617320 100644 --- a/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric.yml +++ b/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric.yml @@ -12,6 +12,7 @@ milestone: "13.9" introduced_by_url: time_frame: 7d data_source: +data_category: Operational distribution: - ce # Add here corresponding tiers diff --git a/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_ee.yml b/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_ee.yml index c51b5bf6e01..5cebfbcbad9 100644 --- a/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_ee.yml +++ b/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_ee.yml @@ -12,6 +12,7 @@ milestone: "13.9" introduced_by_url: time_frame: 7d data_source: +data_category: Operational distribution: - ee tier: diff --git a/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_name_suggestions.yml b/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_name_suggestions.yml index c1ed9783308..d448e7bf3f6 100644 --- a/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_name_suggestions.yml +++ b/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_name_suggestions.yml @@ -13,6 +13,7 @@ milestone: "13.9" introduced_by_url: time_frame: 7d data_source: +data_category: Operational distribution: - ce - ee diff --git a/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap b/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap index f4e617ecafe..b576f1b2553 100644 --- a/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap +++ b/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap @@ -11,7 +11,7 @@ exports[`packages_list_row renders 1`] = ` <!----> <div - class="gl-display-flex gl-xs-flex-direction-column gl-justify-content-space-between gl-align-items-stretch gl-flex-fill-1" + class="gl-display-flex gl-xs-flex-direction-column gl-justify-content-space-between gl-align-items-stretch gl-flex-grow-1" > <div class="gl-display-flex gl-flex-direction-column gl-xs-mb-3 gl-min-w-0 gl-flex-grow-1" @@ -42,7 +42,7 @@ exports[`packages_list_row renders 1`] = ` </div> <div - class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-min-h-6 gl-min-w-0 gl-flex-fill-1" + class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-min-h-6 gl-min-w-0 gl-flex-grow-1" > <div class="gl-display-flex" diff --git a/spec/frontend/runner/runner_list/filtered_search_utils_spec.js b/spec/frontend/runner/runner_list/runner_search_utils_spec.js index abbe05452d1..a1f33e9c880 100644 --- a/spec/frontend/runner/runner_list/filtered_search_utils_spec.js +++ b/spec/frontend/runner/runner_list/runner_search_utils_spec.js @@ -3,7 +3,7 @@ import { fromUrlQueryToSearch, fromSearchToUrl, fromSearchToVariables, -} from '~/runner/runner_list/filtered_search_utils'; +} from '~/runner/runner_list/runner_search_utils'; describe('search_params.js', () => { const examples = [ @@ -24,6 +24,40 @@ describe('search_params.js', () => { graphqlVariables: { status: 'ACTIVE', sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE }, }, { + name: 'a single term text search', + urlQuery: '?search=something', + search: { + filters: [ + { + type: 'filtered-search-term', + value: { data: 'something' }, + }, + ], + pagination: { page: 1 }, + sort: 'CREATED_DESC', + }, + graphqlVariables: { search: 'something', sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE }, + }, + { + name: 'a two terms text search', + urlQuery: '?search=something+else', + search: { + filters: [ + { + type: 'filtered-search-term', + value: { data: 'something' }, + }, + { + type: 'filtered-search-term', + value: { data: 'else' }, + }, + ], + pagination: { page: 1 }, + sort: 'CREATED_DESC', + }, + graphqlVariables: { search: 'something else', sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE }, + }, + { name: 'single instance type', urlQuery: '?runner_type[]=INSTANCE_TYPE', search: { @@ -110,6 +144,13 @@ describe('search_params.js', () => { }); }); + it('When search params appear as array, they are concatenated', () => { + expect(fromUrlQueryToSearch('?search[]=my&search[]=text').filters).toEqual([ + { type: 'filtered-search-term', value: { data: 'my' } }, + { type: 'filtered-search-term', value: { data: 'text' } }, + ]); + }); + it('When a page cannot be parsed as a number, it defaults to `1`', () => { expect(fromUrlQueryToSearch('?page=NONSENSE&after=AFTER_CURSOR').pagination).toEqual({ page: 1, @@ -136,12 +177,15 @@ describe('search_params.js', () => { }); }); - it('When a filtered search parameter is already present, it gets removed', () => { - const initialUrl = `http://test.host/?status[]=ACTIVE`; + it.each([ + 'http://test.host/?status[]=ACTIVE', + 'http://test.host/?runner_type[]=INSTANCE_TYPE', + 'http://test.host/?search=my_text', + ])('When a filter is removed, it is removed from the URL', (initalUrl) => { const search = { filters: [], sort: 'CREATED_DESC' }; const expectedUrl = `http://test.host/`; - expect(fromSearchToUrl(search, initialUrl)).toEqual(expectedUrl); + expect(fromSearchToUrl(search, initalUrl)).toEqual(expectedUrl); }); it('When unrelated search parameter is present, it does not get removed', () => { @@ -159,5 +203,37 @@ describe('search_params.js', () => { expect(fromSearchToVariables(search)).toEqual(graphqlVariables); }); }); + + it('When a search param is empty, it gets removed', () => { + expect( + fromSearchToVariables({ + filters: [ + { + type: 'filtered-search-term', + value: { data: '' }, + }, + ], + }), + ).toMatchObject({ + search: '', + }); + + expect( + fromSearchToVariables({ + filters: [ + { + type: 'filtered-search-term', + value: { data: 'something' }, + }, + { + type: 'filtered-search-term', + value: { data: '' }, + }, + ], + }), + ).toMatchObject({ + search: 'something', + }); + }); }); }); diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js index b2ed79cd75a..93cddff8421 100644 --- a/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js +++ b/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js @@ -1,6 +1,9 @@ import { useLocalStorageSpy } from 'helpers/local_storage_helper'; import AccessorUtilities from '~/lib/utils/accessor'; + +import { FILTERED_SEARCH_TERM } from '~/vue_shared/components/filtered_search_bar/constants'; + import { stripQuotes, uniqueTokens, @@ -210,6 +213,19 @@ describe('filterToQueryObject', () => { const res = filterToQueryObject({ [token]: value }); expect(res).toEqual(result); }); + + it.each([ + [FILTERED_SEARCH_TERM, [{ value: '' }], { search: '' }], + [FILTERED_SEARCH_TERM, [{ value: 'bar' }], { search: 'bar' }], + [FILTERED_SEARCH_TERM, [{ value: 'bar' }, { value: '' }], { search: 'bar' }], + [FILTERED_SEARCH_TERM, [{ value: 'bar' }, { value: 'baz' }], { search: 'bar baz' }], + ])( + 'when filteredSearchTermKey=search gathers filter values %s=%j into query object=%j', + (token, value, result) => { + const res = filterToQueryObject({ [token]: value }, { filteredSearchTermKey: 'search' }); + expect(res).toEqual(result); + }, + ); }); describe('urlQueryToFilter', () => { @@ -255,10 +271,61 @@ describe('urlQueryToFilter', () => { }, ], ['not[foo][]=bar', { foo: [{ value: 'bar', operator: '!=' }] }], - ])('gathers filter values %s into query object=%j', (query, result) => { - const res = urlQueryToFilter(query); - expect(res).toEqual(result); - }); + ['nop=1¬[nop]=2', {}, { filterNamesAllowList: ['foo'] }], + [ + 'foo[]=bar¬[foo][]=baz&nop=xxx¬[nop]=yyy', + { + foo: [ + { value: 'bar', operator: '=' }, + { value: 'baz', operator: '!=' }, + ], + }, + { filterNamesAllowList: ['foo'] }, + ], + [ + 'search=term&foo=bar', + { + [FILTERED_SEARCH_TERM]: [{ value: 'term' }], + foo: { value: 'bar', operator: '=' }, + }, + { filteredSearchTermKey: 'search' }, + ], + [ + 'search=my terms', + { + [FILTERED_SEARCH_TERM]: [{ value: 'my' }, { value: 'terms' }], + }, + { filteredSearchTermKey: 'search' }, + ], + [ + 'search[]=my&search[]=terms', + { + [FILTERED_SEARCH_TERM]: [{ value: 'my' }, { value: 'terms' }], + }, + { filteredSearchTermKey: 'search' }, + ], + [ + 'search=my+terms', + { + [FILTERED_SEARCH_TERM]: [{ value: 'my' }, { value: 'terms' }], + }, + { filteredSearchTermKey: 'search', legacySpacesDecode: false }, + ], + [ + 'search=my terms&foo=bar&nop=xxx', + { + [FILTERED_SEARCH_TERM]: [{ value: 'my' }, { value: 'terms' }], + foo: { value: 'bar', operator: '=' }, + }, + { filteredSearchTermKey: 'search', filterNamesAllowList: ['foo'] }, + ], + ])( + 'gathers filter values %s into query object=%j when options %j', + (query, result, options = undefined) => { + const res = urlQueryToFilter(query, options); + expect(res).toEqual(result); + }, + ); }); describe('getRecentlyUsedTokenValues', () => { diff --git a/spec/graphql/resolvers/concerns/caching_array_resolver_spec.rb b/spec/graphql/resolvers/concerns/caching_array_resolver_spec.rb index e9e7fff6e6e..8d15d7eda1b 100644 --- a/spec/graphql/resolvers/concerns/caching_array_resolver_spec.rb +++ b/spec/graphql/resolvers/concerns/caching_array_resolver_spec.rb @@ -4,7 +4,6 @@ require 'spec_helper' RSpec.describe ::CachingArrayResolver do include GraphqlHelpers - include Gitlab::Graphql::Laziness let_it_be(:admins) { create_list(:user, 4, admin: true) } let(:query_context) { { current_user: admins.first } } diff --git a/spec/graphql/resolvers/package_details_resolver_spec.rb b/spec/graphql/resolvers/package_details_resolver_spec.rb index 1bdc069b3bb..d6acb31d4e3 100644 --- a/spec/graphql/resolvers/package_details_resolver_spec.rb +++ b/spec/graphql/resolvers/package_details_resolver_spec.rb @@ -4,7 +4,6 @@ require 'spec_helper' RSpec.describe Resolvers::PackageDetailsResolver do include GraphqlHelpers - include ::Gitlab::Graphql::Laziness let_it_be_with_reload(:project) { create(:project) } let_it_be(:user) { project.owner } diff --git a/spec/lib/gitlab/kubernetes/helm/parsers/list_v2_spec.rb b/spec/lib/gitlab/kubernetes/helm/parsers/list_v2_spec.rb deleted file mode 100644 index 435c296d5f1..00000000000 --- a/spec/lib/gitlab/kubernetes/helm/parsers/list_v2_spec.rb +++ /dev/null @@ -1,100 +0,0 @@ -# frozen_string_literal: true - -require 'fast_spec_helper' - -RSpec.describe Gitlab::Kubernetes::Helm::Parsers::ListV2 do - let(:valid_file_contents) do - <<~EOF - { - "Next": "", - "Releases": [ - { - "Name": "certmanager", - "Revision": 2, - "Updated": "Sun Mar 29 06:55:42 2020", - "Status": "DEPLOYED", - "Chart": "cert-manager-v0.10.1", - "AppVersion": "v0.10.1", - "Namespace": "gitlab-managed-apps" - }, - { - "Name": "certmanager-crds", - "Revision": 2, - "Updated": "Sun Mar 29 06:55:32 2020", - "Status": "DEPLOYED", - "Chart": "cert-manager-crds-v0.2.0", - "AppVersion": "release-0.10", - "Namespace": "gitlab-managed-apps" - }, - { - "Name": "certmanager-issuer", - "Revision": 1, - "Updated": "Tue Feb 18 10:04:04 2020", - "Status": "FAILED", - "Chart": "cert-manager-issuer-v0.1.0", - "AppVersion": "", - "Namespace": "gitlab-managed-apps" - }, - { - "Name": "runner", - "Revision": 2, - "Updated": "Sun Mar 29 07:01:01 2020", - "Status": "DEPLOYED", - "Chart": "gitlab-runner-0.14.0", - "AppVersion": "12.8.0", - "Namespace": "gitlab-managed-apps" - } - ] - } - EOF - end - - describe '#initialize' do - it 'initializes without error' do - expect do - described_class.new(valid_file_contents) - end.not_to raise_error - end - - it 'raises an error on invalid JSON' do - expect do - described_class.new('') - end.to raise_error(described_class::ParserError) - end - end - - describe '#releases' do - subject(:list_v2) { described_class.new(valid_file_contents) } - - it 'returns list of releases' do - expect(list_v2.releases).to match([ - a_hash_including('Name' => 'certmanager', 'Status' => 'DEPLOYED'), - a_hash_including('Name' => 'certmanager-crds', 'Status' => 'DEPLOYED'), - a_hash_including('Name' => 'certmanager-issuer', 'Status' => 'FAILED'), - a_hash_including('Name' => 'runner', 'Status' => 'DEPLOYED') - ]) - end - - context 'empty Releases' do - let(:valid_file_contents) { '{}' } - - it 'returns an empty array' do - expect(list_v2.releases).to eq([]) - end - end - - context 'invalid Releases' do - let(:invalid_file_contents) do - '{ "Releases" : ["a", "b"] }' - end - - subject(:list_v2) { described_class.new(invalid_file_contents) } - - it 'raises an error' do - expect do - list_v2.releases - end.to raise_error(described_class::ParserError, 'Invalid format for Releases') - end - end - end -end diff --git a/spec/lib/gitlab/project_search_results_spec.rb b/spec/lib/gitlab/project_search_results_spec.rb index a76ad1f6f4c..2f28b8dfce0 100644 --- a/spec/lib/gitlab/project_search_results_spec.rb +++ b/spec/lib/gitlab/project_search_results_spec.rb @@ -549,30 +549,39 @@ RSpec.describe Gitlab::ProjectSearchResults do describe 'user search' do let(:query) { 'gob' } - let(:group) { create(:group) } - let(:project) { create(:project, namespace: group) } + + let_it_be(:user_1) { create(:user, username: 'gob_bluth') } + let_it_be(:user_2) { create(:user, username: 'michael_bluth') } + let_it_be(:user_3) { create(:user, username: 'gob_2018') } + let_it_be(:group) { create(:group) } + let_it_be(:project) { create(:project, namespace: group) } subject(:objects) { results.objects('users') } it 'returns the user belonging to the project matching the search query' do - user1 = create(:user, username: 'gob_bluth') - create(:project_member, :developer, user: user1, project: project) + create(:project_member, :developer, user: user_1, project: project) + create(:project_member, :developer, user: user_2, project: project) - user2 = create(:user, username: 'michael_bluth') - create(:project_member, :developer, user: user2, project: project) + expect(objects).to contain_exactly(user_1) + end - create(:user, username: 'gob_2018') + it 'returns the user belonging to the group matching the search query' do + create(:group_member, :developer, user: user_1, group: group) - expect(objects).to contain_exactly(user1) + expect(objects).to contain_exactly(user_1) end - it 'returns the user belonging to the group matching the search query' do - user1 = create(:user, username: 'gob_bluth') - create(:group_member, :developer, user: user1, group: group) + context 'when multiple projects provided' do + let_it_be(:project_2) { create(:project, namespace: group) } + + subject(:results) { described_class.new(user, query, project: [project, project_2], repository_ref: repository_ref, filters: filters) } - create(:user, username: 'gob_2018') + it 'returns users belonging to projects matching the search query' do + create(:project_member, :developer, user: user_1, project: project) + create(:project_member, :developer, user: user_3, project: project_2) - expect(objects).to contain_exactly(user1) + expect(objects).to contain_exactly(user_1, user_3) + end end end end diff --git a/spec/models/clusters/applications/fluentd_spec.rb b/spec/models/clusters/applications/fluentd_spec.rb deleted file mode 100644 index a4df44225f3..00000000000 --- a/spec/models/clusters/applications/fluentd_spec.rb +++ /dev/null @@ -1,71 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Clusters::Applications::Fluentd do - let(:cilium_log_enabled) { true } - let(:fluentd) { create(:clusters_applications_fluentd, cilium_log_enabled: cilium_log_enabled) } - - include_examples 'cluster application core specs', :clusters_applications_fluentd - include_examples 'cluster application status specs', :clusters_applications_fluentd - include_examples 'cluster application version specs', :clusters_applications_fluentd - include_examples 'cluster application initial status specs' - - describe '#can_uninstall?' do - subject { fluentd.can_uninstall? } - - it { is_expected.to be true } - end - - describe '#install_command' do - subject { fluentd.install_command } - - it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::InstallCommand) } - - it 'is initialized with fluentd arguments' do - expect(subject.name).to eq('fluentd') - expect(subject.chart).to eq('fluentd/fluentd') - expect(subject.version).to eq('2.4.0') - expect(subject).to be_rbac - end - - context 'application failed to install previously' do - let(:fluentd) { create(:clusters_applications_fluentd, :errored, version: '0.0.1') } - - it 'is initialized with the locked version' do - expect(subject.version).to eq('2.4.0') - end - end - end - - describe '#files' do - let(:application) { fluentd } - let(:values) { subject[:'values.yaml'] } - - subject { application.files } - - it 'includes fluentd specific keys in the values.yaml file' do - expect(values).to include('output.conf', 'general.conf') - end - end - - describe '#values' do - let(:cilium_log_path) { "/var/log/containers/*#{described_class::CILIUM_CONTAINER_NAME}*.log" } - - subject { fluentd.values } - - context 'with cilium_log_enabled set to false' do - let(:cilium_log_enabled) { false } - - it "raises ActiveRecord::RecordInvalid" do - expect {subject}.to raise_error(ActiveRecord::RecordInvalid) - end - end - - context 'with cilium_log_enabled set to true' do - let(:cilium_log_enabled) { true } - - it { is_expected.to include(cilium_log_path) } - end - end -end diff --git a/spec/models/operations/feature_flag_scope_spec.rb b/spec/models/operations/feature_flag_scope_spec.rb index 29d338d8b29..dc83789fade 100644 --- a/spec/models/operations/feature_flag_scope_spec.rb +++ b/spec/models/operations/feature_flag_scope_spec.rb @@ -29,7 +29,7 @@ RSpec.describe Operations::FeatureFlagScope do end context 'when environment scope of a default scope is updated' do - let!(:feature_flag) { create(:operations_feature_flag) } + let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag) } let!(:scope_default) { feature_flag.default_scope } it 'keeps default scope intact' do @@ -41,7 +41,7 @@ RSpec.describe Operations::FeatureFlagScope do end context 'when a default scope is destroyed' do - let!(:feature_flag) { create(:operations_feature_flag) } + let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag) } let!(:scope_default) { feature_flag.default_scope } it 'prevents from destroying the default scope' do diff --git a/spec/models/operations/feature_flag_spec.rb b/spec/models/operations/feature_flag_spec.rb index d5b3c7a8582..55682e12642 100644 --- a/spec/models/operations/feature_flag_spec.rb +++ b/spec/models/operations/feature_flag_spec.rb @@ -181,7 +181,7 @@ RSpec.describe Operations::FeatureFlag do end context 'when the feature flag is active and all scopes are inactive' do - let!(:feature_flag) { create(:operations_feature_flag, active: true) } + let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag, active: true) } it 'returns the flag' do feature_flag.default_scope.update!(active: false) @@ -199,7 +199,7 @@ RSpec.describe Operations::FeatureFlag do end context 'when the feature flag is inactive and all scopes are active' do - let!(:feature_flag) { create(:operations_feature_flag, active: false) } + let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag, active: false) } it 'does not return the flag' do feature_flag.default_scope.update!(active: true) @@ -221,7 +221,7 @@ RSpec.describe Operations::FeatureFlag do end context 'when the feature flag is active and all scopes are inactive' do - let!(:feature_flag) { create(:operations_feature_flag, active: true) } + let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag, active: true) } it 'does not return the flag' do feature_flag.default_scope.update!(active: false) @@ -239,7 +239,7 @@ RSpec.describe Operations::FeatureFlag do end context 'when the feature flag is inactive and all scopes are active' do - let!(:feature_flag) { create(:operations_feature_flag, active: false) } + let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag, active: false) } it 'returns the flag' do feature_flag.default_scope.update!(active: true) diff --git a/spec/requests/api/feature_flag_scopes_spec.rb b/spec/requests/api/feature_flag_scopes_spec.rb deleted file mode 100644 index da5b2cbb7ae..00000000000 --- a/spec/requests/api/feature_flag_scopes_spec.rb +++ /dev/null @@ -1,319 +0,0 @@ -# frozen_string_literal: true -require 'spec_helper' - -RSpec.describe API::FeatureFlagScopes do - include FeatureFlagHelpers - - let(:project) { create(:project, :repository) } - let(:developer) { create(:user) } - let(:reporter) { create(:user) } - let(:user) { developer } - - before do - project.add_developer(developer) - project.add_reporter(reporter) - end - - shared_examples_for 'check user permission' do - context 'when user is reporter' do - let(:user) { reporter } - - it 'forbids the request' do - subject - - expect(response).to have_gitlab_http_status(:forbidden) - end - end - end - - shared_examples_for 'not found' do - it 'returns Not Found' do - subject - - expect(response).to have_gitlab_http_status(:not_found) - end - end - - describe 'GET /projects/:id/feature_flag_scopes' do - subject do - get api("/projects/#{project.id}/feature_flag_scopes", user), - params: params - end - - let(:feature_flag_1) { create_flag(project, 'flag_1', true) } - let(:feature_flag_2) { create_flag(project, 'flag_2', true) } - - before do - create_scope(feature_flag_1, 'staging', false) - create_scope(feature_flag_1, 'production', true) - create_scope(feature_flag_2, 'review/*', false) - end - - context 'when environment is production' do - let(:params) { { environment: 'production' } } - - it_behaves_like 'check user permission' - - it 'returns all effective feature flags under the environment' do - subject - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to match_response_schema('public_api/v4/feature_flag_detailed_scopes') - expect(json_response.second).to include({ 'name' => 'flag_1', 'active' => true }) - expect(json_response.first).to include({ 'name' => 'flag_2', 'active' => true }) - end - end - - context 'when environment is staging' do - let(:params) { { environment: 'staging' } } - - it 'returns all effective feature flags under the environment' do - subject - - expect(response).to have_gitlab_http_status(:ok) - expect(json_response.second).to include({ 'name' => 'flag_1', 'active' => false }) - expect(json_response.first).to include({ 'name' => 'flag_2', 'active' => true }) - end - end - - context 'when environment is review/feature X' do - let(:params) { { environment: 'review/feature X' } } - - it 'returns all effective feature flags under the environment' do - subject - - expect(response).to have_gitlab_http_status(:ok) - expect(json_response.second).to include({ 'name' => 'flag_1', 'active' => true }) - expect(json_response.first).to include({ 'name' => 'flag_2', 'active' => false }) - end - end - end - - describe 'GET /projects/:id/feature_flags/:name/scopes' do - subject do - get api("/projects/#{project.id}/feature_flags/#{feature_flag.name}/scopes", user) - end - - context 'when there are two scopes' do - let(:feature_flag) { create_flag(project, 'test') } - let!(:additional_scope) { create_scope(feature_flag, 'production', false) } - - it_behaves_like 'check user permission' - - it 'returns scopes of the feature flag' do - subject - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to match_response_schema('public_api/v4/feature_flag_scopes') - expect(json_response.count).to eq(2) - expect(json_response.first['environment_scope']).to eq(feature_flag.scopes[0].environment_scope) - expect(json_response.second['environment_scope']).to eq(feature_flag.scopes[1].environment_scope) - end - end - - context 'when there are no feature flags' do - let(:feature_flag) { double(:feature_flag, name: 'test') } - - it_behaves_like 'not found' - end - end - - describe 'POST /projects/:id/feature_flags/:name/scopes' do - subject do - post api("/projects/#{project.id}/feature_flags/#{feature_flag.name}/scopes", user), - params: params - end - - let(:params) do - { - environment_scope: 'staging', - active: true, - strategies: [{ name: 'userWithId', parameters: { 'userIds': 'a,b,c' } }].to_json - } - end - - context 'when there is a corresponding feature flag' do - let!(:feature_flag) { create(:operations_feature_flag, project: project) } - - it_behaves_like 'check user permission' - - it 'creates a new scope' do - subject - - expect(response).to have_gitlab_http_status(:created) - expect(response).to match_response_schema('public_api/v4/feature_flag_scope') - expect(json_response['environment_scope']).to eq(params[:environment_scope]) - expect(json_response['active']).to eq(params[:active]) - expect(json_response['strategies']).to eq(Gitlab::Json.parse(params[:strategies])) - end - - context 'when the scope already exists' do - before do - create_scope(feature_flag, params[:environment_scope]) - end - - it 'returns error' do - subject - - expect(response).to have_gitlab_http_status(:bad_request) - expect(json_response['message']).to include('Scopes environment scope (staging) has already been taken') - end - end - end - - context 'when feature flag is not found' do - let(:feature_flag) { double(:feature_flag, name: 'test') } - - it_behaves_like 'not found' - end - end - - describe 'GET /projects/:id/feature_flags/:name/scopes/:environment_scope' do - subject do - get api("/projects/#{project.id}/feature_flags/#{feature_flag.name}/scopes/#{environment_scope}", - user) - end - - let(:environment_scope) { scope.environment_scope } - - shared_examples_for 'successful response' do - it 'returns a scope' do - subject - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to match_response_schema('public_api/v4/feature_flag_scope') - expect(json_response['id']).to eq(scope.id) - expect(json_response['active']).to eq(scope.active) - expect(json_response['environment_scope']).to eq(scope.environment_scope) - end - end - - context 'when there is a feature flag' do - let!(:feature_flag) { create(:operations_feature_flag, project: project) } - let(:scope) { feature_flag.default_scope } - - it_behaves_like 'check user permission' - it_behaves_like 'successful response' - - context 'when environment scope includes slash' do - let!(:scope) { create_scope(feature_flag, 'review/*', false) } - - it_behaves_like 'not found' - - context 'when URL-encoding the environment scope parameter' do - let(:environment_scope) { CGI.escape(scope.environment_scope) } - - it_behaves_like 'successful response' - end - end - end - - context 'when there are no feature flags' do - let(:feature_flag) { double(:feature_flag, name: 'test') } - let(:scope) { double(:feature_flag_scope, environment_scope: 'prd') } - - it_behaves_like 'not found' - end - end - - describe 'PUT /projects/:id/feature_flags/:name/scopes/:environment_scope' do - subject do - put api("/projects/#{project.id}/feature_flags/#{feature_flag.name}/scopes/#{environment_scope}", - user), params: params - end - - let(:environment_scope) { scope.environment_scope } - - let(:params) do - { - active: true, - strategies: [{ name: 'userWithId', parameters: { 'userIds': 'a,b,c' } }].to_json - } - end - - context 'when there is a corresponding feature flag' do - let!(:feature_flag) { create(:operations_feature_flag, project: project) } - let(:scope) { create_scope(feature_flag, 'staging', false, [{ name: "default", parameters: {} }]) } - - it_behaves_like 'check user permission' - - it 'returns the updated scope' do - subject - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to match_response_schema('public_api/v4/feature_flag_scope') - expect(json_response['id']).to eq(scope.id) - expect(json_response['active']).to eq(params[:active]) - expect(json_response['strategies']).to eq(Gitlab::Json.parse(params[:strategies])) - end - - context 'when there are no corresponding feature flag scopes' do - let(:scope) { double(:feature_flag_scope, environment_scope: 'prd') } - - it_behaves_like 'not found' - end - end - - context 'when there are no corresponding feature flags' do - let(:feature_flag) { double(:feature_flag, name: 'test') } - let(:scope) { double(:feature_flag_scope, environment_scope: 'prd') } - - it_behaves_like 'not found' - end - end - - describe 'DELETE /projects/:id/feature_flags/:name/scopes/:environment_scope' do - subject do - delete api("/projects/#{project.id}/feature_flags/#{feature_flag.name}/scopes/#{environment_scope}", - user) - end - - let(:environment_scope) { scope.environment_scope } - - shared_examples_for 'successful response' do - it 'destroys the scope' do - expect { subject } - .to change { Operations::FeatureFlagScope.exists?(environment_scope: scope.environment_scope) } - .from(true).to(false) - - expect(response).to have_gitlab_http_status(:no_content) - end - end - - context 'when there is a feature flag' do - let!(:feature_flag) { create(:operations_feature_flag, project: project) } - - context 'when there is a targeted scope' do - let!(:scope) { create_scope(feature_flag, 'production', false) } - - it_behaves_like 'check user permission' - it_behaves_like 'successful response' - - context 'when environment scope includes slash' do - let!(:scope) { create_scope(feature_flag, 'review/*', false) } - - it_behaves_like 'not found' - - context 'when URL-encoding the environment scope parameter' do - let(:environment_scope) { CGI.escape(scope.environment_scope) } - - it_behaves_like 'successful response' - end - end - end - - context 'when there are no targeted scopes' do - let!(:scope) { double(:feature_flag_scope, environment_scope: 'production') } - - it_behaves_like 'not found' - end - end - - context 'when there are no feature flags' do - let(:feature_flag) { double(:feature_flag, name: 'test') } - let(:scope) { double(:feature_flag_scope, environment_scope: 'prd') } - - it_behaves_like 'not found' - end - end -end diff --git a/spec/requests/api/feature_flags_spec.rb b/spec/requests/api/feature_flags_spec.rb index 923ebefe01f..2cd52c0a5e5 100644 --- a/spec/requests/api/feature_flags_spec.rb +++ b/spec/requests/api/feature_flags_spec.rb @@ -62,7 +62,7 @@ RSpec.describe API::FeatureFlags do expect(response).to have_gitlab_http_status(:ok) expect(response).to match_response_schema('public_api/v4/feature_flags') - expect(json_response.map { |f| f['version'] }).to eq(%w[legacy_flag legacy_flag]) + expect(json_response.map { |f| f['version'] }).to eq(%w[new_version_flag new_version_flag]) end it 'does not have N+1 problem' do @@ -145,19 +145,7 @@ RSpec.describe API::FeatureFlags do expect(response).to match_response_schema('public_api/v4/feature_flag') expect(json_response['name']).to eq(feature_flag.name) expect(json_response['description']).to eq(feature_flag.description) - expect(json_response['version']).to eq('legacy_flag') - end - - context 'without legacy flags' do - before do - stub_feature_flags(remove_legacy_flags: true, remove_legacy_flags_override: false) - end - - it 'returns not found' do - subject - - expect(response).to have_gitlab_http_status(:not_found) - end + expect(json_response['version']).to eq('new_version_flag') end it_behaves_like 'check user permission' @@ -465,246 +453,6 @@ RSpec.describe API::FeatureFlags do end end - describe 'POST /projects/:id/feature_flags/:name/enable' do - subject do - post api("/projects/#{project.id}/feature_flags/#{params[:name]}/enable", user), - params: params - end - - let(:params) do - { - name: 'awesome-feature', - environment_scope: 'production', - strategy: { name: 'userWithId', parameters: { userIds: 'Project:1' } }.to_json - } - end - - context 'when feature flag does not exist yet' do - it 'creates a new feature flag with the specified scope and strategy' do - subject - - feature_flag = project.operations_feature_flags.last - scope = feature_flag.scopes.find_by_environment_scope(params[:environment_scope]) - expect(response).to have_gitlab_http_status(:ok) - expect(response).to match_response_schema('public_api/v4/feature_flag') - expect(feature_flag.name).to eq(params[:name]) - expect(scope.strategies).to eq([Gitlab::Json.parse(params[:strategy])]) - expect(feature_flag.version).to eq('legacy_flag') - end - - it 'returns the flag version and strategies in the json response' do - subject - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to match_response_schema('public_api/v4/feature_flag') - expect(json_response.slice('version', 'strategies')).to eq({ - 'version' => 'legacy_flag', - 'strategies' => [] - }) - end - - it_behaves_like 'check user permission' - - context 'without legacy flags' do - before do - stub_feature_flags(remove_legacy_flags: true, remove_legacy_flags_override: false) - end - - it 'returns not found' do - subject - - expect(response).to have_gitlab_http_status(:not_found) - end - end - end - - context 'when feature flag exists already' do - let!(:feature_flag) { create_flag(project, params[:name]) } - - context 'when feature flag scope does not exist yet' do - it 'creates a new scope with the specified strategy' do - subject - - scope = feature_flag.scopes.find_by_environment_scope(params[:environment_scope]) - expect(response).to have_gitlab_http_status(:ok) - expect(scope.strategies).to eq([Gitlab::Json.parse(params[:strategy])]) - end - - it_behaves_like 'check user permission' - end - - context 'when feature flag scope exists already' do - let(:defined_strategy) { { name: 'userWithId', parameters: { userIds: 'Project:2' } } } - - before do - create_scope(feature_flag, params[:environment_scope], true, [defined_strategy]) - end - - it 'adds an additional strategy to the scope' do - subject - - scope = feature_flag.scopes.find_by_environment_scope(params[:environment_scope]) - expect(response).to have_gitlab_http_status(:ok) - expect(scope.strategies).to eq([defined_strategy.deep_stringify_keys, Gitlab::Json.parse(params[:strategy])]) - end - - context 'when the specified strategy exists already' do - let(:defined_strategy) { Gitlab::Json.parse(params[:strategy]) } - - it 'does not add a duplicate strategy' do - subject - - scope = feature_flag.scopes.find_by_environment_scope(params[:environment_scope]) - strategy_count = scope.strategies.count { |strategy| strategy['name'] == 'userWithId' } - expect(response).to have_gitlab_http_status(:ok) - expect(strategy_count).to eq(1) - end - end - end - - context 'without legacy flags' do - before do - stub_feature_flags(remove_legacy_flags: true, remove_legacy_flags_override: false) - end - - it 'returns not found' do - subject - - expect(response).to have_gitlab_http_status(:not_found) - end - end - end - - context 'with a version 2 flag' do - let!(:feature_flag) { create(:operations_feature_flag, :new_version_flag, project: project, name: params[:name]) } - - it 'does not change the flag and returns an unprocessable_entity response' do - subject - - expect(response).to have_gitlab_http_status(:unprocessable_entity) - expect(json_response).to eq({ 'message' => 'Version 2 flags not supported' }) - feature_flag.reload - expect(feature_flag.scopes).to eq([]) - expect(feature_flag.strategies).to eq([]) - end - end - end - - describe 'POST /projects/:id/feature_flags/:name/disable' do - subject do - post api("/projects/#{project.id}/feature_flags/#{params[:name]}/disable", user), - params: params - end - - let(:params) do - { - name: 'awesome-feature', - environment_scope: 'production', - strategy: { name: 'userWithId', parameters: { userIds: 'Project:1' } }.to_json - } - end - - context 'when feature flag does not exist yet' do - it_behaves_like 'not found' - end - - context 'when feature flag exists already' do - let!(:feature_flag) { create_flag(project, params[:name]) } - - context 'when feature flag scope does not exist yet' do - it_behaves_like 'not found' - end - - context 'when feature flag scope exists already and has the specified strategy' do - let(:defined_strategies) do - [ - { name: 'userWithId', parameters: { userIds: 'Project:1' } }, - { name: 'userWithId', parameters: { userIds: 'Project:2' } } - ] - end - - before do - create_scope(feature_flag, params[:environment_scope], true, defined_strategies) - end - - it 'removes the strategy from the scope' do - subject - - scope = feature_flag.scopes.find_by_environment_scope(params[:environment_scope]) - expect(response).to have_gitlab_http_status(:ok) - expect(response).to match_response_schema('public_api/v4/feature_flag') - expect(scope.strategies) - .to eq([{ name: 'userWithId', parameters: { userIds: 'Project:2' } }.deep_stringify_keys]) - end - - it 'returns the flag version and strategies in the json response' do - subject - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to match_response_schema('public_api/v4/feature_flag') - expect(json_response.slice('version', 'strategies')).to eq({ - 'version' => 'legacy_flag', - 'strategies' => [] - }) - end - - context 'without legacy flags' do - before do - stub_feature_flags(remove_legacy_flags: true, remove_legacy_flags_override: false) - end - - it 'returns not found' do - subject - - expect(response).to have_gitlab_http_status(:not_found) - end - end - - it_behaves_like 'check user permission' - - context 'when strategies become empty array after the removal' do - let(:defined_strategies) do - [{ name: 'userWithId', parameters: { userIds: 'Project:1' } }] - end - - it 'destroys the scope' do - subject - - scope = feature_flag.scopes.find_by_environment_scope(params[:environment_scope]) - expect(response).to have_gitlab_http_status(:ok) - expect(scope).to be_nil - end - - it_behaves_like 'check user permission' - end - end - - context 'when scope exists already but cannot find the corresponding strategy' do - let(:defined_strategy) { { name: 'userWithId', parameters: { userIds: 'Project:2' } } } - - before do - create_scope(feature_flag, params[:environment_scope], true, [defined_strategy]) - end - - it_behaves_like 'not found' - end - end - - context 'with a version 2 feature flag' do - let!(:feature_flag) { create(:operations_feature_flag, :new_version_flag, project: project, name: params[:name]) } - - it 'does not change the flag and returns an unprocessable_entity response' do - subject - - expect(response).to have_gitlab_http_status(:unprocessable_entity) - expect(json_response).to eq({ 'message' => 'Version 2 flags not supported' }) - feature_flag.reload - expect(feature_flag.scopes).to eq([]) - expect(feature_flag.strategies).to eq([]) - end - end - end - describe 'PUT /projects/:id/feature_flags/:name' do context 'with a legacy feature flag' do let!(:feature_flag) do @@ -712,13 +460,13 @@ RSpec.describe API::FeatureFlags do name: 'feature1', description: 'old description') end - it 'returns a 422' do + it 'returns a 404' do params = { description: 'new description' } put api("/projects/#{project.id}/feature_flags/feature1", user), params: params - expect(response).to have_gitlab_http_status(:unprocessable_entity) - expect(json_response).to eq({ 'message' => 'PUT operations are not supported for legacy feature flags' }) + expect(response).to have_gitlab_http_status(:not_found) + expect(json_response).to eq({ 'message' => '404 Not Found' }) expect(feature_flag.reload.description).to eq('old description') end end @@ -1024,20 +772,6 @@ RSpec.describe API::FeatureFlags do expect(feature_flag.reload.strategies.first.scopes.count).to eq(0) end end - - context 'without legacy flags' do - before do - stub_feature_flags(remove_legacy_flags: true, remove_legacy_flags_override: false) - end - - it 'returns not found' do - params = { description: 'new description' } - - put api("/projects/#{project.id}/feature_flags/other_flag_name", user), params: params - - expect(response).to have_gitlab_http_status(:not_found) - end - end end describe 'DELETE /projects/:id/feature_flags/:name' do @@ -1046,7 +780,7 @@ RSpec.describe API::FeatureFlags do params: params end - let!(:feature_flag) { create(:operations_feature_flag, project: project) } + let!(:feature_flag) { create(:operations_feature_flag, :legacy_flag, project: project) } let(:params) { {} } it 'destroys the feature flag' do diff --git a/spec/requests/api/unleash_spec.rb b/spec/requests/api/unleash_spec.rb index d3d193ba052..9989f8d28bd 100644 --- a/spec/requests/api/unleash_spec.rb +++ b/spec/requests/api/unleash_spec.rb @@ -176,34 +176,9 @@ RSpec.describe API::Unleash do it_behaves_like 'authenticated request' context 'with version 1 (legacy) feature flags' do - let(:feature_flag) { create(:operations_feature_flag, project: project, name: 'feature1', active: true, version: 1) } + let(:feature_flag) { create(:operations_feature_flag, :legacy_flag, project: project, name: 'feature1', active: true, version: 1) } - it_behaves_like 'support multiple environments' - - context 'with a list of feature flags' do - let(:headers) { { "UNLEASH-INSTANCEID" => client.token, "UNLEASH-APPNAME" => "production" } } - let!(:enabled_feature_flag) { create(:operations_feature_flag, project: project, name: 'feature1', active: true, version: 1) } - let!(:disabled_feature_flag) { create(:operations_feature_flag, project: project, name: 'feature2', active: false, version: 1) } - - it 'responds with a list of features' do - subject - - expect(response).to have_gitlab_http_status(:ok) - expect(json_response['version']).to eq(1) - expect(json_response['features']).not_to be_empty - expect(json_response['features'].map { |f| f['name'] }.sort).to eq(%w[feature1 feature2]) - expect(json_response['features'].sort_by {|f| f['name'] }.map { |f| f['enabled'] }).to eq([true, false]) - end - - it 'matches json schema' do - subject - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to match_response_schema('unleash/unleash') - end - end - - it 'returns a feature flag strategy' do + it 'does not return a legacy feature flag' do create(:operations_feature_flag_scope, feature_flag: feature_flag, environment_scope: 'sandbox', @@ -215,81 +190,7 @@ RSpec.describe API::Unleash do get api(features_url), headers: headers expect(response).to have_gitlab_http_status(:ok) - expect(json_response['features'].first['enabled']).to eq(true) - strategies = json_response['features'].first['strategies'] - expect(strategies).to eq([{ - "name" => "gradualRolloutUserId", - "parameters" => { - "percentage" => "50", - "groupId" => "default" - } - }]) - end - - it 'returns a default strategy for a scope' do - create(:operations_feature_flag_scope, feature_flag: feature_flag, environment_scope: 'sandbox', active: true) - headers = { "UNLEASH-INSTANCEID" => client.token, "UNLEASH-APPNAME" => "sandbox" } - - get api(features_url), headers: headers - - expect(response).to have_gitlab_http_status(:ok) - expect(json_response['features'].first['enabled']).to eq(true) - strategies = json_response['features'].first['strategies'] - expect(strategies).to eq([{ "name" => "default", "parameters" => {} }]) - end - - it 'returns multiple strategies for a feature flag' do - create(:operations_feature_flag_scope, - feature_flag: feature_flag, - environment_scope: 'staging', - active: true, - strategies: [{ name: "userWithId", parameters: { userIds: "max,fred" } }, - { name: "gradualRolloutUserId", - parameters: { groupId: "default", percentage: "50" } }]) - headers = { "UNLEASH-INSTANCEID" => client.token, "UNLEASH-APPNAME" => "staging" } - - get api(features_url), headers: headers - - expect(response).to have_gitlab_http_status(:ok) - expect(json_response['features'].first['enabled']).to eq(true) - strategies = json_response['features'].first['strategies'].sort_by { |s| s['name'] } - expect(strategies).to eq([{ - "name" => "gradualRolloutUserId", - "parameters" => { - "percentage" => "50", - "groupId" => "default" - } - }, { - "name" => "userWithId", - "parameters" => { - "userIds" => "max,fred" - } - }]) - end - - it 'returns a disabled feature when the flag is disabled' do - flag = create(:operations_feature_flag, project: project, name: 'test_feature', active: false, version: 1) - create(:operations_feature_flag_scope, feature_flag: flag, environment_scope: 'production', active: true) - headers = { "UNLEASH-INSTANCEID" => client.token, "UNLEASH-APPNAME" => "production" } - - get api(features_url), headers: headers - - expect(response).to have_gitlab_http_status(:ok) - expect(json_response['features'].first['enabled']).to eq(false) - end - - context "with an inactive scope" do - let!(:scope) { create(:operations_feature_flag_scope, feature_flag: feature_flag, environment_scope: 'production', active: false, strategies: [{ name: "default", parameters: {} }]) } - let(:headers) { { "UNLEASH-INSTANCEID" => client.token, "UNLEASH-APPNAME" => "production" } } - - it 'returns a disabled feature' do - get api(features_url), headers: headers - - expect(response).to have_gitlab_http_status(:ok) - feature_json = json_response['features'].first - expect(feature_json['enabled']).to eq(false) - expect(feature_json['strategies']).to eq([{ 'name' => 'default', 'parameters' => {} }]) - end + expect(json_response['features']).to be_empty end end @@ -534,89 +435,6 @@ RSpec.describe API::Unleash do }]) end end - - context 'when mixing version 1 and version 2 feature flags' do - it 'returns both types of flags when both match' do - feature_flag_a = create(:operations_feature_flag, project: project, - name: 'feature_a', active: true, version: 2) - strategy = create(:operations_strategy, feature_flag: feature_flag_a, - name: 'userWithId', parameters: { userIds: 'user8' }) - create(:operations_scope, strategy: strategy, environment_scope: 'staging') - feature_flag_b = create(:operations_feature_flag, project: project, - name: 'feature_b', active: true, version: 1) - create(:operations_feature_flag_scope, feature_flag: feature_flag_b, - active: true, strategies: [{ name: 'default', parameters: {} }], environment_scope: 'staging') - - get api(features_url), headers: { 'UNLEASH-INSTANCEID' => client.token, 'UNLEASH-APPNAME' => 'staging' } - - expect(response).to have_gitlab_http_status(:ok) - expect(json_response['features'].sort_by {|f| f['name']}).to eq([{ - 'name' => 'feature_a', - 'enabled' => true, - 'strategies' => [{ - 'name' => 'userWithId', - 'parameters' => { 'userIds' => 'user8' } - }] - }, { - 'name' => 'feature_b', - 'enabled' => true, - 'strategies' => [{ - 'name' => 'default', - 'parameters' => {} - }] - }]) - end - - it 'returns legacy flags when only legacy flags match' do - feature_flag_a = create(:operations_feature_flag, project: project, - name: 'feature_a', active: true, version: 2) - strategy = create(:operations_strategy, feature_flag: feature_flag_a, - name: 'userWithId', parameters: { userIds: 'user8' }) - create(:operations_scope, strategy: strategy, environment_scope: 'production') - feature_flag_b = create(:operations_feature_flag, project: project, - name: 'feature_b', active: true, version: 1) - create(:operations_feature_flag_scope, feature_flag: feature_flag_b, - active: true, strategies: [{ name: 'default', parameters: {} }], environment_scope: 'staging') - - get api(features_url), headers: { 'UNLEASH-INSTANCEID' => client.token, 'UNLEASH-APPNAME' => 'staging' } - - expect(response).to have_gitlab_http_status(:ok) - expect(json_response['features']).to eq([{ - 'name' => 'feature_b', - 'enabled' => true, - 'strategies' => [{ - 'name' => 'default', - 'parameters' => {} - }] - }]) - end - - it 'returns new flags when legacy flags are disabled' do - stub_feature_flags(remove_legacy_flags_override: false, remove_legacy_flags: true) - - feature_flag_a = create(:operations_feature_flag, :new_version_flag, project: project, - name: 'feature_a', active: true) - strategy = create(:operations_strategy, feature_flag: feature_flag_a, - name: 'userWithId', parameters: { userIds: 'user8' }) - create(:operations_scope, strategy: strategy, environment_scope: 'staging') - feature_flag_b = create(:operations_feature_flag, :legacy_flag, project: project, - name: 'feature_b', active: true) - create(:operations_feature_flag_scope, feature_flag: feature_flag_b, - active: true, strategies: [{ name: 'default', parameters: {} }], environment_scope: 'staging') - - get api(features_url), headers: { 'UNLEASH-INSTANCEID' => client.token, 'UNLEASH-APPNAME' => 'staging' } - - expect(response).to have_gitlab_http_status(:ok) - expect(json_response['features'].sort_by {|f| f['name']}).to eq([{ - 'name' => 'feature_a', - 'enabled' => true, - 'strategies' => [{ - 'name' => 'userWithId', - 'parameters' => { 'userIds' => 'user8' } - }] - }]) - end - end end end diff --git a/spec/serializers/cluster_application_entity_spec.rb b/spec/serializers/cluster_application_entity_spec.rb index 3941aad540a..1e71e45948c 100644 --- a/spec/serializers/cluster_application_entity_spec.rb +++ b/spec/serializers/cluster_application_entity_spec.rb @@ -77,16 +77,5 @@ RSpec.describe ClusterApplicationEntity do expect(subject[:pages_domain]).to eq(id: pages_domain.id, domain: pages_domain.domain) end end - - context 'for fluentd application' do - let(:application) { build(:clusters_applications_fluentd, :installed) } - - it 'includes host, port, protocol and log fields' do - expect(subject[:port]).to eq(514) - expect(subject[:host]).to eq("example.com") - expect(subject[:protocol]).to eq("tcp") - expect(subject[:cilium_log_enabled]).to be true - end - end end end diff --git a/spec/services/ci/job_artifacts/create_service_spec.rb b/spec/services/ci/job_artifacts/create_service_spec.rb index 97c65dc005e..e6d9f208096 100644 --- a/spec/services/ci/job_artifacts/create_service_spec.rb +++ b/spec/services/ci/job_artifacts/create_service_spec.rb @@ -203,53 +203,6 @@ RSpec.describe Ci::JobArtifacts::CreateService do end end - context 'when artifact type is cluster_applications' do - let(:artifacts_file) do - file_to_upload('spec/fixtures/helm/helm_list_v2_prometheus_missing.json.gz', sha256: artifacts_sha256) - end - - let(:params) do - { - 'artifact_type' => 'cluster_applications', - 'artifact_format' => 'gzip' - }.with_indifferent_access - end - - it 'calls cluster applications parse service' do - expect_next_instance_of(Clusters::ParseClusterApplicationsArtifactService) do |service| - expect(service).to receive(:execute).once.and_call_original - end - - subject - end - - context 'when there is a deployment cluster' do - let(:user) { project.owner } - - before do - job.update!(user: user) - end - - it 'calls cluster applications parse service with job and job user', :aggregate_failures do - expect(Clusters::ParseClusterApplicationsArtifactService).to receive(:new).with(job, user).and_call_original - - subject - end - end - - context 'when ci_synchronous_artifact_parsing feature flag is disabled' do - before do - stub_feature_flags(ci_synchronous_artifact_parsing: false) - end - - it 'does not call parse service' do - expect(Clusters::ParseClusterApplicationsArtifactService).not_to receive(:new) - - expect(subject[:status]).to eq(:success) - end - end - end - shared_examples 'rescues object storage error' do |klass, message, expected_message| it "handles #{klass}" do allow_next_instance_of(JobArtifactUploader) do |uploader| diff --git a/spec/services/clusters/parse_cluster_applications_artifact_service_spec.rb b/spec/services/clusters/parse_cluster_applications_artifact_service_spec.rb deleted file mode 100644 index 1f6ad218927..00000000000 --- a/spec/services/clusters/parse_cluster_applications_artifact_service_spec.rb +++ /dev/null @@ -1,126 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Clusters::ParseClusterApplicationsArtifactService do - let_it_be(:project) { create(:project) } - let_it_be(:user) { create(:user) } - - before do - project.add_maintainer(user) - end - - describe 'RELEASE_NAMES' do - it 'is included in Cluster application names', :aggregate_failures do - described_class::RELEASE_NAMES.each do |release_name| - expect(Clusters::Cluster::APPLICATIONS).to include(release_name) - end - end - end - - describe '.new' do - let(:job) { build(:ci_build) } - - it 'sets the project and current user', :aggregate_failures do - service = described_class.new(job, user) - - expect(service.project).to eq(job.project) - expect(service.current_user).to eq(user) - end - end - - describe '#execute' do - let_it_be(:cluster, reload: true) { create(:cluster, projects: [project]) } - let_it_be(:deployment, reload: true) { create(:deployment, cluster: cluster) } - - let(:job) { deployment.deployable } - let(:artifact) { create(:ci_job_artifact, :cluster_applications, job: job) } - - it 'calls Gitlab::Kubernetes::Helm::Parsers::ListV2' do - expect(Gitlab::Kubernetes::Helm::Parsers::ListV2).to receive(:new).and_call_original - - result = described_class.new(job, user).execute(artifact) - - expect(result[:status]).to eq(:success) - end - - context 'artifact is not of cluster_applications type' do - let(:artifact) { create(:ci_job_artifact, :archive) } - let(:job) { artifact.job } - - it 'raise ArgumentError' do - expect do - described_class.new(job, user).execute(artifact) - end.to raise_error(ArgumentError, 'Artifact is not cluster_applications file type') - end - end - - context 'artifact exceeds acceptable size' do - it 'returns an error' do - stub_const("#{described_class}::MAX_ACCEPTABLE_ARTIFACT_SIZE", 1.byte) - - result = described_class.new(job, user).execute(artifact) - - expect(result[:status]).to eq(:error) - expect(result[:message]).to eq('Cluster_applications artifact too big. Maximum allowable size: 1 Byte') - end - end - - context 'job has no deployment' do - let(:job) { build(:ci_build) } - - it 'returns an error' do - result = described_class.new(job, user).execute(artifact) - - expect(result[:status]).to eq(:error) - expect(result[:message]).to eq('No deployment found for this job') - end - end - - context 'job has no deployment cluster' do - let(:deployment) { create(:deployment) } - let(:job) { deployment.deployable } - - it 'returns an error' do - result = described_class.new(job, user).execute(artifact) - - expect(result[:status]).to eq(:error) - expect(result[:message]).to eq('No deployment cluster found for this job') - end - end - - context 'blob is empty' do - let(:file) { fixture_file_upload(Rails.root.join("spec/fixtures/helm/helm_list_v2_empty_blob.json.gz")) } - let(:artifact) { create(:ci_job_artifact, :cluster_applications, job: job, file: file) } - - it 'returns success' do - result = described_class.new(job, user).execute(artifact) - - expect(result[:status]).to eq(:success) - end - end - - context 'job has deployment cluster' do - context 'current user does not have access to deployment cluster' do - let(:other_user) { create(:user) } - - it 'returns an error' do - result = described_class.new(job, other_user).execute(artifact) - - expect(result[:status]).to eq(:error) - expect(result[:message]).to eq('No deployment cluster found for this job') - end - end - - it 'does not affect unpermitted cluster applications' do - expect(Clusters::ParseClusterApplicationsArtifactService::RELEASE_NAMES).to contain_exactly('cilium') - end - - Clusters::ParseClusterApplicationsArtifactService::RELEASE_NAMES.each do |release_name| - context release_name do - include_examples 'parse cluster applications artifact', release_name - end - end - end - end -end diff --git a/spec/services/feature_flags/disable_service_spec.rb b/spec/services/feature_flags/disable_service_spec.rb deleted file mode 100644 index 4b2137be35c..00000000000 --- a/spec/services/feature_flags/disable_service_spec.rb +++ /dev/null @@ -1,92 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe FeatureFlags::DisableService do - include FeatureFlagHelpers - - let_it_be(:project) { create(:project) } - let_it_be(:user) { create(:user) } - - let(:params) { {} } - let(:service) { described_class.new(project, user, params) } - - before_all do - project.add_developer(user) - end - - describe '#execute' do - subject { service.execute } - - context 'with params to disable default strategy on prd scope' do - let(:params) do - { - name: 'awesome', - environment_scope: 'prd', - strategy: { name: 'userWithId', parameters: { 'userIds': 'User:1' } }.deep_stringify_keys - } - end - - context 'when there is a persisted feature flag' do - let!(:feature_flag) { create_flag(project, params[:name]) } - - context 'when there is a persisted scope' do - let!(:scope) do - create_scope(feature_flag, params[:environment_scope], true, strategies) - end - - context 'when there is a persisted strategy' do - let(:strategies) do - [ - { name: 'userWithId', parameters: { 'userIds': 'User:1' } }.deep_stringify_keys, - { name: 'userWithId', parameters: { 'userIds': 'User:2' } }.deep_stringify_keys - ] - end - - it 'deletes the specified strategy' do - subject - - scope.reload - expect(scope.strategies.count).to eq(1) - expect(scope.strategies).not_to include(params[:strategy]) - end - - context 'when strategies will be empty' do - let(:strategies) { [params[:strategy]] } - - it 'deletes the persisted scope' do - subject - - expect(feature_flag.scopes.exists?(environment_scope: params[:environment_scope])) - .to eq(false) - end - end - end - - context 'when there is no persisted strategy' do - let(:strategies) { [{ name: 'default', parameters: {} }] } - - it 'returns error' do - expect(subject[:status]).to eq(:error) - expect(subject[:message]).to include('Strategy not found') - end - end - end - - context 'when there is no persisted scope' do - it 'returns error' do - expect(subject[:status]).to eq(:error) - expect(subject[:message]).to include('Feature Flag Scope not found') - end - end - end - - context 'when there is no persisted feature flag' do - it 'returns error' do - expect(subject[:status]).to eq(:error) - expect(subject[:message]).to include('Feature Flag not found') - end - end - end - end -end diff --git a/spec/services/feature_flags/enable_service_spec.rb b/spec/services/feature_flags/enable_service_spec.rb deleted file mode 100644 index c0008b1933f..00000000000 --- a/spec/services/feature_flags/enable_service_spec.rb +++ /dev/null @@ -1,154 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe FeatureFlags::EnableService do - include FeatureFlagHelpers - - let_it_be(:project) { create(:project) } - let_it_be(:user) { create(:user) } - - let(:params) { {} } - let(:service) { described_class.new(project, user, params) } - - before_all do - project.add_developer(user) - end - - describe '#execute' do - subject { service.execute } - - context 'with params to enable default strategy on prd scope' do - let(:params) do - { - name: 'awesome', - environment_scope: 'prd', - strategy: { name: 'default', parameters: {} }.stringify_keys - } - end - - context 'when there is no persisted feature flag' do - it 'creates a new feature flag with scope' do - feature_flag = subject[:feature_flag] - scope = feature_flag.scopes.find_by_environment_scope(params[:environment_scope]) - expect(subject[:status]).to eq(:success) - expect(feature_flag.name).to eq(params[:name]) - expect(feature_flag.default_scope).not_to be_active - expect(scope).to be_active - expect(scope.strategies).to include(params[:strategy]) - end - - context 'when params include default scope' do - let(:params) do - { - name: 'awesome', - environment_scope: '*', - strategy: { name: 'userWithId', parameters: { 'userIds': 'abc' } }.deep_stringify_keys - } - end - - it 'create a new feature flag with an active default scope with the specified strategy' do - feature_flag = subject[:feature_flag] - expect(subject[:status]).to eq(:success) - expect(feature_flag.default_scope).to be_active - expect(feature_flag.default_scope.strategies).to include(params[:strategy]) - end - end - end - - context 'when there is a persisted feature flag' do - let!(:feature_flag) { create_flag(project, params[:name]) } - - context 'when there is no persisted scope' do - it 'creates a new scope for the persisted feature flag' do - feature_flag = subject[:feature_flag] - scope = feature_flag.scopes.find_by_environment_scope(params[:environment_scope]) - expect(subject[:status]).to eq(:success) - expect(feature_flag.name).to eq(params[:name]) - expect(scope).to be_active - expect(scope.strategies).to include(params[:strategy]) - end - end - - context 'when there is a persisted scope' do - let!(:feature_flag_scope) do - create_scope(feature_flag, params[:environment_scope], active, strategies) - end - - let(:active) { true } - - context 'when the persisted scope does not have the specified strategy yet' do - let(:strategies) { [{ name: 'userWithId', parameters: { 'userIds': 'abc' } }] } - - it 'adds the specified strategy to the scope' do - subject - - feature_flag_scope.reload - expect(feature_flag_scope.strategies).to include(params[:strategy]) - end - - context 'when the persisted scope is inactive' do - let(:active) { false } - - it 'reactivates the scope' do - expect { subject } - .to change { feature_flag_scope.reload.active }.from(false).to(true) - end - end - end - - context 'when the persisted scope has the specified strategy already' do - let(:strategies) { [params[:strategy]] } - - it 'does not add a duplicated strategy to the scope' do - expect { subject } - .not_to change { feature_flag_scope.reload.strategies.count } - end - end - end - end - end - - context 'when strategy is not specified in params' do - let(:params) do - { - name: 'awesome', - environment_scope: 'prd' - } - end - - it 'returns error' do - expect(subject[:status]).to eq(:error) - expect(subject[:message]).to include('Scopes strategies must be an array of strategy hashes') - end - end - - context 'when environment scope is not specified in params' do - let(:params) do - { - name: 'awesome', - strategy: { name: 'default', parameters: {} }.stringify_keys - } - end - - it 'returns error' do - expect(subject[:status]).to eq(:error) - expect(subject[:message]).to include("Scopes environment scope can't be blank") - end - end - - context 'when name is not specified in params' do - let(:params) do - { - environment_scope: 'prd', - strategy: { name: 'default', parameters: {} }.stringify_keys - } - end - - it 'returns error' do - expect(subject[:status]).to eq(:error) - expect(subject[:message]).to include("Name can't be blank") - end - end - end -end diff --git a/spec/services/feature_flags/update_service_spec.rb b/spec/services/feature_flags/update_service_spec.rb index 1a127a0d472..d838549891a 100644 --- a/spec/services/feature_flags/update_service_spec.rb +++ b/spec/services/feature_flags/update_service_spec.rb @@ -121,150 +121,5 @@ RSpec.describe FeatureFlags::UpdateService do subject end end - - context 'when scope active state is changed' do - let(:params) do - { - scopes_attributes: [{ id: feature_flag.scopes.first.id, active: false }] - } - end - - it 'creates audit event about changing active state' do - expect { subject }.to change { AuditEvent.count }.by(1) - expect(audit_event_message).to( - include("Updated rule <strong>*</strong> active state "\ - "from <strong>true</strong> to <strong>false</strong>.") - ) - end - end - - context 'when scope is renamed' do - let(:changed_scope) { feature_flag.scopes.create!(environment_scope: 'review', active: true) } - let(:params) do - { - scopes_attributes: [{ id: changed_scope.id, environment_scope: 'staging' }] - } - end - - it 'creates audit event with changed name' do - expect { subject }.to change { AuditEvent.count }.by(1) - expect(audit_event_message).to( - include("Updated rule <strong>staging</strong> environment scope "\ - "from <strong>review</strong> to <strong>staging</strong>.") - ) - end - - context 'when scope can not be updated' do - let(:params) do - { - scopes_attributes: [{ id: changed_scope.id, environment_scope: '' }] - } - end - - it 'returns error status' do - expect(subject[:status]).to eq(:error) - end - - it 'returns error messages' do - expect(subject[:message]).to include("Scopes environment scope can't be blank") - end - - it 'does not create audit event' do - expect { subject }.not_to change { AuditEvent.count } - end - end - end - - context 'when scope is deleted' do - let(:deleted_scope) { feature_flag.scopes.create!(environment_scope: 'review', active: true) } - let(:params) do - { - scopes_attributes: [{ id: deleted_scope.id, '_destroy': true }] - } - end - - it 'creates audit event with deleted scope' do - expect { subject }.to change { AuditEvent.count }.by(1) - expect(audit_event_message).to include("Deleted rule <strong>review</strong>.") - end - - context 'when scope can not be deleted' do - before do - allow(deleted_scope).to receive(:destroy).and_return(false) - end - - it 'does not create audit event' do - expect do - subject - end.to not_change { AuditEvent.count }.and raise_error(ActiveRecord::RecordNotDestroyed) - end - end - end - - context 'when new scope is being added' do - let(:new_environment_scope) { 'review' } - let(:params) do - { - scopes_attributes: [{ environment_scope: new_environment_scope, active: true }] - } - end - - it 'creates audit event with new scope' do - expected = 'Created rule <strong>review</strong> and set it as <strong>active</strong> '\ - 'with strategies <strong>[{"name"=>"default", "parameters"=>{}}]</strong>.' - - subject - - expect(audit_event_message).to include(expected) - end - - context 'when scope can not be created' do - let(:new_environment_scope) { '' } - - it 'returns error status' do - expect(subject[:status]).to eq(:error) - end - - it 'returns error messages' do - expect(subject[:message]).to include("Scopes environment scope can't be blank") - end - - it 'does not create audit event' do - expect { subject }.not_to change { AuditEvent.count } - end - end - end - - context 'when the strategy is changed' do - let(:scope) do - create(:operations_feature_flag_scope, - feature_flag: feature_flag, - environment_scope: 'sandbox', - strategies: [{ name: "default", parameters: {} }]) - end - - let(:params) do - { - scopes_attributes: [{ - id: scope.id, - environment_scope: 'sandbox', - strategies: [{ - name: 'gradualRolloutUserId', - parameters: { - groupId: 'mygroup', - percentage: "40" - } - }] - }] - } - end - - it 'creates an audit event' do - expected = %r{Updated rule <strong>sandbox</strong> strategies from <strong>.*</strong> to <strong>.*</strong>.} - - expect { subject }.to change { AuditEvent.count }.by(1) - expect(audit_event_message).to match(expected) - end - end end end diff --git a/spec/support/helpers/feature_flag_helpers.rb b/spec/support/helpers/feature_flag_helpers.rb index aef15d81712..af7a674f3bc 100644 --- a/spec/support/helpers/feature_flag_helpers.rb +++ b/spec/support/helpers/feature_flag_helpers.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module FeatureFlagHelpers - def create_flag(project, name, active = true, description: nil, version: Operations::FeatureFlag.versions['legacy_flag']) + def create_flag(project, name, active = true, description: nil, version: Operations::FeatureFlag.versions['new_version_flag']) create(:operations_feature_flag, name: name, active: active, version: version, description: description, project: project) end diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb index 5dc6945ec5e..4857fa63114 100644 --- a/spec/support/helpers/graphql_helpers.rb +++ b/spec/support/helpers/graphql_helpers.rb @@ -1,6 +1,10 @@ # frozen_string_literal: true module GraphqlHelpers + def self.included(base) + base.include(::Gitlab::Graphql::Laziness) + end + MutationDefinition = Struct.new(:query, :variables) NoData = Class.new(StandardError) diff --git a/spec/support/shared_examples/services/clusters/parse_cluster_applications_artifact_shared_examples.rb b/spec/support/shared_examples/services/clusters/parse_cluster_applications_artifact_shared_examples.rb deleted file mode 100644 index 466300017d9..00000000000 --- a/spec/support/shared_examples/services/clusters/parse_cluster_applications_artifact_shared_examples.rb +++ /dev/null @@ -1,89 +0,0 @@ -# frozen_string_literal: true - -RSpec.shared_examples 'parse cluster applications artifact' do |release_name| - let(:application_class) { Clusters::Cluster::APPLICATIONS[release_name] } - let(:cluster_application) { cluster.public_send("application_#{release_name}") } - let(:file) { fixture_file_upload(Rails.root.join(fixture)) } - let(:artifact) { create(:ci_job_artifact, :cluster_applications, job: job, file: file) } - - context 'release is missing' do - let(:fixture) { "spec/fixtures/helm/helm_list_v2_#{release_name}_missing.json.gz" } - - context 'application does not exist' do - it 'does not create or destroy an application' do - expect do - described_class.new(job, user).execute(artifact) - end.not_to change(application_class, :count) - end - end - - context 'application exists' do - before do - create("clusters_applications_#{release_name}".to_sym, :installed, cluster: cluster) - end - - it 'marks the application as uninstalled' do - described_class.new(job, user).execute(artifact) - - cluster_application.reload - expect(cluster_application).to be_uninstalled - end - end - end - - context 'release is deployed' do - let(:fixture) { "spec/fixtures/helm/helm_list_v2_#{release_name}_deployed.json.gz" } - - context 'application does not exist' do - it 'creates an application and marks it as installed' do - expect do - described_class.new(job, user).execute(artifact) - end.to change(application_class, :count) - - expect(cluster_application).to be_persisted - expect(cluster_application).to be_externally_installed - end - end - - context 'application exists' do - before do - create("clusters_applications_#{release_name}".to_sym, :errored, cluster: cluster) - end - - it 'marks the application as installed' do - described_class.new(job, user).execute(artifact) - - expect(cluster_application).to be_externally_installed - end - end - end - - context 'release is failed' do - let(:fixture) { "spec/fixtures/helm/helm_list_v2_#{release_name}_failed.json.gz" } - - context 'application does not exist' do - it 'creates an application and marks it as errored' do - expect do - described_class.new(job, user).execute(artifact) - end.to change(application_class, :count) - - expect(cluster_application).to be_persisted - expect(cluster_application).to be_errored - expect(cluster_application.status_reason).to eq('Helm release failed to install') - end - end - - context 'application exists' do - before do - create("clusters_applications_#{release_name}".to_sym, :installed, cluster: cluster) - end - - it 'marks the application as errored' do - described_class.new(job, user).execute(artifact) - - expect(cluster_application).to be_errored - expect(cluster_application.status_reason).to eq('Helm release failed to install') - end - end - end -end diff --git a/spec/tooling/danger/project_helper_spec.rb b/spec/tooling/danger/project_helper_spec.rb index 3275b41ba6e..7474709d255 100644 --- a/spec/tooling/danger/project_helper_spec.rb +++ b/spec/tooling/danger/project_helper_spec.rb @@ -112,10 +112,10 @@ RSpec.describe Tooling::Danger::ProjectHelper do 'FOO_VERSION' | [:backend] 'Dangerfile' | [:engineering_productivity] - 'danger/commit_messages/Dangerfile' | [:engineering_productivity] - 'ee/danger/commit_messages/Dangerfile' | [:engineering_productivity] - 'danger/commit_messages/' | [:engineering_productivity] - 'ee/danger/commit_messages/' | [:engineering_productivity] + 'danger/bundle_size/Dangerfile' | [:engineering_productivity] + 'ee/danger/bundle_size/Dangerfile' | [:engineering_productivity] + 'danger/bundle_size/' | [:engineering_productivity] + 'ee/danger/bundle_size/' | [:engineering_productivity] '.gitlab-ci.yml' | [:engineering_productivity] '.gitlab/ci/cng.gitlab-ci.yml' | [:engineering_productivity] '.gitlab/ci/ee-specific-checks.gitlab-ci.yml' | [:engineering_productivity] @@ -218,7 +218,7 @@ RSpec.describe Tooling::Danger::ProjectHelper do describe '.local_warning_message' do it 'returns an informational message with rules that can run' do - expect(described_class.local_warning_message).to eq('==> Only the following Danger rules can be run locally: changelog, commit_messages, database, datateam, documentation, duplicate_yarn_dependencies, eslint, karma, pajamas, pipeline, prettier, product_intelligence, utility_css') + expect(described_class.local_warning_message).to eq('==> Only the following Danger rules can be run locally: changelog, database, datateam, documentation, duplicate_yarn_dependencies, eslint, karma, pajamas, pipeline, prettier, product_intelligence, utility_css') end end diff --git a/tooling/danger/project_helper.rb b/tooling/danger/project_helper.rb index c0aa27b7a0c..a29dc5e5bed 100644 --- a/tooling/danger/project_helper.rb +++ b/tooling/danger/project_helper.rb @@ -5,7 +5,6 @@ module Tooling module ProjectHelper LOCAL_RULES ||= %w[ changelog - commit_messages database datateam documentation diff --git a/vendor/fluentd/values.yaml b/vendor/fluentd/values.yaml deleted file mode 100644 index a5072ef14ae..00000000000 --- a/vendor/fluentd/values.yaml +++ /dev/null @@ -1,18 +0,0 @@ -plugins: - enabled: true - pluginsList: ["fluent-plugin-remote_syslog"] - -extraVolumes: - - name: varlog - hostPath: - path: /var/log - - name: varlibdockercontainers - hostPath: - path: /var/lib/docker/containers - -extraVolumeMounts: - - name: varlog - mountPath: /var/log - - name: varlibdockercontainers - mountPath: /var/lib/docker/containers - readOnly: true diff --git a/yarn.lock b/yarn.lock index e5b5c8cc88b..980b8fa5990 100644 --- a/yarn.lock +++ b/yarn.lock @@ -908,10 +908,10 @@ resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8" integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw== -"@gitlab/ui@29.34.0": - version "29.34.0" - resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-29.34.0.tgz#c8e9d7411f98537d3153d99b6c614583d4d1285d" - integrity sha512-ukEHnvd+4f9M+K4b5EArVygUDbS+kUcsP94f6I7Rvd95TR/LlJXwf6vtFdgdBNbk8W98AzW9GwdlT4hmgWfRdw== +"@gitlab/ui@29.34.1": + version "29.34.1" + resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-29.34.1.tgz#1dfd6864c0c7b325745f28ec708d1f187df3acd8" + integrity sha512-uNS3KNAzDFELq5SkfN7Yg9F8Pc98kcPVaXVhZGvw8JcjyVdLF4AORUbzFBsAtJXOwkWPH8yfBQY7+RVC9wkjGg== dependencies: "@babel/standalone" "^7.0.0" "@gitlab/vue-toasted" "^1.3.0" |