summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-05-03 12:13:11 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2023-05-03 12:13:11 +0000
commit2c01907a1ab4b328e2f20ddf9e10dfe6dc17105a (patch)
tree5c9aec88c17b1046dd7e47657c39f3f8f36bf0f1
parent29761d24b86b7a091ca83df4e8cd1cc14f81d534 (diff)
downloadgitlab-ce-2c01907a1ab4b328e2f20ddf9e10dfe6dc17105a.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/graphql_shared/possible_types.json4
-rw-r--r--app/assets/javascripts/lib/utils/vue3compat/get_instance_from_directive.js9
-rw-r--r--app/assets/javascripts/ml/experiment_tracking/routes/candidates/show/ml_candidates_show.vue8
-rw-r--r--app/assets/javascripts/ml/experiment_tracking/routes/candidates/show/translations.js1
-rw-r--r--app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue20
-rw-r--r--app/assets/javascripts/packages_and_registries/dependency_proxy/index.js3
-rw-r--r--app/assets/javascripts/projects/settings/components/shared_runners_toggle.vue25
-rw-r--r--app/assets/javascripts/vue_shared/directives/validation.js19
-rw-r--r--app/helpers/projects/ml/experiments_helper.rb1
-rw-r--r--app/models/namespace/aggregation_schedule.rb8
-rw-r--r--app/views/groups/dependency_proxies/show.html.haml1
-rw-r--r--config/feature_flags/development/single_file_file_by_file.yml2
-rw-r--r--db/post_migrate/20230419094535_ensure_merge_request_metrics_id_bigint_backfill_is_finished_for_self_hosts.rb24
-rw-r--r--db/post_migrate/20230419094939_swap_merge_request_metrics_id_to_bigint_for_self_hosts.rb82
-rw-r--r--db/schema_migrations/202304190945351
-rw-r--r--db/schema_migrations/202304190949391
-rw-r--r--doc/api/graphql/reference/index.md46
-rw-r--r--doc/development/documentation/redirects.md11
-rw-r--r--doc/development/testing_guide/flaky_tests.md5
-rw-r--r--doc/integration/jira/connect-app.md24
-rw-r--r--doc/integration/jira/development_panel.md110
-rw-r--r--doc/integration/jira/dvcs/index.md109
-rw-r--r--doc/integration/jira/dvcs/troubleshooting.md2
-rw-r--r--locale/gitlab.pot15
-rw-r--r--package.json4
-rwxr-xr-xscripts/review_apps/review-apps.sh18
-rw-r--r--spec/controllers/import/gitea_controller_spec.rb20
-rw-r--r--spec/features/groups/dependency_proxy_spec.rb10
-rw-r--r--spec/frontend/ml/experiment_tracking/routes/candidates/show/__snapshots__/ml_candidates_show_spec.js.snap14
-rw-r--r--spec/frontend/ml/experiment_tracking/routes/candidates/show/ml_candidates_show_spec.js1
-rw-r--r--spec/frontend/packages_and_registries/dependency_proxy/app_spec.js37
-rw-r--r--spec/frontend/projects/settings/components/shared_runners_toggle_spec.js16
-rw-r--r--spec/helpers/projects/ml/experiments_helper_spec.rb1
-rw-r--r--spec/migrations/ensure_merge_request_metrics_id_bigint_backfill_is_finished_for_self_hosts_spec.rb25
-rw-r--r--spec/migrations/swap_merge_request_metrics_id_to_bigint_for_self_hosts_spec.rb150
-rw-r--r--spec/models/namespace/aggregation_schedule_spec.rb22
-rw-r--r--spec/workers/namespaces/prune_aggregation_schedules_worker_spec.rb3
-rw-r--r--spec/workers/project_cache_worker_spec.rb9
-rw-r--r--yarn.lock18
39 files changed, 365 insertions, 514 deletions
diff --git a/app/assets/javascripts/graphql_shared/possible_types.json b/app/assets/javascripts/graphql_shared/possible_types.json
index f7d1efc4d1f..c6c145f5e2b 100644
--- a/app/assets/javascripts/graphql_shared/possible_types.json
+++ b/app/assets/javascripts/graphql_shared/possible_types.json
@@ -40,6 +40,10 @@
"BoardEpic",
"Epic"
],
+ "ExternalAuditEventDestinationInterface": [
+ "ExternalAuditEventDestination",
+ "InstanceExternalAuditEventDestination"
+ ],
"Issuable": [
"Epic",
"Issue",
diff --git a/app/assets/javascripts/lib/utils/vue3compat/get_instance_from_directive.js b/app/assets/javascripts/lib/utils/vue3compat/get_instance_from_directive.js
new file mode 100644
index 00000000000..b69f5e0c546
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/vue3compat/get_instance_from_directive.js
@@ -0,0 +1,9 @@
+// See https://v3-migration.vuejs.org/breaking-changes/custom-directives.html#edge-case-accessing-the-component-instance
+export function getInstanceFromDirective({ binding, vnode }) {
+ if (binding.instance) {
+ // this is Vue.js 3, even in compat mode
+ return binding.instance;
+ }
+
+ return vnode.context;
+}
diff --git a/app/assets/javascripts/ml/experiment_tracking/routes/candidates/show/ml_candidates_show.vue b/app/assets/javascripts/ml/experiment_tracking/routes/candidates/show/ml_candidates_show.vue
index 23b58543f11..b671bdc47a6 100644
--- a/app/assets/javascripts/ml/experiment_tracking/routes/candidates/show/ml_candidates_show.vue
+++ b/app/assets/javascripts/ml/experiment_tracking/routes/candidates/show/ml_candidates_show.vue
@@ -16,6 +16,7 @@ import {
DELETE_CANDIDATE_CONFIRMATION_MESSAGE,
DELETE_CANDIDATE_PRIMARY_ACTION_LABEL,
DELETE_CANDIDATE_MODAL_TITLE,
+ MLFLOW_ID_LABEL,
} from './translations';
export default {
@@ -44,6 +45,7 @@ export default {
DELETE_CANDIDATE_CONFIRMATION_MESSAGE,
DELETE_CANDIDATE_PRIMARY_ACTION_LABEL,
DELETE_CANDIDATE_MODAL_TITLE,
+ MLFLOW_ID_LABEL,
},
computed: {
sections() {
@@ -102,6 +104,12 @@ export default {
<tr>
<td></td>
+ <td class="gl-font-weight-bold">{{ $options.i18n.MLFLOW_ID_LABEL }}</td>
+ <td>{{ candidate.info.eid }}</td>
+ </tr>
+
+ <tr>
+ <td></td>
<td class="gl-font-weight-bold">{{ $options.i18n.STATUS_LABEL }}</td>
<td>{{ candidate.info.status }}</td>
</tr>
diff --git a/app/assets/javascripts/ml/experiment_tracking/routes/candidates/show/translations.js b/app/assets/javascripts/ml/experiment_tracking/routes/candidates/show/translations.js
index 5f7714aa0c0..66ee84adb4e 100644
--- a/app/assets/javascripts/ml/experiment_tracking/routes/candidates/show/translations.js
+++ b/app/assets/javascripts/ml/experiment_tracking/routes/candidates/show/translations.js
@@ -3,6 +3,7 @@ import { s__ } from '~/locale';
export const TITLE_LABEL = s__('MlExperimentTracking|Model candidate details');
export const INFO_LABEL = s__('MlExperimentTracking|Info');
export const ID_LABEL = s__('MlExperimentTracking|ID');
+export const MLFLOW_ID_LABEL = s__('MlExperimentTracking|MLflow run ID');
export const STATUS_LABEL = s__('MlExperimentTracking|Status');
export const EXPERIMENT_LABEL = s__('MlExperimentTracking|Experiment');
export const ARTIFACTS_LABEL = s__('MlExperimentTracking|Artifacts');
diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue b/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue
index 48e5bb8f0b2..732d544816b 100644
--- a/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue
+++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue
@@ -1,6 +1,7 @@
<script>
import {
GlAlert,
+ GlButton,
GlDropdown,
GlDropdownItem,
GlEmptyState,
@@ -9,6 +10,7 @@ import {
GlModal,
GlModalDirective,
GlSprintf,
+ GlTooltipDirective,
} from '@gitlab/ui';
import { __, s__, n__, sprintf } from '~/locale';
import Api from '~/api';
@@ -23,6 +25,7 @@ import getDependencyProxyDetailsQuery from '~/packages_and_registries/dependency
export default {
components: {
GlAlert,
+ GlButton,
GlDropdown,
GlDropdownItem,
GlEmptyState,
@@ -36,8 +39,9 @@ export default {
},
directives: {
GlModalDirective,
+ GlTooltip: GlTooltipDirective,
},
- inject: ['groupPath', 'groupId', 'noManifestsIllustration', 'canClearCache'],
+ inject: ['groupPath', 'groupId', 'noManifestsIllustration', 'canClearCache', 'settingsPath'],
i18n: {
proxyImagePrefix: s__('DependencyProxy|Dependency Proxy image prefix'),
copyImagePrefixText: s__('DependencyProxy|Copy prefix'),
@@ -48,6 +52,7 @@ export default {
'DependencyProxy|All items in the cache are scheduled for removal.',
),
clearCache: s__('DependencyProxy|Clear cache'),
+ settingsText: s__('DependencyProxy|Configure in settings'),
},
confirmClearCacheModal: 'confirm-clear-cache-modal',
modalButtons: {
@@ -112,7 +117,7 @@ export default {
);
},
showDeleteDropdown() {
- return this.group.dependencyProxyManifests?.nodes.length > 0 && this.canClearCache;
+ return this.manifests?.length > 0 && this.canClearCache;
},
dependencyProxyImagePrefix() {
return this.group.dependencyProxyImagePrefix;
@@ -168,8 +173,9 @@ export default {
{{ deleteCacheAlertMessage }}
</gl-alert>
<title-area :title="$options.i18n.pageTitle">
- <template v-if="showDeleteDropdown" #right-actions>
+ <template #right-actions>
<gl-dropdown
+ v-if="showDeleteDropdown"
icon="ellipsis_v"
text="More actions"
:text-sr-only="true"
@@ -182,6 +188,14 @@ export default {
>{{ $options.i18n.clearCache }}</gl-dropdown-item
>
</gl-dropdown>
+ <gl-button
+ v-if="canClearCache"
+ v-gl-tooltip="$options.i18n.settingsText"
+ icon="settings"
+ data-testid="settings-link"
+ :href="settingsPath"
+ :aria-label="$options.i18n.settingsText"
+ />
</template>
</title-area>
diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/index.js b/app/assets/javascripts/packages_and_registries/dependency_proxy/index.js
index 428d6d6cd75..74444d2c7ec 100644
--- a/app/assets/javascripts/packages_and_registries/dependency_proxy/index.js
+++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/index.js
@@ -11,7 +11,7 @@ export const initDependencyProxyApp = () => {
if (!el) {
return null;
}
- const { groupPath, groupId, noManifestsIllustration, canClearCache } = el.dataset;
+ const { groupPath, groupId, noManifestsIllustration, canClearCache, settingsPath } = el.dataset;
return new Vue({
el,
apolloProvider,
@@ -20,6 +20,7 @@ export const initDependencyProxyApp = () => {
groupId,
noManifestsIllustration,
canClearCache: parseBoolean(canClearCache),
+ settingsPath,
},
render(createElement) {
return createElement(app);
diff --git a/app/assets/javascripts/projects/settings/components/shared_runners_toggle.vue b/app/assets/javascripts/projects/settings/components/shared_runners_toggle.vue
index aa3235b1515..b8e7e9e15db 100644
--- a/app/assets/javascripts/projects/settings/components/shared_runners_toggle.vue
+++ b/app/assets/javascripts/projects/settings/components/shared_runners_toggle.vue
@@ -1,5 +1,5 @@
<script>
-import { GlAlert, GlToggle, GlTooltip } from '@gitlab/ui';
+import { GlAlert, GlToggle } from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils';
import { __, s__ } from '~/locale';
import { CC_VALIDATION_REQUIRED_ERROR } from '../constants';
@@ -16,7 +16,6 @@ export default {
components: {
GlAlert,
GlToggle,
- GlTooltip,
CcValidationRequiredAlert: () =>
import('ee_component/billings/components/cc_validation_required_alert.vue'),
},
@@ -94,10 +93,26 @@ export default {
@dismiss="ccAlertDismissed = true"
/>
- <gl-alert v-if="genericError" class="gl-mb-3" variant="danger" :dismissible="false">
+ <gl-alert
+ v-if="genericError"
+ data-testid="error-alert"
+ variant="danger"
+ :dismissible="false"
+ class="gl-mb-5"
+ >
{{ errorMessage }}
</gl-alert>
+ <gl-alert
+ v-if="isDisabledAndUnoverridable"
+ data-testid="unoverridable-alert"
+ variant="warning"
+ :dismissible="false"
+ class="gl-mb-5"
+ >
+ {{ s__('Runners|Shared runners are disabled in the group settings') }}
+ </gl-alert>
+
<gl-toggle
ref="sharedRunnersToggle"
:disabled="isDisabledAndUnoverridable"
@@ -107,10 +122,6 @@ export default {
data-testid="toggle-shared-runners"
@change="toggleSharedRunners"
/>
-
- <gl-tooltip v-if="isDisabledAndUnoverridable" :target="() => $refs.sharedRunnersToggle">
- {{ __('Shared runners are disabled on group level') }}
- </gl-tooltip>
</section>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/directives/validation.js b/app/assets/javascripts/vue_shared/directives/validation.js
index fc0ff78e7b4..b9a09c2521c 100644
--- a/app/assets/javascripts/vue_shared/directives/validation.js
+++ b/app/assets/javascripts/vue_shared/directives/validation.js
@@ -1,4 +1,5 @@
import { __ } from '~/locale';
+import { getInstanceFromDirective } from '~/lib/utils/vue3compat/get_instance_from_directive';
/**
* Validation messages will take priority based on the property order.
@@ -45,8 +46,7 @@ const getInputElement = (el) => {
const isEveryFieldValid = (form) => Object.values(form.fields).every(({ state }) => state === true);
-const createValidator = (context, feedbackMap) => ({ el, reportInvalidInput = false }) => {
- const { form } = context;
+const createValidator = (feedbackMap) => ({ el, form, reportInvalidInput = false }) => {
const { name } = el;
if (!name) {
@@ -69,6 +69,7 @@ const createValidator = (context, feedbackMap) => ({ el, reportInvalidInput = fa
formField.state = reportInvalidInput ? isValid : isValid || null;
formField.feedback = reportInvalidInput ? getFeedbackForElement(feedbackMap, el) : '';
+ // eslint-disable-next-line no-param-reassign
form.state = isEveryFieldValid(form);
};
@@ -102,12 +103,13 @@ export default function initValidation(customFeedbackMap = {}) {
const elDataMap = new WeakMap();
return {
- inserted(element, binding, { context }) {
+ inserted(element, binding, vnode) {
const { arg: showGlobalValidation } = binding;
const el = getInputElement(element);
const { form: formEl } = el;
+ const instance = getInstanceFromDirective({ binding, vnode });
- const validate = createValidator(context, feedbackMap);
+ const validate = createValidator(feedbackMap);
const elData = { validate, isTouched: false, isBlurred: false };
elDataMap.set(el, elData);
@@ -121,7 +123,7 @@ export default function initValidation(customFeedbackMap = {}) {
el.addEventListener('blur', function markAsBlurred({ target }) {
if (elData.isTouched) {
elData.isBlurred = true;
- validate({ el: target, reportInvalidInput: true });
+ validate({ el: target, form: instance.form, reportInvalidInput: true });
// this event handler can be removed, since the live-feedback in `update` takes over
el.removeEventListener('blur', markAsBlurred);
}
@@ -131,15 +133,16 @@ export default function initValidation(customFeedbackMap = {}) {
formEl.addEventListener('submit', focusFirstInvalidInput);
}
- validate({ el, reportInvalidInput: showGlobalValidation });
+ validate({ el, form: instance.form, reportInvalidInput: showGlobalValidation });
},
- update(element, binding) {
+ update(element, binding, vnode) {
const el = getInputElement(element);
const { arg: showGlobalValidation } = binding;
const { validate, isTouched, isBlurred } = elDataMap.get(el);
const showValidationFeedback = showGlobalValidation || (isTouched && isBlurred);
- validate({ el, reportInvalidInput: showValidationFeedback });
+ const instance = getInstanceFromDirective({ binding, vnode });
+ validate({ el, form: instance.form, reportInvalidInput: showValidationFeedback });
},
};
}
diff --git a/app/helpers/projects/ml/experiments_helper.rb b/app/helpers/projects/ml/experiments_helper.rb
index 1f044ebed3b..bcf07df0e72 100644
--- a/app/helpers/projects/ml/experiments_helper.rb
+++ b/app/helpers/projects/ml/experiments_helper.rb
@@ -12,6 +12,7 @@ module Projects
metrics: candidate.latest_metrics,
info: {
iid: candidate.iid,
+ eid: candidate.eid,
path_to_artifact: link_to_artifact(candidate),
experiment_name: candidate.experiment.name,
path_to_experiment: link_to_experiment(candidate.project, candidate.experiment),
diff --git a/app/models/namespace/aggregation_schedule.rb b/app/models/namespace/aggregation_schedule.rb
index 0312016b1d7..e08c08f9ced 100644
--- a/app/models/namespace/aggregation_schedule.rb
+++ b/app/models/namespace/aggregation_schedule.rb
@@ -12,8 +12,8 @@ class Namespace::AggregationSchedule < ApplicationRecord
after_create :schedule_root_storage_statistics
- def self.default_lease_timeout
- if Feature.enabled?(:reduce_aggregation_schedule_lease)
+ def default_lease_timeout
+ if Feature.enabled?(:reduce_aggregation_schedule_lease, namespace.root_ancestor)
2.minutes.to_i
else
30.minutes.to_i
@@ -27,7 +27,7 @@ class Namespace::AggregationSchedule < ApplicationRecord
.perform_async(namespace_id)
Namespaces::RootStatisticsWorker
- .perform_in(self.class.default_lease_timeout, namespace_id)
+ .perform_in(default_lease_timeout, namespace_id)
end
end
end
@@ -36,7 +36,7 @@ class Namespace::AggregationSchedule < ApplicationRecord
# Used by ExclusiveLeaseGuard
def lease_timeout
- self.class.default_lease_timeout
+ default_lease_timeout
end
# Used by ExclusiveLeaseGuard
diff --git a/app/views/groups/dependency_proxies/show.html.haml b/app/views/groups/dependency_proxies/show.html.haml
index 23d397faaf5..8416cb81c95 100644
--- a/app/views/groups/dependency_proxies/show.html.haml
+++ b/app/views/groups/dependency_proxies/show.html.haml
@@ -3,4 +3,5 @@
#js-dependency-proxy{ data: { group_path: @group.full_path,
no_manifests_illustration: image_path('illustrations/docker-empty-state.svg'),
group_id: @group.id,
+ settings_path: group_settings_packages_and_registries_path(@group),
can_clear_cache: can?(current_user, :admin_group, @group).to_s } }
diff --git a/config/feature_flags/development/single_file_file_by_file.yml b/config/feature_flags/development/single_file_file_by_file.yml
index 4efc81f18af..bc38cf8afb2 100644
--- a/config/feature_flags/development/single_file_file_by_file.yml
+++ b/config/feature_flags/development/single_file_file_by_file.yml
@@ -5,4 +5,4 @@ rollout_issue_url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/403571'
milestone: '15.11'
type: development
group: group::code review
-default_enabled: false
+default_enabled: true
diff --git a/db/post_migrate/20230419094535_ensure_merge_request_metrics_id_bigint_backfill_is_finished_for_self_hosts.rb b/db/post_migrate/20230419094535_ensure_merge_request_metrics_id_bigint_backfill_is_finished_for_self_hosts.rb
deleted file mode 100644
index decfdf0a3ca..00000000000
--- a/db/post_migrate/20230419094535_ensure_merge_request_metrics_id_bigint_backfill_is_finished_for_self_hosts.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class EnsureMergeRequestMetricsIdBigintBackfillIsFinishedForSelfHosts < Gitlab::Database::Migration[2.1]
- include Gitlab::Database::MigrationHelpers::ConvertToBigint
-
- disable_ddl_transaction!
-
- restrict_gitlab_migration gitlab_schema: :gitlab_main
-
- TABLE_NAME = 'merge_request_metrics'
-
- def up
- ensure_batched_background_migration_is_finished(
- job_class_name: 'CopyColumnUsingBackgroundMigrationJob',
- table_name: TABLE_NAME,
- column_name: 'id',
- job_arguments: [['id'], ['id_convert_to_bigint']]
- )
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20230419094939_swap_merge_request_metrics_id_to_bigint_for_self_hosts.rb b/db/post_migrate/20230419094939_swap_merge_request_metrics_id_to_bigint_for_self_hosts.rb
deleted file mode 100644
index d249ffb9c1b..00000000000
--- a/db/post_migrate/20230419094939_swap_merge_request_metrics_id_to_bigint_for_self_hosts.rb
+++ /dev/null
@@ -1,82 +0,0 @@
-# frozen_string_literal: true
-
-class SwapMergeRequestMetricsIdToBigintForSelfHosts < Gitlab::Database::Migration[2.1]
- include Gitlab::Database::MigrationHelpers::ConvertToBigint
-
- disable_ddl_transaction!
-
- TABLE_NAME = 'merge_request_metrics'
- TMP_INDEX_NAME = 'tmp_index_mr_metrics_on_target_project_id_merged_at_nulls_last'
- INDEX_NAME = 'index_mr_metrics_on_target_project_id_merged_at_nulls_last'
- CONSTRAINT_NAME = 'merge_request_metrics_pkey'
-
- def up
- return if should_skip?
- return if temporary_column_already_dropped?
- return if columns_alredy_swapped?
-
- swap
- end
-
- def down
- return if should_skip?
- return if temporary_column_already_dropped?
- return unless columns_alredy_swapped?
-
- swap
- end
-
- private
-
- def swap
- add_concurrent_index TABLE_NAME, :id_convert_to_bigint, unique: true,
- name: 'index_merge_request_metrics_on_id_convert_to_bigint'
- add_concurrent_index TABLE_NAME, 'target_project_id, merged_at DESC NULLS LAST, id_convert_to_bigint DESC',
- name: TMP_INDEX_NAME
-
- with_lock_retries(raise_on_exhaustion: true) do
- execute "LOCK TABLE #{TABLE_NAME} IN ACCESS EXCLUSIVE MODE"
-
- execute "ALTER TABLE #{TABLE_NAME} RENAME COLUMN id TO id_tmp"
- execute "ALTER TABLE #{TABLE_NAME} RENAME COLUMN id_convert_to_bigint TO id"
- execute "ALTER TABLE #{TABLE_NAME} RENAME COLUMN id_tmp TO id_convert_to_bigint"
-
- function_name = Gitlab::Database::UnidirectionalCopyTrigger
- .on_table(TABLE_NAME, connection: connection)
- .name(:id, :id_convert_to_bigint)
- execute "ALTER FUNCTION #{quote_table_name(function_name)} RESET ALL"
-
- # Swap defaults of the columns, and change ownership of the sequence to the new id
- execute "ALTER SEQUENCE merge_request_metrics_id_seq OWNED BY #{TABLE_NAME}.id"
- change_column_default TABLE_NAME, :id, -> { "nextval('merge_request_metrics_id_seq'::regclass)" }
- change_column_default TABLE_NAME, :id_convert_to_bigint, 0
-
- # Swap PK constraint
- execute "ALTER TABLE #{TABLE_NAME} DROP CONSTRAINT IF EXISTS #{CONSTRAINT_NAME}"
- rename_index TABLE_NAME, 'index_merge_request_metrics_on_id_convert_to_bigint', CONSTRAINT_NAME
- execute "ALTER TABLE #{TABLE_NAME} ADD CONSTRAINT #{CONSTRAINT_NAME} PRIMARY KEY USING INDEX #{CONSTRAINT_NAME}"
-
- # Rename the rest of the indexes (we already hold an exclusive lock, so no need to use DROP INDEX CONCURRENTLY)
- execute "DROP INDEX IF EXISTS #{INDEX_NAME}"
- rename_index TABLE_NAME, TMP_INDEX_NAME, INDEX_NAME
- end
- end
-
- def should_skip?
- com_or_dev_or_test_but_not_jh?
- end
-
- def columns_alredy_swapped?
- table_columns = columns(TABLE_NAME)
- column_id = table_columns.find { |c| c.name == 'id' }
- column_id_convert_to_bigint = table_columns.find { |c| c.name == 'id_convert_to_bigint' }
-
- column_id.sql_type == 'bigint' && column_id_convert_to_bigint.sql_type == 'integer'
- end
-
- def temporary_column_already_dropped?
- table_columns = columns(TABLE_NAME)
-
- !table_columns.find { |c| c.name == 'id_convert_to_bigint' }
- end
-end
diff --git a/db/schema_migrations/20230419094535 b/db/schema_migrations/20230419094535
deleted file mode 100644
index 7df3afa8a17..00000000000
--- a/db/schema_migrations/20230419094535
+++ /dev/null
@@ -1 +0,0 @@
-09e9e754b83635abe717fa686b13488f965ae9678f74e0a47e802941d3501d5a \ No newline at end of file
diff --git a/db/schema_migrations/20230419094939 b/db/schema_migrations/20230419094939
deleted file mode 100644
index 643e94129a2..00000000000
--- a/db/schema_migrations/20230419094939
+++ /dev/null
@@ -1 +0,0 @@
-a0e01b39610c5c307e34a5215ce4aa47a24fc0f5cff62ebef13172ef6761198b \ No newline at end of file
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 7d315fb65e0..fe04693aa58 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -3473,6 +3473,25 @@ Input type: `HttpIntegrationUpdateInput`
| <a id="mutationhttpintegrationupdateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationhttpintegrationupdateintegration"></a>`integration` | [`AlertManagementHttpIntegration`](#alertmanagementhttpintegration) | HTTP integration. |
+### `Mutation.instanceExternalAuditEventDestinationCreate`
+
+Input type: `InstanceExternalAuditEventDestinationCreateInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationinstanceexternalauditeventdestinationcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationinstanceexternalauditeventdestinationcreatedestinationurl"></a>`destinationUrl` | [`String!`](#string) | Destination URL. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationinstanceexternalauditeventdestinationcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationinstanceexternalauditeventdestinationcreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| <a id="mutationinstanceexternalauditeventdestinationcreateinstanceexternalauditeventdestination"></a>`instanceExternalAuditEventDestination` | [`InstanceExternalAuditEventDestination`](#instanceexternalauditeventdestination) | Destination created. |
+
### `Mutation.issuableResourceLinkCreate`
Input type: `IssuableResourceLinkCreateInput`
@@ -15746,6 +15765,18 @@ A block of time for which a participant is on-call.
| <a id="incidentmanagementoncallshiftparticipant"></a>`participant` | [`OncallParticipantType`](#oncallparticipanttype) | Participant assigned to the on-call shift. |
| <a id="incidentmanagementoncallshiftstartsat"></a>`startsAt` | [`Time`](#time) | Start time of the on-call shift. |
+### `InstanceExternalAuditEventDestination`
+
+Represents an external resource to send instance audit events to.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="instanceexternalauditeventdestinationdestinationurl"></a>`destinationUrl` | [`String!`](#string) | External destination to send audit events to. |
+| <a id="instanceexternalauditeventdestinationid"></a>`id` | [`ID!`](#id) | ID of the destination. |
+| <a id="instanceexternalauditeventdestinationverificationtoken"></a>`verificationToken` | [`String!`](#string) | Verification token to validate source of event. |
+
### `InstanceSecurityDashboard`
#### Fields
@@ -26173,6 +26204,21 @@ Implementations:
| ---- | ---- | ----------- |
| <a id="eventableevents"></a>`events` | [`EventConnection`](#eventconnection) | List of events associated with the object. (see [Connections](#connections)) |
+#### `ExternalAuditEventDestinationInterface`
+
+Implementations:
+
+- [`ExternalAuditEventDestination`](#externalauditeventdestination)
+- [`InstanceExternalAuditEventDestination`](#instanceexternalauditeventdestination)
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="externalauditeventdestinationinterfacedestinationurl"></a>`destinationUrl` | [`String!`](#string) | External destination to send audit events to. |
+| <a id="externalauditeventdestinationinterfaceid"></a>`id` | [`ID!`](#id) | ID of the destination. |
+| <a id="externalauditeventdestinationinterfaceverificationtoken"></a>`verificationToken` | [`String!`](#string) | Verification token to validate source of event. |
+
#### `MemberInterface`
Implementations:
diff --git a/doc/development/documentation/redirects.md b/doc/development/documentation/redirects.md
index 068c1e84a0f..f080625ea9c 100644
--- a/doc/development/documentation/redirects.md
+++ b/doc/development/documentation/redirects.md
@@ -157,3 +157,14 @@ If you create a new page and then rename it before it's added to a release on th
Instead of following that procedure, ask a Technical Writer to manually add the redirect
to [`redirects.yaml`](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/content/_data/redirects.yaml).
+
+## Exceptions to creating a redirect
+
+In some cases you can skip adding the redirect and just delete the file. The page
+must have already been removed from (or never existed in) the navigation, and one
+of the following must be true:
+
+- The page was added and removed in the same release, so it was never included in
+ a self-managed release.
+- The page does not contain any content of value, like a placeholder page or a page
+ with extremely low usage statistics.
diff --git a/doc/development/testing_guide/flaky_tests.md b/doc/development/testing_guide/flaky_tests.md
index e41c680e0ee..d8bdc56f265 100644
--- a/doc/development/testing_guide/flaky_tests.md
+++ b/doc/development/testing_guide/flaky_tests.md
@@ -81,6 +81,11 @@ difficult to achieve locally.
suite, it might pass as not enough records were created before it, but as soon as it would run
later in the suite, there could be a record that actually has the ID `42`, hence the test would
start to fail.
+- [Example 3](https://gitlab.com/gitlab-org/gitlab/-/issues/402915): State leakage can result from
+ data records created with `let_it_be` shared between test examples, while some test modifies the model
+ either deliberately or unwillingly causing out-of-sync data in test examples. This can result in `PG::QueryCanceled: ERROR` in the subsequent test examples or retries.
+ For more information about state leakages and resolution options,
+ see [GitLab testing best practices](best_practices.md#lets-talk-about-let).
### Random input
diff --git a/doc/integration/jira/connect-app.md b/doc/integration/jira/connect-app.md
index 06aa8c218dd..b40d9707274 100644
--- a/doc/integration/jira/connect-app.md
+++ b/doc/integration/jira/connect-app.md
@@ -6,7 +6,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# GitLab for Jira Cloud app **(FREE)**
-With the [GitLab for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud) app, you can connect GitLab and Jira Cloud and use the Jira development panel.
+With the [GitLab for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud) app, you can connect GitLab and Jira Cloud to sync development information in real time. You can view this information in the [Jira development panel](development_panel.md).
+
+You can use the GitLab for Jira Cloud app to link top-level groups or subgroups. It's not possible to directly link projects or personal namespaces.
- **For GitLab.com**:
- [Install the GitLab for Jira Cloud app](#install-the-gitlab-for-jira-cloud-app).
@@ -14,14 +16,15 @@ With the [GitLab for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/
- [Connect the GitLab for Jira Cloud app for self-managed instances](#connect-the-gitlab-for-jira-cloud-app-for-self-managed-instances) (GitLab 15.7 and later).
- [Install the GitLab for Jira Cloud app manually](#install-the-gitlab-for-jira-cloud-app-manually).
-If you use Jira Server or Jira Data Center, use the [Jira DVCS connector](dvcs/index.md) instead.
+If you use Jira Data Center or Jira Server, use the [Jira DVCS connector](dvcs/index.md) instead.
## Install the GitLab for Jira Cloud app **(FREE SAAS)**
Prerequisites:
-- You must have at least the Maintainer role for the GitLab namespace.
+- You must have at least the Maintainer role for the GitLab group.
- You must have administrator access to the Jira instance.
+- Your network must allow inbound and outbound connections between GitLab and Jira.
To install the GitLab for Jira Cloud app:
@@ -32,14 +35,14 @@ To install the GitLab for Jira Cloud app:
1. To go to the configurations page, select **Get started**.
You can always access this page in **Jira Settings > Apps > Manage apps**.
-1. To open the list of available namespaces, select **Add namespace**.
-1. To link to a namespace, select **Link**.
+1. For a list of groups to link, select **Add namespace**.
+1. To link to a group, select **Link**.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an overview, see
[Configure the GitLab for Jira Cloud app from the Atlassian Marketplace](https://youtu.be/SwR-g1s1zTo).
-After you add a namespace, the following data is synced to Jira for all projects in that namespace:
+After you add a group, the following data is synced to Jira for all projects in that group:
- New merge requests, branches, and commits
- Existing merge requests (GitLab 13.8 and later)
@@ -100,6 +103,7 @@ It's not possible to create branches from Jira for self-managed instances. For m
- The instance must be publicly available.
- The instance must be on GitLab version 15.7 or later.
- You must set up [OAuth authentication](#set-up-oauth-authentication-for-self-managed-instances).
+- Your network must allow inbound and outbound connections between GitLab and Jira.
### Set up your instance
@@ -225,8 +229,8 @@ The OAuth application must have the `api` scope, which grants complete read and
This access includes all groups and projects, the container registry, and the package registry.
However, the GitLab for Jira Cloud app only uses this access to:
-- Display namespaces to be linked.
-- Link namespaces.
+- Display groups to link.
+- Link groups.
Access through OAuth is only needed for the time a user configures the GitLab for Jira Cloud app. For more information, see [Access token expiration](../oauth_provider.md#access-token-expiration).
@@ -248,7 +252,7 @@ when you're already signed in:
You need to sign in or sign up before continuing.
```
-The GitLab for Jira Cloud app uses an iframe to add namespaces on the
+The GitLab for Jira Cloud app uses an iframe to add groups on the
settings page. Some browsers block cross-site cookies, which can lead to this issue.
To resolve this issue, set up [OAuth authentication](#set-up-oauth-authentication-for-self-managed-instances).
@@ -296,7 +300,7 @@ To resolve this issue on GitLab self-managed, follow one of the solutions below,
- If you [installed the GitLab for Jira Cloud app manually](#install-the-gitlab-for-jira-cloud-app-manually):
- In GitLab 14.9 and later:
- - Contact the [Jira Software Cloud support](https://support.atlassian.com/jira-software-cloud/) and ask to trigger a new installed lifecycle event for the GitLab for Jira Cloud app in your namespace.
+ - Contact the [Jira Software Cloud support](https://support.atlassian.com/jira-software-cloud/) and ask to trigger a new installed lifecycle event for the GitLab for Jira Cloud app in your group.
- In all GitLab versions:
- Re-install the GitLab for Jira Cloud app. This method might remove all synced data from the Jira development panel.
diff --git a/doc/integration/jira/development_panel.md b/doc/integration/jira/development_panel.md
index a03507c4e19..f8c37394f85 100644
--- a/doc/integration/jira/development_panel.md
+++ b/doc/integration/jira/development_panel.md
@@ -8,29 +8,46 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/233149) from GitLab Premium to GitLab Free in 13.4.
-The Jira development panel connects all GitLab projects in a group or personal namespace
-where you can view GitLab activity.
+You can use the Jira development panel to view GitLab activity for a Jira issue directly in Jira.
+To set up the Jira development panel:
-When you're in GitLab, you can refer to a Jira issue by ID.
-The [activity for that issue](https://support.atlassian.com/jira-software-cloud/docs/view-development-information-for-an-issue/)
-is displayed in the Jira development panel.
+- **For Jira Cloud**, use the [GitLab for Jira Cloud app](connect-app.md) developed by GitLab.
+- **For Jira Data Center or Jira Server**, use the [Jira DVCS connector](dvcs/index.md) developed by Atlassian.
-In the Jira development panel, you can create a GitLab merge request from a branch.
-You can also create a GitLab branch from a Jira issue in the GitLab for Jira Cloud app
-([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66032) in GitLab 14.2).
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+For an overview, see [Jira development panel integration](https://www.youtube.com/watch?v=VjVTOmMl85M).
+
+## Feature availability
+
+This table shows the features available with the Jira DVCS connector and the GitLab for Jira Cloud app:
+
+| Feature | Jira DVCS connector | GitLab for Jira Cloud app |
+|---------------------|------------------------|---------------------------|
+| Smart Commits | **{check-circle}** Yes | **{check-circle}** Yes |
+| Sync merge requests | **{check-circle}** Yes | **{check-circle}** Yes |
+| Sync branches | **{check-circle}** Yes | **{check-circle}** Yes |
+| Sync commits | **{check-circle}** Yes | **{check-circle}** Yes |
+| Sync existing data | **{check-circle}** Yes | **{check-circle}** Yes |
+| Sync builds | **{dotted-circle}** No | **{check-circle}** Yes |
+| Sync deployments | **{dotted-circle}** No | **{check-circle}** Yes |
+| Sync feature flags | **{dotted-circle}** No | **{check-circle}** Yes |
+| Sync interval | Up to 60 minutes | Real time |
+| Create branches | **{dotted-circle}** No | **{check-circle}** Yes (GitLab SaaS only) |
+| Create merge request from branch | **{check-circle}** Yes | **{check-circle}** Yes |
+| Create branch from Jira issue | **{dotted-circle}** No | **{check-circle}** Yes ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66032) in GitLab 14.2) |
## Connected projects in GitLab
-The Jira development panel connects to the entire Jira instance all GitLab projects in:
+The Jira development panel connects a Jira instance with all its projects to the following:
-- A top-level group, including all projects in its subgroups.
-- A personal namespace.
+- **For the [GitLab for Jira Cloud app](connect-app.md)**, linked GitLab groups or subgroups and their projects
+- **For the [Jira DVCS connector](dvcs/index.md)**, linked GitLab groups, subgroups, or personal namespaces and their projects
-These GitLab projects can interact with all Jira projects in that instance.
+## Information displayed in the development panel
-## Information displayed in the panel
+You can [view GitLab activity for a Jira issue](https://support.atlassian.com/jira-software-cloud/docs/view-development-information-for-an-issue/) in the Jira development panel by referring to the Jira issue by ID in GitLab.
-The information displayed in the Jira development panel depends on where you mention the Jira issue ID in GitLab.
+The information displayed in the development panel depends on where you mention the Jira issue ID in GitLab.
| GitLab: where you mention the Jira issue ID | Jira development panel: what information is displayed |
|------------------------------------------------|-------------------------------------------------------|
@@ -41,58 +58,37 @@ The information displayed in the Jira development panel depends on where you men
## Jira Smart Commits
+Prerequisites:
+
+- You must have GitLab and Jira user accounts with the same email address or username.
+- The commands must be in the first line of the commit message.
+- The commit message must not span more than one line.
+
Jira Smart Commits are special commands to process a Jira issue. With these commands, you can use GitLab to:
- Add a custom comment to a Jira issue.
- Log time against a Jira issue.
- Transition a Jira issue to any status defined in the project workflow.
-For more information, see the
-[Atlassian documentation](https://confluence.atlassian.com/fisheye/using-smart-commits-960155400.html).
-
-## Configure the panel
+### Smart Commit syntax
-<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
-For an overview, see [Jira development panel integration](https://www.youtube.com/watch?v=VjVTOmMl85M).
-
-### For GitLab.com
-
-Prerequisite:
-
-- You must have at least the Maintainer role for the group.
-
-To configure the Jira development panel on GitLab.com:
-
-- **For [Jira Cloud](https://www.atlassian.com/migration/assess/why-cloud)**:
- - [From the Atlassian Marketplace, install the GitLab for Jira Cloud app](https://marketplace.atlassian.com/apps/1221011/gitlab-for-jira-cloud?hosting=cloud&tab=overview).
- - This method syncs data between GitLab.com and Jira in real time.
- - This method requires inbound connections for the setup and outbound connections to push data to Jira.
- - For more information, see [GitLab for Jira Cloud app](connect-app.md).
-- **For Jira Server**:
- - Use the [Jira DVCS connector](dvcs/index.md).
- - This method syncs data every hour and works only with inbound connections.
- - This method attempts to set up webhooks in GitLab to sync data in real time, which requires outbound connections.
-
-### For self-managed GitLab
-
-Prerequisites:
+Smart Commits must follow this syntax:
-- You must have administrator access to the instance.
-- Your GitLab installation must not use a [relative URL](https://docs.gitlab.com/omnibus/settings/configuration.html#configure-a-relative-url-for-gitlab)
- (for example, `https://example.com/gitlab`).
+```plaintext
+<ISSUE_KEY> <ignored text> #<command> <optional command parameters>
+```
-To configure the Jira development panel on self-managed GitLab:
+You can execute one or more commands in a single commit.
-- **For [Jira Cloud](https://www.atlassian.com/migration/assess/why-cloud)**:
- - [Install the GitLab for Jira Cloud app manually](connect-app.md#install-the-gitlab-for-jira-cloud-app-manually).
- - This method requires inbound connections for the setup and outbound connection to push data to Jira.
- - For more information, see [Connect the GitLab for Jira Cloud app for self-managed instances](connect-app.md#connect-the-gitlab-for-jira-cloud-app-for-self-managed-instances).
-- **For Jira Server**:
- - Use the [Jira DVCS connector](dvcs/index.md).
- - This method syncs data every hour and works only with inbound connections.
- - This method attempts to set up webhooks in GitLab to sync data in real time, which requires outbound connections.
+| Commands | Syntax |
+|-------------------------------------------------|--------------------------------------------------------------|
+| Add a comment | `KEY-123 #comment Bug is fixed` |
+| Log time | `KEY-123 #time 2w 4d 10h 52m Tracking work time` |
+| Close an issue | `KEY-123 #close Closing issue` |
+| Log time and close an issue | `KEY-123 #time 2d 5h #close` |
+| Add a comment and transition to **In-progress** | `KEY-123 #comment Started working on the issue #in-progress` |
-## Troubleshooting
+For more information about how Smart Commits work and what commands are available to use, see:
-To troubleshoot the Jira development panel on your own server, see the
-[Atlassian documentation](https://confluence.atlassian.com/jirakb/troubleshoot-the-development-panel-in-jira-server-574685212.html).
+- [Process issues with Smart Commits](https://support.atlassian.com/jira-software-cloud/docs/process-issues-with-smart-commits/)
+- [Using Smart Commits](https://confluence.atlassian.com/fisheye/using-smart-commits-960155400.html)
diff --git a/doc/integration/jira/dvcs/index.md b/doc/integration/jira/dvcs/index.md
index 858da15d638..ceaa6255047 100644
--- a/doc/integration/jira/dvcs/index.md
+++ b/doc/integration/jira/dvcs/index.md
@@ -9,73 +9,32 @@ info: To determine the technical writer assigned to the Stage/Group associated w
WARNING:
The Jira DVCS connector for Jira Cloud was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/362168) in GitLab 15.1
and is planned for removal in 16.0. Use the [GitLab for Jira Cloud app](../connect-app.md) instead.
-The Jira DVCS connector was also deprecated for Jira 8.13 and earlier. You can only use the Jira DVCS connector with Jira Server or Jira Data Center in Jira 8.14 and later. Upgrade your Jira instance to Jira 8.14 or later, and reconfigure the Jira integration in your GitLab instance.
+The Jira DVCS connector was also deprecated for Jira 8.13 and earlier. You can only use the Jira DVCS connector with Jira Data Center or Jira Server in Jira 8.14 and later. Upgrade your Jira instance to Jira 8.14 or later, and reconfigure the Jira integration in your GitLab instance.
Use the Jira DVCS (distributed version control system) connector if you self-host
-your Jira instance with Jira Server or Jira Data Center and want to sync information between GitLab and Jira.
-If you're on Jira Cloud, [migrate to the GitLab for Jira Cloud app](#migrate-to-the-gitlab-for-jira-cloud-app).
+your Jira instance with Jira Data Center or Jira Server and want to use the [Jira development panel](../development_panel.md).
-When you configure the Jira DVCS connector, make sure your GitLab and Jira instances
-are accessible.
+If you're on Jira Cloud, migrate to the GitLab for Jira Cloud app. For more information, see [Install the GitLab for Jira Cloud app](../connect-app.md#install-the-gitlab-for-jira-cloud-app).
-- **Self-managed GitLab**: Your GitLab instance must be accessible by Jira.
-- **Jira Server**: Your network must allow access to your instance.
+## Configure the Jira DVCS connector
-## Smart Commits
+### Prerequisites
-When connecting GitLab and Jira with the Jira DVCS connector, you can process your Jira issues with
-special commands called [Smart Commits](https://support.atlassian.com/jira-software-cloud/docs/process-issues-with-smart-commits/).
-With Smart Commits, you can:
+- Your GitLab instance must be accessible by Jira.
+- You must have at least the Maintainer role for the GitLab group.
+- Your network must allow inbound and outbound connections between GitLab and Jira.
-- Comment on issues.
-- Record time-tracking information against issues.
-- Transition issues to any status defined in the Jira project's workflow.
-
-Commands must be in the first line of the commit message. For more information about how Smart Commits work and what commands are available
-for use, see the [Atlassian documentation](https://support.atlassian.com/jira-software-cloud/docs/process-issues-with-smart-commits/).
-
-For Smart Commits to work, the GitLab user must have a corresponding
-Jira user with the same email address or username.
-
-### Smart Commit syntax
-
-Smart Commits must follow this pattern:
-
-```plaintext
-<ISSUE_KEY> <ignored text> #<command> <optional command parameters>
-```
-
-Some examples:
-
-- Add a comment to a Jira issue: `KEY-123 fixes a bug #comment Bug is fixed.`
-- Record time tracking: `KEY-123 #time 2w 4d 10h 52m Tracking work time.`
-- Close an issue: `KEY-123 #close Closing issue`
-
-A Smart Commit message must not span more than one line (no carriage returns), but
-you can still perform multiple actions in a single commit. For example:
-
-- Add time tracking, add a comment, and transition to **Closed**:
-
- ```plaintext
- KEY-123 #time 2d 5h #comment Task completed ahead of schedule #close
- ```
-
-- Add a comment, transition to **In-progress**, and add time tracking:
-
- ```plaintext
- KEY-123 #comment started working on the issue #in-progress #time 12d 5h
- ```
-
-## Configure a GitLab application for DVCS
+### Create a GitLab application for DVCS
For projects in a single group, you should create a [group application](../../oauth_provider.md#create-a-group-owned-application).
For projects across multiple groups, you should create a new user account in GitLab for Jira integration work only.
A separate account ensures regular account maintenance does not affect your integration.
-If a separate user account or group application is not possible, you can set up this integration
-as an [instance-wide application](../../oauth_provider.md#create-an-instance-wide-application)
-or with a [user-owned application](../../oauth_provider.md#create-a-user-owned-application).
+If it's not possible to create a separate user account or group application, you can set up this integration by creating:
+
+- [An instance-wide application](../../oauth_provider.md#create-an-instance-wide-application)
+- [A user-owned application](../../oauth_provider.md#create-a-user-owned-application)
1. Go to the [appropriate **Applications** section](../../oauth_provider.md).
1. In the **Name** text box, enter a descriptive name for the integration (for example, `Jira`).
@@ -87,34 +46,29 @@ or with a [user-owned application](../../oauth_provider.md#create-a-user-owned-a
1. Copy the **Application ID** and **Secret** values.
You need these values to configure Jira.
-## Configure Jira for DVCS
+### Configure Jira for DVCS
-To import all GitLab commits and branches into Jira for the groups you specify,
-configure Jira for DVCS. This import takes a few minutes and, after
-it completes, refreshes every 60 minutes:
-
-1. Complete the [GitLab configuration](#configure-a-gitlab-application-for-dvcs).
1. Go to your DVCS account:
- **For Jira Server**, select **Settings (gear) > Applications > DVCS accounts**.
1. To create a new integration, for **Host**, select **GitLab** or **GitLab Self-Managed**.
-1. For **Team or User Account**, enter the relative path of a top-level GitLab group that [the GitLab user](#configure-a-gitlab-application-for-dvcs) can access.
+1. For **Team or User Account**, enter the relative path of a top-level GitLab group that [the GitLab user](#create-a-gitlab-application-for-dvcs) can access.
1. In the **Host URL** text box, enter the appropriate URL.
Replace `<gitlab.example.com>` with your GitLab instance domain.
Use `https://<gitlab.example.com>`.
-1. For **Client ID**, use the [**Application ID** value](#configure-a-gitlab-application-for-dvcs).
-1. For **Client Secret**, use the [**Secret** value](#configure-a-gitlab-application-for-dvcs).
+1. For **Client ID**, use the [**Application ID** value](#create-a-gitlab-application-for-dvcs).
+1. For **Client Secret**, use the [**Secret** value](#create-a-gitlab-application-for-dvcs).
1. Ensure that all other checkboxes are selected.
1. To create the DVCS account, select **Add** and then **Continue**.
1. Jira redirects to GitLab where you have to confirm the authorization.
GitLab then redirects back to Jira where the synced
- projects should display in the new account.
+ projects should display in the new account. The initial sync takes a few minutes.
+
+After the initial sync, it can take up to 60 minutes to refresh.
To connect additional GitLab projects from other GitLab top-level groups or
personal namespaces, repeat the previous steps with additional Jira DVCS accounts.
-For more information about how to use the integration, see [Jira development panel](../development_panel.md).
-
## Refresh data imported to Jira
Jira imports the commits and branches every 60 minutes for your projects. You
@@ -126,22 +80,7 @@ can refresh the data manually from the Jira interface:
1. In the table, for the repository you want to refresh, in the **Last Activity**
column, select the icon.
-## Migrate to the GitLab for Jira Cloud app
-
-If you're using the Jira DVCS connector with Jira Cloud, migrate to the GitLab for Jira Cloud app.
-For more information, see [Install the GitLab for Jira Cloud app](../connect-app.md#install-the-gitlab-for-jira-cloud-app).
-
-### Feature comparison of DVCS and GitLab for Jira Cloud app
-
-| Feature | DVCS | GitLab for Jira Cloud app |
-|---------------------|------------------------|---------------------------|
-| Smart Commits | **{check-circle}** Yes | **{check-circle}** Yes |
-| Sync merge requests | **{check-circle}** Yes | **{check-circle}** Yes |
-| Sync branches | **{check-circle}** Yes | **{check-circle}** Yes |
-| Sync commits | **{check-circle}** Yes | **{check-circle}** Yes |
-| Sync existing data | **{check-circle}** Yes | **{check-circle}** Yes |
-| Sync builds | **{dotted-circle}** No | **{check-circle}** Yes |
-| Sync deployments | **{dotted-circle}** No | **{check-circle}** Yes |
-| Sync feature flags | **{dotted-circle}** No | **{check-circle}** Yes |
-| Sync interval | 60 minutes | Real time |
-| Create branches | **{dotted-circle}** No | **{check-circle}** Yes (GitLab SaaS only) |
+## Troubleshooting
+
+To troubleshoot the Jira development panel on your own server, see the
+[Atlassian documentation](https://confluence.atlassian.com/jirakb/troubleshoot-the-development-panel-in-jira-server-574685212.html).
diff --git a/doc/integration/jira/dvcs/troubleshooting.md b/doc/integration/jira/dvcs/troubleshooting.md
index 2be744ec8ff..541c743b609 100644
--- a/doc/integration/jira/dvcs/troubleshooting.md
+++ b/doc/integration/jira/dvcs/troubleshooting.md
@@ -80,7 +80,7 @@ Potential resolutions:
[Jira DVCS connector setup](index.md#configure-jira-for-dvcs) includes `scope=api` in
the query string.
1. If `scope=api` is missing from the URL, edit the
- [GitLab account configuration](index.md#configure-a-gitlab-application-for-dvcs). Review
+ [GitLab account configuration](index.md#create-a-gitlab-application-for-dvcs). Review
the **Scopes** field and ensure the `api` checkbox is selected.
## Jira error adding account and no repositories listed
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index fc3d4d1659c..affd72a8def 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -11962,6 +11962,9 @@ msgstr ""
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
+msgid "Containers"
+msgstr ""
+
msgid "Content"
msgstr ""
@@ -14580,6 +14583,9 @@ msgstr ""
msgid "DependencyProxy|Clear the Dependency Proxy cache automatically"
msgstr ""
+msgid "DependencyProxy|Configure in settings"
+msgstr ""
+
msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
@@ -28690,6 +28696,9 @@ msgstr ""
msgid "MlExperimentTracking|Logged candidates for experiment"
msgstr ""
+msgid "MlExperimentTracking|MLflow run ID"
+msgstr ""
+
msgid "MlExperimentTracking|Machine learning experiment tracking"
msgstr ""
@@ -38939,6 +38948,9 @@ msgstr ""
msgid "Runners|Select your preferred runner, then choose the capacity for the runner in the AWS CloudFormation console."
msgstr ""
+msgid "Runners|Shared runners are disabled in the group settings"
+msgstr ""
+
msgid "Runners|Show only inherited"
msgstr ""
@@ -41524,9 +41536,6 @@ msgstr ""
msgid "Shared runners are disabled for the parent group"
msgstr ""
-msgid "Shared runners are disabled on group level"
-msgstr ""
-
msgid "Shared runners details"
msgstr ""
diff --git a/package.json b/package.json
index 41a9d910fc3..ce36535fa56 100644
--- a/package.json
+++ b/package.json
@@ -50,8 +50,8 @@
"@apollo/client": "^3.5.10",
"@babel/core": "^7.18.5",
"@babel/preset-env": "^7.18.2",
- "@cubejs-client/core": "^0.32.22",
- "@cubejs-client/vue": "^0.32.22",
+ "@cubejs-client/core": "^0.32.30",
+ "@cubejs-client/vue": "^0.32.30",
"@gitlab/at.js": "1.5.7",
"@gitlab/cluster-client": "^1.2.0",
"@gitlab/favicon-overlay": "2.0.0",
diff --git a/scripts/review_apps/review-apps.sh b/scripts/review_apps/review-apps.sh
index 79571cb1e53..54924fb8a34 100755
--- a/scripts/review_apps/review-apps.sh
+++ b/scripts/review_apps/review-apps.sh
@@ -128,8 +128,22 @@ function disable_sign_ups() {
true
fi
- # Create the root token + Disable sign-ups
- local disable_signup_rb="token = User.find_by_username('root').personal_access_tokens.create(scopes: [:api], name: 'Token to disable sign-ups'); token.set_token('${REVIEW_APPS_ROOT_TOKEN}'); begin; token.save!; rescue(ActiveRecord::RecordNotUnique); end; Gitlab::CurrentSettings.current_application_settings.update!(signup_enabled: false)"
+# Create the root token + Disable sign-ups
+#
+# We use this weird syntax because we need to pass a one-liner ruby command to a Kubernetes container via kubectl.
+read -r -d '' multiline_ruby_code <<RUBY
+user = User.find_by_username('root');
+puts 'Error: Could not find root user. Check that the database was properly seeded'; exit(1) unless user;
+token = user.personal_access_tokens.create(scopes: [:api], name: 'Token to disable sign-ups');
+token.set_token('${REVIEW_APPS_ROOT_TOKEN}');
+begin;
+token.save!;
+rescue(ActiveRecord::RecordNotUnique);
+end;
+Gitlab::CurrentSettings.current_application_settings.update!(signup_enabled: false);
+RUBY
+
+ local disable_signup_rb=$(echo $multiline_ruby_code | tr '\n' ' ')
if (retry_exponential "run_task \"${disable_signup_rb}\""); then
echoinfo "Sign-ups have been disabled successfully."
else
diff --git a/spec/controllers/import/gitea_controller_spec.rb b/spec/controllers/import/gitea_controller_spec.rb
index 7466ffb2393..94b02f7c1b9 100644
--- a/spec/controllers/import/gitea_controller_spec.rb
+++ b/spec/controllers/import/gitea_controller_spec.rb
@@ -42,19 +42,23 @@ RSpec.describe Import::GiteaController, feature_category: :importers do
expect(response).to have_gitlab_http_status(:ok)
end
- context 'when host url is local or not http' do
- %w[https://localhost:3000 http://192.168.0.1 ftp://testing].each do |url|
- let(:host_url) { url }
+ shared_examples "unacceptable url" do |url, expected_error|
+ let(:host_url) { url }
- it 'denies network request' do
- get :status, format: :json
+ it 'denies network request' do
+ get :status, format: :json
- expect(controller).to redirect_to(new_import_url)
- expect(flash[:alert]).to eq('Specified URL cannot be used: "Only allowed schemes are http, https"')
- end
+ expect(controller).to redirect_to(new_import_url)
+ expect(flash[:alert]).to eq("Specified URL cannot be used: \"#{expected_error}\"")
end
end
+ context 'when host url is local or not http' do
+ include_examples 'unacceptable url', 'https://localhost:3000', 'Only allowed schemes are http, https'
+ include_examples 'unacceptable url', 'http://192.168.0.1', 'Only allowed schemes are http, https'
+ include_examples 'unacceptable url', 'ftp://testing', 'Only allowed schemes are http, https'
+ end
+
context 'when DNS Rebinding protection is enabled' do
let(:token) { 'gitea token' }
diff --git a/spec/features/groups/dependency_proxy_spec.rb b/spec/features/groups/dependency_proxy_spec.rb
index 05984d40ea6..60922f813df 100644
--- a/spec/features/groups/dependency_proxy_spec.rb
+++ b/spec/features/groups/dependency_proxy_spec.rb
@@ -52,6 +52,12 @@ RSpec.describe 'Group Dependency Proxy', feature_category: :dependency_proxy do
expect(find('input[data-testid="proxy-url"]').value).to have_content('/dependency_proxy/containers')
end
+ it 'has link to settings' do
+ visit path
+
+ expect(page).to have_link s_('DependencyProxy|Configure in settings')
+ end
+
it 'hides the proxy URL when feature is disabled' do
visit settings_path
wait_for_requests
@@ -80,6 +86,10 @@ RSpec.describe 'Group Dependency Proxy', feature_category: :dependency_proxy do
it 'does not show the feature toggle but shows the proxy URL' do
expect(find('input[data-testid="proxy-url"]').value).to have_content('/dependency_proxy/containers')
end
+
+ it 'does not have link to settings' do
+ expect(page).not_to have_link s_('DependencyProxy|Configure in settings')
+ end
end
end
diff --git a/spec/frontend/ml/experiment_tracking/routes/candidates/show/__snapshots__/ml_candidates_show_spec.js.snap b/spec/frontend/ml/experiment_tracking/routes/candidates/show/__snapshots__/ml_candidates_show_spec.js.snap
index 6fd3dce1941..e1ea3a351ec 100644
--- a/spec/frontend/ml/experiment_tracking/routes/candidates/show/__snapshots__/ml_candidates_show_spec.js.snap
+++ b/spec/frontend/ml/experiment_tracking/routes/candidates/show/__snapshots__/ml_candidates_show_spec.js.snap
@@ -62,6 +62,20 @@ exports[`MlCandidatesShow renders correctly 1`] = `
<td
class="gl-font-weight-bold"
>
+ MLflow run ID
+ </td>
+
+ <td>
+ abcdefg
+ </td>
+ </tr>
+
+ <tr>
+ <td />
+
+ <td
+ class="gl-font-weight-bold"
+ >
Status
</td>
diff --git a/spec/frontend/ml/experiment_tracking/routes/candidates/show/ml_candidates_show_spec.js b/spec/frontend/ml/experiment_tracking/routes/candidates/show/ml_candidates_show_spec.js
index 7d03ab3b509..b2a16b7ae78 100644
--- a/spec/frontend/ml/experiment_tracking/routes/candidates/show/ml_candidates_show_spec.js
+++ b/spec/frontend/ml/experiment_tracking/routes/candidates/show/ml_candidates_show_spec.js
@@ -22,6 +22,7 @@ describe('MlCandidatesShow', () => {
],
info: {
iid: 'candidate_iid',
+ eid: 'abcdefg',
path_to_artifact: 'path_to_artifact',
experiment_name: 'The Experiment',
experiment_path: 'path/to/experiment',
diff --git a/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js b/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js
index 0e383e551d0..1928dbf72b6 100644
--- a/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js
+++ b/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js
@@ -12,6 +12,7 @@ import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import MockAdapter from 'axios-mock-adapter';
import createMockApollo from 'helpers/mock_apollo_helper';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { GRAPHQL_PAGE_SIZE } from '~/packages_and_registries/dependency_proxy/constants';
@@ -45,6 +46,7 @@ describe('DependencyProxyApp', () => {
groupId: dummyGrouptId,
noManifestsIllustration: 'noManifestsIllustration',
canClearCache: true,
+ settingsPath: 'path',
};
function createComponent({ provide = provideDefaults } = {}) {
@@ -65,6 +67,9 @@ describe('DependencyProxyApp', () => {
GlSprintf,
TitleArea,
},
+ directives: {
+ GlTooltip: createMockDirective('gl-tooltip'),
+ },
});
}
@@ -77,6 +82,7 @@ describe('DependencyProxyApp', () => {
const findClearCacheDropdownList = () => wrapper.findComponent(GlDropdown);
const findClearCacheModal = () => wrapper.findComponent(GlModal);
const findClearCacheAlert = () => wrapper.findComponent(GlAlert);
+ const findSettingsLink = () => wrapper.findByTestId('settings-link');
beforeEach(() => {
resolver = jest.fn().mockResolvedValue(proxyDetailsQuery());
@@ -133,6 +139,29 @@ describe('DependencyProxyApp', () => {
expect(findProxyCountText().text()).toBe('Contains 2 blobs of images (1024 Bytes)');
});
+ describe('link to settings', () => {
+ it('is rendered', () => {
+ expect(findSettingsLink().exists()).toBe(true);
+ });
+
+ it('has the right icon', () => {
+ expect(findSettingsLink().props('icon')).toBe('settings');
+ });
+
+ it('has the right attributes', () => {
+ expect(findSettingsLink().attributes()).toMatchObject({
+ 'aria-label': DependencyProxyApp.i18n.settingsText,
+ href: 'path',
+ });
+ });
+
+ it('sets tooltip with right label', () => {
+ const tooltip = getBinding(findSettingsLink().element, 'gl-tooltip');
+
+ expect(tooltip.value).toBe(DependencyProxyApp.i18n.settingsText);
+ });
+ });
+
describe('manifest lists', () => {
describe('when there are no manifests', () => {
beforeEach(() => {
@@ -237,9 +266,7 @@ describe('DependencyProxyApp', () => {
beforeEach(() => {
createComponent({
provide: {
- groupPath: 'gitlab-org',
- groupId: dummyGrouptId,
- noManifestsIllustration: 'noManifestsIllustration',
+ ...provideDefaults,
canClearCache: false,
},
});
@@ -248,6 +275,10 @@ describe('DependencyProxyApp', () => {
it('does not show the clear cache dropdown list', () => {
expect(findClearCacheDropdownList().exists()).toBe(false);
});
+
+ it('does not show link to settings', () => {
+ expect(findSettingsLink().exists()).toBe(false);
+ });
});
});
});
diff --git a/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js b/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js
index 0ec0e981d65..f28bc13895e 100644
--- a/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js
+++ b/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js
@@ -1,7 +1,7 @@
-import { GlAlert, GlToggle, GlTooltip } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
+import { GlToggle } from '@gitlab/ui';
import MockAxiosAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import { HTTP_STATUS_OK, HTTP_STATUS_UNAUTHORIZED } from '~/lib/utils/http_status';
@@ -16,7 +16,7 @@ describe('projects/settings/components/shared_runners', () => {
let mockAxios;
const createComponent = (props = {}) => {
- wrapper = shallowMount(SharedRunnersToggleComponent, {
+ wrapper = shallowMountExtended(SharedRunnersToggleComponent, {
propsData: {
isEnabled: false,
isDisabledAndUnoverridable: false,
@@ -28,9 +28,9 @@ describe('projects/settings/components/shared_runners', () => {
});
};
- const findErrorAlert = () => wrapper.findComponent(GlAlert);
+ const findErrorAlert = () => wrapper.findByTestId('error-alert');
+ const findUnoverridableAlert = () => wrapper.findByTestId('unoverridable-alert');
const findSharedRunnersToggle = () => wrapper.findComponent(GlToggle);
- const findToggleTooltip = () => wrapper.findComponent(GlTooltip);
const getToggleValue = () => findSharedRunnersToggle().props('value');
const isToggleLoading = () => findSharedRunnersToggle().props('isLoading');
const isToggleDisabled = () => findSharedRunnersToggle().props('disabled');
@@ -55,8 +55,8 @@ describe('projects/settings/components/shared_runners', () => {
expect(isToggleDisabled()).toBe(true);
});
- it('tooltip should exist explaining why the toggle is disabled', () => {
- expect(findToggleTooltip().exists()).toBe(true);
+ it('alert should exist explaining why the toggle is disabled', () => {
+ expect(findUnoverridableAlert().exists()).toBe(true);
});
});
@@ -72,7 +72,7 @@ describe('projects/settings/components/shared_runners', () => {
it('loading icon, error message, and tooltip should not exist', () => {
expect(isToggleLoading()).toBe(false);
expect(findErrorAlert().exists()).toBe(false);
- expect(findToggleTooltip().exists()).toBe(false);
+ expect(findUnoverridableAlert().exists()).toBe(false);
});
describe('with shared runners DISABLED', () => {
diff --git a/spec/helpers/projects/ml/experiments_helper_spec.rb b/spec/helpers/projects/ml/experiments_helper_spec.rb
index 9b3c23e1f87..4296d6acdca 100644
--- a/spec/helpers/projects/ml/experiments_helper_spec.rb
+++ b/spec/helpers/projects/ml/experiments_helper_spec.rb
@@ -111,6 +111,7 @@ RSpec.describe Projects::Ml::ExperimentsHelper, feature_category: :mlops do
it 'generates the correct info' do
expected_info = {
'iid' => candidate.iid,
+ 'eid' => candidate.eid,
'path_to_artifact' => "/#{project.full_path}/-/packages/#{candidate.artifact.id}",
'experiment_name' => candidate.experiment.name,
'path_to_experiment' => "/#{project.full_path}/-/ml/experiments/#{experiment.iid}",
diff --git a/spec/migrations/ensure_merge_request_metrics_id_bigint_backfill_is_finished_for_self_hosts_spec.rb b/spec/migrations/ensure_merge_request_metrics_id_bigint_backfill_is_finished_for_self_hosts_spec.rb
deleted file mode 100644
index b946f816f3b..00000000000
--- a/spec/migrations/ensure_merge_request_metrics_id_bigint_backfill_is_finished_for_self_hosts_spec.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe EnsureMergeRequestMetricsIdBigintBackfillIsFinishedForSelfHosts, feature_category: :database do
- describe '#up' do
- let(:migration_arguments) do
- {
- job_class_name: 'CopyColumnUsingBackgroundMigrationJob',
- table_name: 'merge_request_metrics',
- column_name: 'id',
- job_arguments: [['id'], ['id_convert_to_bigint']]
- }
- end
-
- it 'ensures the migration is completed' do
- expect_next_instance_of(described_class) do |instance|
- expect(instance).to receive(:ensure_batched_background_migration_is_finished).with(migration_arguments)
- end
-
- migrate!
- end
- end
-end
diff --git a/spec/migrations/swap_merge_request_metrics_id_to_bigint_for_self_hosts_spec.rb b/spec/migrations/swap_merge_request_metrics_id_to_bigint_for_self_hosts_spec.rb
deleted file mode 100644
index 823c446d1e1..00000000000
--- a/spec/migrations/swap_merge_request_metrics_id_to_bigint_for_self_hosts_spec.rb
+++ /dev/null
@@ -1,150 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe SwapMergeRequestMetricsIdToBigintForSelfHosts, feature_category: :database do
- describe '#up' do
- context 'when is GitLab.com, dev, or test' do
- before do
- # As we call `schema_migrate_down!` before each example, and for this migration
- # `#down` is same as `#up`, we need to ensure we start from the expected state.
- connection = described_class.new.connection
- connection.execute('ALTER TABLE merge_request_metrics ALTER COLUMN id TYPE bigint')
- connection.execute('ALTER TABLE merge_request_metrics DROP COLUMN IF EXISTS id_convert_to_bigint')
- end
-
- it 'does not swap the columns' do
- # rubocop: disable RSpec/AnyInstanceOf
- allow_any_instance_of(described_class).to receive(:com_or_dev_or_test_but_not_jh?).and_return(true)
- # rubocop: enable RSpec/AnyInstanceOf
-
- merge_request_metrics = table(:merge_request_metrics)
-
- disable_migrations_output do
- reversible_migration do |migration|
- migration.before -> {
- merge_request_metrics.reset_column_information
-
- expect(merge_request_metrics.columns.find { |c| c.name == 'id' }.sql_type).to eq('bigint')
- expect(merge_request_metrics.columns.find { |c| c.name == 'id_convert_to_bigint' }).to be nil
- }
-
- migration.after -> {
- merge_request_metrics.reset_column_information
-
- expect(merge_request_metrics.columns.find { |c| c.name == 'id' }.sql_type).to eq('bigint')
- expect(merge_request_metrics.columns.find { |c| c.name == 'id_convert_to_bigint' }).to be nil
- }
- end
- end
- end
- end
-
- context 'when is a self-host customer with the swapped already completed' do
- before do
- # As we call `schema_migrate_down!` before each example, and for this migration
- # `#down` is same as `#up`, we need to ensure we start from the expected state.
- connection = described_class.new.connection
- connection.execute('ALTER TABLE merge_request_metrics ALTER COLUMN id TYPE bigint')
- connection.execute('ALTER TABLE merge_request_metrics ADD COLUMN IF NOT EXISTS id_convert_to_bigint integer')
- end
-
- it 'does not swap the columns' do
- # rubocop: disable RSpec/AnyInstanceOf
- allow_any_instance_of(described_class).to receive(:com_or_dev_or_test_but_not_jh?).and_return(false)
- # rubocop: enable RSpec/AnyInstanceOf
-
- merge_request_metrics = table(:merge_request_metrics)
-
- migrate!
-
- expect(merge_request_metrics.columns.find { |c| c.name == 'id' }.sql_type).to eq('bigint')
- expect(merge_request_metrics.columns.find do |c|
- c.name == 'id_convert_to_bigint'
- end.sql_type).to eq('integer')
- end
- end
-
- context 'when is a self-host customer with the `id_convert_to_bigint` column already dropped ' do
- before do
- # As we call `schema_migrate_down!` before each example, and for this migration
- # `#down` is same as `#up`, we need to ensure we start from the expected state.
- connection = described_class.new.connection
- connection.execute('ALTER TABLE merge_request_metrics ALTER COLUMN id TYPE bigint')
- connection.execute('ALTER TABLE merge_request_metrics DROP COLUMN IF EXISTS id_convert_to_bigint')
- end
-
- it 'does not swap the columns' do
- # rubocop: disable RSpec/AnyInstanceOf
- allow_any_instance_of(described_class).to receive(:com_or_dev_or_test_but_not_jh?).and_return(false)
- # rubocop: enable RSpec/AnyInstanceOf
-
- merge_request_metrics = table(:merge_request_metrics)
-
- disable_migrations_output do
- reversible_migration do |migration|
- migration.before -> {
- merge_request_metrics.reset_column_information
-
- expect(merge_request_metrics.columns.find { |c| c.name == 'id' }.sql_type).to eq('bigint')
- expect(merge_request_metrics.columns.find { |c| c.name == 'id_convert_to_bigint' }).to be nil
- }
-
- migration.after -> {
- merge_request_metrics.reset_column_information
-
- expect(merge_request_metrics.columns.find { |c| c.name == 'id' }.sql_type).to eq('bigint')
- expect(merge_request_metrics.columns.find { |c| c.name == 'id_convert_to_bigint' }).to be nil
- }
- end
- end
- end
- end
-
- context 'when is a self-host customer' do
- before do
- # As we call `schema_migrate_down!` before each example, and for this migration
- # `#down` is same as `#up`, we need to ensure we start from the expected state.
- connection = described_class.new.connection
- connection.execute('ALTER TABLE merge_request_metrics ALTER COLUMN id TYPE integer')
- connection.execute('ALTER TABLE merge_request_metrics ADD COLUMN IF NOT EXISTS id_convert_to_bigint bigint')
- connection.execute('ALTER TABLE merge_request_metrics ALTER COLUMN id_convert_to_bigint TYPE bigint')
- connection.execute('DROP INDEX IF EXISTS index_merge_request_metrics_on_id_convert_to_bigint')
- connection.execute('DROP INDEX IF EXISTS tmp_index_mr_metrics_on_target_project_id_merged_at_nulls_last')
- connection.execute('CREATE OR REPLACE FUNCTION trigger_c7107f30d69d() RETURNS trigger LANGUAGE plpgsql AS $$
- BEGIN NEW."id_convert_to_bigint" := NEW."id"; RETURN NEW; END; $$;')
- end
-
- it 'swaps the columns' do
- # rubocop: disable RSpec/AnyInstanceOf
- allow_any_instance_of(described_class).to receive(:com_or_dev_or_test_but_not_jh?).and_return(false)
- # rubocop: enable RSpec/AnyInstanceOf
-
- merge_request_metrics = table(:merge_request_metrics)
-
- disable_migrations_output do
- reversible_migration do |migration|
- migration.before -> {
- merge_request_metrics.reset_column_information
-
- expect(merge_request_metrics.columns.find { |c| c.name == 'id' }.sql_type).to eq('integer')
- expect(merge_request_metrics.columns.find do |c|
- c.name == 'id_convert_to_bigint'
- end.sql_type).to eq('bigint')
- }
-
- migration.after -> {
- merge_request_metrics.reset_column_information
-
- expect(merge_request_metrics.columns.find { |c| c.name == 'id' }.sql_type).to eq('bigint')
- expect(merge_request_metrics.columns.find do |c|
- c.name == 'id_convert_to_bigint'
- end.sql_type).to eq('integer')
- }
- end
- end
- end
- end
- end
-end
diff --git a/spec/models/namespace/aggregation_schedule_spec.rb b/spec/models/namespace/aggregation_schedule_spec.rb
index 3b48775d71e..0289e4a5462 100644
--- a/spec/models/namespace/aggregation_schedule_spec.rb
+++ b/spec/models/namespace/aggregation_schedule_spec.rb
@@ -5,27 +5,33 @@ require 'spec_helper'
RSpec.describe Namespace::AggregationSchedule, :clean_gitlab_redis_shared_state, type: :model do
include ExclusiveLeaseHelpers
- let(:default_timeout) { described_class.default_lease_timeout }
+ let(:namespace) { create(:namespace) }
+ let(:aggregation_schedule) { namespace.build_aggregation_schedule }
+ let(:default_timeout) { aggregation_schedule.default_lease_timeout }
it { is_expected.to belong_to :namespace }
describe "#default_lease_timeout" do
- subject(:default_lease_timeout) { default_timeout }
+ before do
+ aggregation_schedule.save!
+ end
- it { is_expected.to eq 2.minutes.to_i }
+ context 'when reduce_aggregation_schedule_lease FF is enabled' do
+ it 'is 2 minutes' do
+ stub_feature_flags(reduce_aggregation_schedule_lease: true)
+ expect(aggregation_schedule.default_lease_timeout).to eq 2.minutes.to_i
+ end
+ end
context 'when reduce_aggregation_schedule_lease FF is disabled' do
- before do
+ it 'is 30 minutes' do
stub_feature_flags(reduce_aggregation_schedule_lease: false)
+ expect(aggregation_schedule.default_lease_timeout).to eq 30.minutes.to_i
end
-
- it { is_expected.to eq 30.minutes.to_i }
end
end
describe '#schedule_root_storage_statistics' do
- let(:namespace) { create(:namespace) }
- let(:aggregation_schedule) { namespace.build_aggregation_schedule }
let(:lease_key) { "namespace:namespaces_root_statistics:#{namespace.id}" }
context "when we can't obtain the lease" do
diff --git a/spec/workers/namespaces/prune_aggregation_schedules_worker_spec.rb b/spec/workers/namespaces/prune_aggregation_schedules_worker_spec.rb
index 02856e16552..9f0ea366726 100644
--- a/spec/workers/namespaces/prune_aggregation_schedules_worker_spec.rb
+++ b/spec/workers/namespaces/prune_aggregation_schedules_worker_spec.rb
@@ -6,7 +6,6 @@ RSpec.describe Namespaces::PruneAggregationSchedulesWorker, '#perform', :clean_g
include ExclusiveLeaseHelpers
let(:namespaces) { create_list(:namespace, 5, :with_aggregation_schedule) }
- let(:timeout) { Namespace::AggregationSchedule.default_lease_timeout }
subject(:worker) { described_class.new }
@@ -19,7 +18,7 @@ RSpec.describe Namespaces::PruneAggregationSchedulesWorker, '#perform', :clean_g
namespaces.each do |namespace|
lease_key = "namespace:namespaces_root_statistics:#{namespace.id}"
- stub_exclusive_lease(lease_key, timeout: timeout)
+ stub_exclusive_lease(lease_key, timeout: namespace.aggregation_schedule.default_lease_timeout)
end
end
diff --git a/spec/workers/project_cache_worker_spec.rb b/spec/workers/project_cache_worker_spec.rb
index 508dacea2fb..4d468897599 100644
--- a/spec/workers/project_cache_worker_spec.rb
+++ b/spec/workers/project_cache_worker_spec.rb
@@ -13,10 +13,6 @@ RSpec.describe ProjectCacheWorker, feature_category: :source_code_management do
let(:statistics) { [] }
describe '#perform' do
- before do
- stub_exclusive_lease(lease_key, timeout: lease_timeout)
- end
-
context 'with a non-existing project' do
it 'does nothing' do
expect(worker).not_to receive(:update_statistics)
@@ -37,11 +33,6 @@ RSpec.describe ProjectCacheWorker, feature_category: :source_code_management do
end
context 'with an existing project' do
- before do
- lease_key = "namespace:namespaces_root_statistics:#{project.namespace_id}"
- stub_exclusive_lease_taken(lease_key, timeout: Namespace::AggregationSchedule.default_lease_timeout)
- end
-
it 'refreshes the method caches' do
expect_any_instance_of(Repository).to receive(:refresh_method_caches)
.with(%i(readme))
diff --git a/yarn.lock b/yarn.lock
index 07c81067f04..9c365d7449d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1005,10 +1005,10 @@
resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.0.1.tgz#b6b8d81780b9a9f6459f4bfe9226ac6aefaefe87"
integrity sha512-aG20vknL4/YjQF9BSV7ts4EWm/yrjagAN7OWBNmlbEOUiu0llj4OGrFoOKK3g2vey4/p2omKCoHrWtPxSwV3HA==
-"@cubejs-client/core@^0.32.22":
- version "0.32.22"
- resolved "https://registry.yarnpkg.com/@cubejs-client/core/-/core-0.32.22.tgz#fe3bc9382e7858cb1b9c7dd726e3327acc3e9508"
- integrity sha512-JYA8lgr0Pjus/Y+GA5gbP6iY/X2+7wO+DXg4fjAWJjn2MEU8X478OU+uLENzgIqLyZRSjvEZoI6Vt8BicJboEQ==
+"@cubejs-client/core@^0.32.30":
+ version "0.32.30"
+ resolved "https://registry.yarnpkg.com/@cubejs-client/core/-/core-0.32.30.tgz#40bad1199635363a82a1a5e9f4718a67f2fe4f59"
+ integrity sha512-Lb5qBHIrpp9LpqFVgaOpVInVNZd77Cj452jbGl0hiZVDw+0CErzkqTOrjZ1lBRdKiYqHdYoHU2ZVzg95vNKnPw==
dependencies:
"@babel/runtime" "^7.1.2"
core-js "^3.6.5"
@@ -1018,12 +1018,12 @@
url-search-params-polyfill "^7.0.0"
uuid "^8.3.2"
-"@cubejs-client/vue@^0.32.22":
- version "0.32.22"
- resolved "https://registry.yarnpkg.com/@cubejs-client/vue/-/vue-0.32.22.tgz#2a16a0e2b9f1c084fc11d1416f2cd52ed30fdbbb"
- integrity sha512-FuApIKcLmM1JaR4wOjLDPONsJE8PeRw6QAo+nBOZJNFBjXPmDhd7EH73xvlT3PY0hhBwD1ts6sUWuvjV2uPQGA==
+"@cubejs-client/vue@^0.32.30":
+ version "0.32.30"
+ resolved "https://registry.yarnpkg.com/@cubejs-client/vue/-/vue-0.32.30.tgz#a192350a8eed901bff4f6311abf7016dcb66d0b4"
+ integrity sha512-AaJR3ZP25/NMKXpSlJaOa7FY4VK5UO7BNyV3sp5wKNhNmyDU+gC8diPVISDp5b7usL8EF4ZKxHHDNEbKrsaKUA==
dependencies:
- "@cubejs-client/core" "^0.32.22"
+ "@cubejs-client/core" "^0.32.30"
core-js "^3.6.5"
ramda "^0.27.2"