Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
82d72ee0ea
commit
e7bfce6d9f
|
|
@ -280,7 +280,6 @@ export default {
|
|||
'app/assets/javascripts/work_items/components/work_item_links/work_item_rolled_up_count.vue',
|
||||
'app/assets/javascripts/work_items/components/work_item_links/work_item_rolled_up_data.vue',
|
||||
'app/assets/javascripts/work_items/components/work_item_links/work_item_tree.vue',
|
||||
'app/assets/javascripts/work_items/components/work_item_sticky_header.vue',
|
||||
'ee/app/assets/javascripts/admin/subscriptions/show/components/subscription_breakdown.vue',
|
||||
'ee/app/assets/javascripts/ai/components/duo_chat_feedback_modal.vue',
|
||||
'ee/app/assets/javascripts/ai/components/user_feedback.vue',
|
||||
|
|
@ -444,11 +443,6 @@ export default {
|
|||
'ee/app/assets/javascripts/vulnerabilities/components/new_vulnerability/section_details.vue',
|
||||
'ee/app/assets/javascripts/vulnerabilities/components/vulnerability_details.vue',
|
||||
'ee/app/assets/javascripts/vulnerabilities/components/vulnerability_training.vue',
|
||||
'ee/app/assets/javascripts/work_items/components/work_item_custom_fields_multi_select.vue',
|
||||
'ee/app/assets/javascripts/work_items/components/work_item_custom_fields_single_select.vue',
|
||||
'ee/app/assets/javascripts/work_items/components/work_item_health_status.vue',
|
||||
'ee/app/assets/javascripts/work_items/components/work_item_iteration.vue',
|
||||
'ee/app/assets/javascripts/work_items/components/work_item_links/work_item_rolled_up_health_status.vue',
|
||||
],
|
||||
rules: {
|
||||
'vue/no-unused-properties': 'off',
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ db:check-schema-single-db:
|
|||
db:check-migrations:
|
||||
extends:
|
||||
- .db-job-base
|
||||
- .use-pg14 # Should match the db same version used by GDK
|
||||
- .use-pg16 # Should match the db same version used by GDK
|
||||
- .rails:rules:ee-and-foss-mr-with-migration
|
||||
script:
|
||||
- |
|
||||
|
|
|
|||
|
|
@ -23,4 +23,4 @@
|
|||
<!-- Make sure to add one of the type labels (as per https://handbook.gitlab.com/handbook/product/groups/product-analysis/engineering/metrics/#work-type-classification):-->
|
||||
<!-- /label ~"type::bug" ~"type::feature" ~"type::tooling" ~"type::maintenance" -->
|
||||
|
||||
/label ~devops::analytics ~"group::analytics instrumentation"
|
||||
/label ~"group::analytics instrumentation"
|
||||
|
|
|
|||
|
|
@ -96,7 +96,6 @@ Gitlab/FeatureFlagWithoutActor:
|
|||
- 'ee/app/views/projects/on_demand_scans/index.html.haml'
|
||||
- 'ee/app/views/projects/settings/merge_requests/_merge_trains_settings.html.haml'
|
||||
- 'ee/lib/api/code_suggestions.rb'
|
||||
- 'ee/lib/api/internal/search/zoekt.rb'
|
||||
- 'ee/lib/api/internal/suggested_reviewers.rb'
|
||||
- 'ee/lib/ee/api/entities/application_setting.rb'
|
||||
- 'ee/lib/ee/api/geo.rb'
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
2fb6e0b3a55ae7554b353ea70a54a97b7fe6512f
|
||||
184f295d9e55a273ce85a2c3c32da526f32a8f6b
|
||||
|
|
|
|||
|
|
@ -26,15 +26,7 @@ export default () => {
|
|||
|
||||
const isGroupPage = pageType === 'groups';
|
||||
|
||||
// This is a mini state to help the breadcrumb have the correct name in the details page
|
||||
const breadCrumbState = Vue.observable({
|
||||
name: '',
|
||||
updateName(value) {
|
||||
this.name = value;
|
||||
},
|
||||
});
|
||||
|
||||
const router = createRouter(endpoint, breadCrumbState);
|
||||
const router = createRouter(endpoint);
|
||||
|
||||
const attachMainComponent = () =>
|
||||
new Vue({
|
||||
|
|
@ -50,7 +42,6 @@ export default () => {
|
|||
npmGroupUrl,
|
||||
projectListUrl,
|
||||
groupListUrl,
|
||||
breadCrumbState,
|
||||
settingsPath,
|
||||
canDeletePackages: parseBoolean(canDeletePackages),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ export default {
|
|||
GlModal: GlModalDirective,
|
||||
},
|
||||
mixins: [Tracking.mixin()],
|
||||
inject: ['emptyListIllustration', 'projectListUrl', 'groupListUrl', 'breadCrumbState'],
|
||||
inject: ['emptyListIllustration', 'projectListUrl', 'groupListUrl'],
|
||||
trackingActions: {
|
||||
DELETE_PACKAGE_TRACKING_ACTION,
|
||||
REQUEST_DELETE_PACKAGE_TRACKING_ACTION,
|
||||
|
|
@ -117,11 +117,6 @@ export default {
|
|||
error,
|
||||
});
|
||||
},
|
||||
result() {
|
||||
this.breadCrumbState.updateName(
|
||||
`${this.packageEntity?.name} v${this.packageEntity?.version}`,
|
||||
);
|
||||
},
|
||||
},
|
||||
groupSettings: {
|
||||
query: getGroupPackageSettings,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { PACKAGE_REGISTRY_TITLE } from '~/packages_and_registries/package_regist
|
|||
|
||||
Vue.use(VueRouter);
|
||||
|
||||
export default function createRouter(base, breadCrumbState) {
|
||||
export default function createRouter(base) {
|
||||
const router = new VueRouter({
|
||||
base,
|
||||
mode: 'history',
|
||||
|
|
@ -24,16 +24,9 @@ export default function createRouter(base, breadCrumbState) {
|
|||
name: 'details',
|
||||
path: '/:id',
|
||||
component: Details,
|
||||
meta: {
|
||||
nameGenerator: () => breadCrumbState.name,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
router.afterEach(() => {
|
||||
breadCrumbState.updateName('');
|
||||
});
|
||||
|
||||
return router;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export default {
|
|||
return this.$route.name === this.rootRoute.name;
|
||||
},
|
||||
detailsRouteName() {
|
||||
return this.detailsRoute.meta.nameGenerator();
|
||||
return `${this.$route.params?.id}`;
|
||||
},
|
||||
isLoaded() {
|
||||
return this.isRootRoute || this.detailsRouteName;
|
||||
|
|
@ -35,7 +35,7 @@ export default {
|
|||
if (!this.isRootRoute) {
|
||||
crumbs.push({
|
||||
text: this.detailsRouteName,
|
||||
href: this.detailsRoute.meta.path,
|
||||
href: this.detailsRoute.path,
|
||||
});
|
||||
}
|
||||
return crumbs;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui';
|
||||
import { GlButton, GlTooltipDirective, GlIcon, GlAnimatedLoaderIcon } from '@gitlab/ui';
|
||||
import { TYPE_ISSUE } from '~/issues/constants';
|
||||
import { __, sprintf, s__ } from '~/locale';
|
||||
import ReviewerAvatarLink from './reviewer_avatar_link.vue';
|
||||
|
|
@ -44,6 +44,7 @@ export default {
|
|||
components: {
|
||||
GlButton,
|
||||
GlIcon,
|
||||
GlAnimatedLoaderIcon,
|
||||
ReviewerAvatarLink,
|
||||
},
|
||||
directives: {
|
||||
|
|
@ -216,7 +217,15 @@ export default {
|
|||
:class="reviewStateIcon(user).class"
|
||||
data-testid="reviewer-state-icon-parent"
|
||||
>
|
||||
<gl-animated-loader-icon
|
||||
v-if="
|
||||
user.type === 'DUO_CODE_REVIEW_BOT' &&
|
||||
user.mergeRequestInteraction.reviewState === 'REVIEW_STARTED'
|
||||
"
|
||||
is-on
|
||||
/>
|
||||
<gl-icon
|
||||
v-else
|
||||
:size="reviewStateIcon(user).size || 16"
|
||||
:name="reviewStateIcon(user).name"
|
||||
:class="reviewStateIcon(user).iconClass"
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ query mergeRequestReviewers($fullPath: ID!, $iid: String!) {
|
|||
nodes {
|
||||
...User
|
||||
...UserAvailability
|
||||
type
|
||||
mergeRequestInteraction {
|
||||
canMerge
|
||||
canUpdate
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@ export const SEARCH_SCOPE = {
|
|||
export const GLOBAL_COMMANDS_GROUP_TITLE = s__('CommandPalette|Global Commands');
|
||||
export const USERS_GROUP_TITLE = s__('GlobalSearch|Users');
|
||||
export const PAGES_GROUP_TITLE = s__('CommandPalette|Pages');
|
||||
export const PROJECTS_GROUP_TITLE = s__('GlobalSearch|Projects');
|
||||
export const GROUPS_GROUP_TITLE = s__('GlobalSearch|Groups');
|
||||
export const PROJECTS_GROUP_TITLE = s__("GlobalSearch|Projects I'm a member of");
|
||||
export const GROUPS_GROUP_TITLE = s__("GlobalSearch|Groups I'm a member of");
|
||||
export const ISSUES_GROUP_TITLE = s__('GlobalSearch|Issues');
|
||||
export const PATH_GROUP_TITLE = s__('CommandPalette|Project files');
|
||||
export const SETTINGS_GROUP_TITLE = s__('CommandPalette|Settings');
|
||||
|
|
@ -75,3 +75,6 @@ export const OVERLAY_GOTO = s__('GlobalSearch|Go to %{kbdStart}↵%{kbdEnd}');
|
|||
|
||||
export const FREQUENTLY_VISITED_PROJECTS_HANDLE = 'FREQUENTLY_VISITED_PROJECTS_HANDLE';
|
||||
export const FREQUENTLY_VISITED_GROUPS_HANDLE = 'FREQUENTLY_VISITED_GROUPS_HANDLE';
|
||||
|
||||
export const GROUPS_GROUP_HANDLE = 'Groups';
|
||||
export const PROJECTS_GROUP_HANDLE = 'Projects';
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ import {
|
|||
ISSUES_GROUP_TITLE,
|
||||
PAGES_GROUP_TITLE,
|
||||
GROUPS_GROUP_TITLE,
|
||||
GROUPS_GROUP_HANDLE,
|
||||
PROJECTS_GROUP_HANDLE,
|
||||
} from '../command_palette/constants';
|
||||
import SearchResultFocusLayover from './global_search_focus_overlay.vue';
|
||||
import GlobalSearchNoResults from './global_search_no_results.vue';
|
||||
|
|
@ -81,7 +83,7 @@ export default {
|
|||
groups() {
|
||||
return this.autocompleteGroupedSearchOptions.map((group) => {
|
||||
return {
|
||||
name: group?.name,
|
||||
name: this.modifiedGroupName(group?.name),
|
||||
items: group?.items?.map((item) => {
|
||||
return {
|
||||
...item,
|
||||
|
|
@ -160,6 +162,17 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
modifiedGroupName(groupName) {
|
||||
if (groupName === GROUPS_GROUP_HANDLE) {
|
||||
return this.$options.i18n.GROUPS_GROUP_TITLE;
|
||||
}
|
||||
|
||||
if (groupName === PROJECTS_GROUP_HANDLE) {
|
||||
return this.$options.i18n.PROJECTS_GROUP_TITLE;
|
||||
}
|
||||
|
||||
return groupName;
|
||||
},
|
||||
},
|
||||
AVATAR_SHAPE_OPTION_RECT,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -162,9 +162,7 @@ export default {
|
|||
<template #description>
|
||||
<gl-sprintf
|
||||
:message="
|
||||
s__(
|
||||
'CICD|Authentication events from the last 30 days. %{linkStart}Learn more.%{linkEnd}',
|
||||
)
|
||||
s__('CICD|Authentication events using the job token. %{linkStart}Learn more.%{linkEnd}')
|
||||
"
|
||||
>
|
||||
<template #link="{ content }">
|
||||
|
|
@ -214,7 +212,7 @@ export default {
|
|||
class="gl-text-center"
|
||||
data-testid="auth-logs-no-events"
|
||||
>
|
||||
{{ s__('CICD|No authentication events in the last 30 days.') }}
|
||||
{{ s__('CICD|No authentication events to display.') }}
|
||||
</div>
|
||||
</crud-component>
|
||||
<gl-keyset-pagination
|
||||
|
|
|
|||
|
|
@ -1051,7 +1051,6 @@ export default {
|
|||
:work-item-type="selectedWorkItemTypeName"
|
||||
:custom-fields="workItemCustomFields"
|
||||
:full-path="selectedProjectFullPath"
|
||||
:is-group="isGroup"
|
||||
:can-update="canUpdate"
|
||||
@error="$emit('error', $event)"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -330,7 +330,6 @@ export default {
|
|||
:custom-fields="customFields"
|
||||
:full-path="fullPath"
|
||||
:can-update="canUpdateMetadata"
|
||||
:is-group="isGroup"
|
||||
@error="$emit('error', $event)"
|
||||
/>
|
||||
<work-item-parent
|
||||
|
|
|
|||
|
|
@ -896,21 +896,10 @@ export default {
|
|||
v-if="showIntersectionObserver"
|
||||
:current-user-todos="currentUserTodos"
|
||||
:show-work-item-current-user-todos="showWorkItemCurrentUserTodos"
|
||||
:parent-work-item-confidentiality="parentWorkItemConfidentiality"
|
||||
:update-in-progress="updateInProgress"
|
||||
:full-path="workItemFullPath"
|
||||
:is-modal="isModal"
|
||||
:work-item="workItem"
|
||||
:is-sticky-header-showing="isStickyHeaderShowing"
|
||||
:work-item-notifications-subscribed="workItemNotificationsSubscribed"
|
||||
:work-item-author-id="workItemAuthorId"
|
||||
:is-group="isGroupWorkItem"
|
||||
:allowed-child-types="allowedChildTypes"
|
||||
:parent-id="parentWorkItemId"
|
||||
:namespace-full-name="namespaceFullName"
|
||||
:has-children="hasChildren"
|
||||
:show-sidebar="showSidebar"
|
||||
:truncation-enabled="truncationEnabled"
|
||||
@hideStickyHeader="hideStickyHeader"
|
||||
@showStickyHeader="showStickyHeader"
|
||||
@deleteWorkItem="$emit('deleteWorkItem', { workItemType, workItemId: workItem.id })"
|
||||
|
|
|
|||
|
|
@ -27,10 +27,6 @@ export default {
|
|||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
fullPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
isStickyHeaderShowing: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
|
|
@ -44,63 +40,16 @@ export default {
|
|||
required: false,
|
||||
default: false,
|
||||
},
|
||||
parentWorkItemConfidentiality: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
parentId: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
showWorkItemCurrentUserTodos: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
isModal: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
currentUserTodos: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => [],
|
||||
},
|
||||
workItemAuthorId: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0,
|
||||
},
|
||||
isGroup: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
allowedChildTypes: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => [],
|
||||
},
|
||||
namespaceFullName: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
hasChildren: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
showSidebar: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
truncationEnabled: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
canUpdate() {
|
||||
|
|
|
|||
|
|
@ -233,7 +233,13 @@ class Issue < ApplicationRecord
|
|||
scope :confidential_only, -> { where(confidential: true) }
|
||||
|
||||
scope :without_hidden, -> {
|
||||
where('NOT EXISTS (?)', Users::BannedUser.select(1).where('issues.author_id = banned_users.user_id'))
|
||||
if Feature.enabled?(:optimize_issues_banned_users_query, :instance)
|
||||
# We add `+ 0` to the author_id to make the query planner use a nested loop and prevent
|
||||
# loading of all banned user IDs for certain queries
|
||||
where_not_exists(Users::BannedUser.where('banned_users.user_id = (issues.author_id + 0)'))
|
||||
else
|
||||
where_not_exists(Users::BannedUser.where('banned_users.user_id = issues.author_id'))
|
||||
end
|
||||
}
|
||||
|
||||
scope :counts_by_state, -> { reorder(nil).group(:state_id).count }
|
||||
|
|
|
|||
|
|
@ -473,7 +473,6 @@ class User < ApplicationRecord
|
|||
delegate :webauthn_xid, :webauthn_xid=, to: :user_detail, allow_nil: true
|
||||
delegate :pronouns, :pronouns=, to: :user_detail, allow_nil: true
|
||||
delegate :pronunciation, :pronunciation=, to: :user_detail, allow_nil: true
|
||||
delegate :registration_objective, :registration_objective=, to: :user_detail, allow_nil: true
|
||||
delegate :bluesky, :bluesky=, to: :user_detail, allow_nil: true
|
||||
delegate :mastodon, :mastodon=, to: :user_detail, allow_nil: true
|
||||
delegate :linkedin, :linkedin=, to: :user_detail, allow_nil: true
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@
|
|||
class UserDetail < ApplicationRecord
|
||||
extend ::Gitlab::Utils::Override
|
||||
|
||||
REGISTRATION_OBJECTIVE_PAIRS = { basics: 0, move_repository: 1, code_storage: 2, exploring: 3, ci: 4, other: 5, joining_team: 6 }.freeze
|
||||
|
||||
belongs_to :user
|
||||
belongs_to :bot_namespace, class_name: 'Namespace', optional: true, inverse_of: :bot_user_details
|
||||
|
||||
|
|
@ -15,6 +13,8 @@ class UserDetail < ApplicationRecord
|
|||
|
||||
validate :bot_namespace_user_type, if: :bot_namespace_id_changed?
|
||||
|
||||
ignore_column :registration_objective, remove_after: '2025-07-17', remove_with: '18.2'
|
||||
|
||||
DEFAULT_FIELD_LENGTH = 500
|
||||
|
||||
# specification for bluesky identifier https://web.plc.directory/spec/v0.1/did-plc
|
||||
|
|
@ -56,8 +56,6 @@ class UserDetail < ApplicationRecord
|
|||
before_validation :sanitize_attrs
|
||||
before_save :prevent_nil_fields
|
||||
|
||||
enum :registration_objective, REGISTRATION_OBJECTIVE_PAIRS, suffix: true
|
||||
|
||||
def sanitize_attrs
|
||||
%i[bluesky discord linkedin mastodon skype twitter website_url].each do |attr|
|
||||
value = self[attr]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
name: optimize_issues_banned_users_query
|
||||
description: Optimize banned user clause for issue list queries
|
||||
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/394980
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/189141
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/537923
|
||||
milestone: '18.0'
|
||||
group: group::project management
|
||||
type: gitlab_com_derisk
|
||||
default_enabled: false
|
||||
|
|
@ -35,6 +35,10 @@ approval_merge_request_rules:
|
|||
- table: approval_policy_rules
|
||||
column: approval_policy_rule_id
|
||||
on_delete: async_nullify
|
||||
ci_build_needs:
|
||||
- table: projects
|
||||
column: project_id
|
||||
on_delete: async_delete
|
||||
ci_build_report_results:
|
||||
- table: projects
|
||||
column: project_id
|
||||
|
|
|
|||
|
|
@ -8,15 +8,6 @@ description: Dependencies for a specific CI/CD job.
|
|||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31328
|
||||
milestone: '12.2'
|
||||
gitlab_schema: gitlab_ci
|
||||
desired_sharding_key:
|
||||
project_id:
|
||||
references: projects
|
||||
backfill_via:
|
||||
parent:
|
||||
foreign_key: build_id
|
||||
table: p_ci_builds
|
||||
sharding_key: project_id
|
||||
belongs_to: build
|
||||
foreign_key_name: fk_rails_3cf221d4ed_p
|
||||
desired_sharding_key_migration_job_name: BackfillCiBuildNeedsProjectId
|
||||
sharding_key:
|
||||
project_id: projects
|
||||
table_size: over_limit
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddAuthorEmailToSshSignatures < Gitlab::Database::Migration[2.2]
|
||||
disable_ddl_transaction!
|
||||
milestone '18.0'
|
||||
|
||||
# rubocop:disable Migration/AddLimitToTextColumns -- limit is added in a separate migration 20250425111203
|
||||
def up
|
||||
add_column :ssh_signatures, :author_email, :text
|
||||
end
|
||||
# rubocop:enable Migration/AddLimitToTextColumns
|
||||
|
||||
def down
|
||||
remove_column :ssh_signatures, :author_email if column_exists?(:ssh_signatures, :author_email)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddAuthorEmailLimitToSshSignatures < Gitlab::Database::Migration[2.2]
|
||||
disable_ddl_transaction!
|
||||
milestone '18.0'
|
||||
|
||||
def up
|
||||
add_text_limit :ssh_signatures, :author_email, 255
|
||||
end
|
||||
|
||||
def down
|
||||
remove_text_limit :ssh_signatures, :author_email
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ValidateCiBuildNeedsProjectIdNotNull < Gitlab::Database::Migration[2.2]
|
||||
milestone '18.0'
|
||||
|
||||
def up
|
||||
validate_not_null_constraint :ci_build_needs, :project_id, constraint_name: 'check_4fab85ecdc'
|
||||
end
|
||||
|
||||
def down
|
||||
# no-op
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
49bb1fbe7f7055a16c167199fe7c5c1dd62e0c46e68f50dff05f2470b22241f6
|
||||
|
|
@ -0,0 +1 @@
|
|||
a07dd290fe3abc6c4e74f41ec0a83218b4ef8cc8c83a99e0da820fce11c7c732
|
||||
|
|
@ -0,0 +1 @@
|
|||
3672a1886f77ed6e9072ef2e4bb2f1b00f87e1b9f7c7289bc930db1f0f4e376d
|
||||
|
|
@ -10912,7 +10912,8 @@ CREATE TABLE ci_build_needs (
|
|||
build_id bigint NOT NULL,
|
||||
partition_id bigint NOT NULL,
|
||||
id bigint NOT NULL,
|
||||
project_id bigint
|
||||
project_id bigint,
|
||||
CONSTRAINT check_4fab85ecdc CHECK ((project_id IS NOT NULL))
|
||||
);
|
||||
|
||||
CREATE SEQUENCE ci_build_needs_id_seq
|
||||
|
|
@ -23245,7 +23246,9 @@ CREATE TABLE ssh_signatures (
|
|||
verification_status smallint DEFAULT 0 NOT NULL,
|
||||
commit_sha bytea NOT NULL,
|
||||
user_id bigint,
|
||||
key_fingerprint_sha256 bytea
|
||||
key_fingerprint_sha256 bytea,
|
||||
author_email text,
|
||||
CONSTRAINT check_5ff707c7f9 CHECK ((char_length(author_email) <= 255))
|
||||
);
|
||||
|
||||
CREATE SEQUENCE ssh_signatures_id_seq
|
||||
|
|
@ -29140,9 +29143,6 @@ ALTER TABLE security_scans
|
|||
ALTER TABLE vulnerability_scanners
|
||||
ADD CONSTRAINT check_37608c9db5 CHECK ((char_length(vendor) <= 255)) NOT VALID;
|
||||
|
||||
ALTER TABLE ci_build_needs
|
||||
ADD CONSTRAINT check_4fab85ecdc CHECK ((project_id IS NOT NULL)) NOT VALID;
|
||||
|
||||
ALTER TABLE ONLY instance_type_ci_runners
|
||||
ADD CONSTRAINT check_5c34a3c1db UNIQUE (id);
|
||||
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ After you sign in to Switchboard, follow these steps to create your instance:
|
|||
|
||||
- **Reference architecture**: The maximum number of users allowed in your instance. For more information, see [availability and scalability](../../../subscriptions/gitlab_dedicated/data_residency_and_high_availability.md#availability-and-scalability). For example, up to 3,000 users.
|
||||
|
||||
- **Total repository capacity**: The total storage space available for all repositories in your instance. For example, 16 GB. This setting cannot be reduced after you create your instance. You can increase storage capacity later if needed.
|
||||
- **Total repository capacity**: The total storage space available for all repositories in your instance. For example, 16 GB. This setting cannot be reduced after you create your instance. You can increase storage capacity later if needed. For more information about how storage is calculated for GitLab Dedicated, see [GitLab Dedicated storage types](storage_types.md).
|
||||
|
||||
If you need to change either of these values, [submit a support ticket](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=4414917877650).
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ The **Overview** page displays:
|
|||
The top section shows important information about your tenant, including:
|
||||
|
||||
- Tenant name and URL
|
||||
- Total Git repository capacity
|
||||
- [Total Git repository capacity](create_instance/storage_types.md#view-repository-storage-per-gitaly-node)
|
||||
- Current GitLab version
|
||||
- Reference architecture
|
||||
- Maintenance window
|
||||
|
|
|
|||
|
|
@ -93,8 +93,8 @@ Test the regex patterns carefully. Tool output formats can change over time, and
|
|||
| Tool | Command | Regex pattern |
|
||||
|------|--------------------------------------|---------------|
|
||||
| tap | `tap --coverage-report=text-summary` | `/^Statements\s*:\s*([^%]+)/` |
|
||||
| nyc | `nyc npm test` | `/All files[^\|]*\|[^\|]*\s+([\d\.]+)/` |
|
||||
| jest | `jest --ci --coverage` | `/All files[^\|]*\|[^\|]*\s+([\d\.]+)/` |
|
||||
| nyc | `nyc npm test` | `/All files[^\|]*\\|[^\|]*\s+([\d\.]+)/` |
|
||||
| jest | `jest --ci --coverage` | `/All files[^\|]*\\|[^\|]*\s+([\d\.]+)/` |
|
||||
|
||||
{{< /tab >}}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,12 +64,12 @@ with the deployed staging AI gateway. To do this:
|
|||
|
||||
### Setup instructions to use GDK with the Code Suggestions Add-on
|
||||
|
||||
**Option 1 - Recommended**
|
||||
#### Option 1 - Recommended
|
||||
|
||||
1. Ensure that you have a [GitLab Team Member License](https://handbook.gitlab.com/handbook/engineering/developer-onboarding/#working-on-gitlab-ee-developer-licenses) and that it is [activated](../../administration/license_file.md).
|
||||
1. Follow the [Setup and Run GDK](_index.md#set-up-and-run-gdk) guide under the AI Features doc.
|
||||
|
||||
**Option 2**
|
||||
#### Option 2
|
||||
|
||||
You can set up Duo on your GDK by going through CustomersDot. This is a more complex process, but it more accurately reflects the GitLab Self-Managed setup of our customers.
|
||||
|
||||
|
|
|
|||
|
|
@ -222,17 +222,6 @@ Optionally, the context can contain:
|
|||
- `namespace`. If not provided, `project.namespace` will be used (if `project` is available).
|
||||
- `category`
|
||||
- `additional_properties`
|
||||
- `event_attribute_overrides` - is used when its necessary to override the attributes available in parent context. For example:
|
||||
|
||||
```ruby
|
||||
let(:event) { 'create_new_issue' }
|
||||
|
||||
it_behaves_like 'internal event tracking' do
|
||||
let(:event_attribute_overrides) { { event: 'create_new_milestone'} }
|
||||
|
||||
subject(:service_action) { described_class.new(issue).save }
|
||||
end
|
||||
```
|
||||
|
||||
If present in the context, the following legacy options will be respected by the shared example but are discouraged:
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ For each of the vulnerabilities listed in this document, AppSec aims to have a S
|
|||
| Guideline | Rule | Status |
|
||||
|---|---|---|
|
||||
| [Regular Expressions](#regular-expressions-guidelines) | [1](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_insecure_regex.yml) | ✅ |
|
||||
| [ReDOS](#denial-of-service-redos--catastrophic-backtracking) | [1](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_redos_1.yml), [2](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_redos_2.yml) | ✅ |
|
||||
| [ReDOS](#denial-of-service-redos--catastrophic-backtracking) | [1](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_redos_1.yml), [2](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_redos_2.yml), [3](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/merge_requests/59#note_2443657926) | ✅ |
|
||||
| [JWT](#json-web-tokens-jwt) | Pending | ❌ |
|
||||
| [SSRF](#server-side-request-forgery-ssrf) | [1](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_insecure_url-1.yml), [2](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_insecure_http.yml?ref_type=heads) | ✅ |
|
||||
| [XSS](#xss-guidelines) | [1](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_xss_redirect.yml), [2](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_xss_html_safe.yml) | ✅ |
|
||||
|
|
@ -301,6 +301,37 @@ For other regular expressions, here are a few guidelines:
|
|||
|
||||
Go's [`regexp`](https://pkg.go.dev/regexp) package uses `re2` and isn't vulnerable to backtracking issues.
|
||||
|
||||
#### Python Regular Expression Denial of Service (ReDoS) Prevention
|
||||
|
||||
Python offers three main regular expression libraries:
|
||||
|
||||
| Library | Security | Notes |
|
||||
|---------|---------------------|-----------------------------------------------------------------------|
|
||||
| `re` | Vulnerable to ReDoS | Built-in library. Must use timeout parameter. |
|
||||
| `regex` | Vulnerable to ReDoS | Third-party library with extended features. Must use timeout parameter. |
|
||||
| `re2` | Secure by default | Wrapper for the Google RE2 engine. Prevents backtracking by design. |
|
||||
|
||||
Both `re` and `regex` use backtracking algorithms that can cause exponential execution time with certain patterns.
|
||||
|
||||
```python
|
||||
evil_input = 'a' * 30 + '!'
|
||||
|
||||
# Vulnerable - can cause exponential execution time with nested quantifiers
|
||||
# 30 'a's -> ~30 seconds
|
||||
# 31 'a's -> ~60 seconds
|
||||
re.match(r'^(a+)+$', evil_input)
|
||||
regex.match(r'^(a|aa)+$', evil_input)
|
||||
|
||||
# Secure - adds timeout to limit execution time
|
||||
re.match(r'^(a+)+$', evil_input, timeout=1.0)
|
||||
regex.match(r'^(a|aa)+$', evil_input, timeout=1.0)
|
||||
|
||||
# Preferred - re2 prevents catastrophic backtracking by design
|
||||
re2.match(r'^(a+)+$', evil_input)
|
||||
```
|
||||
|
||||
When working with regular expressions in Python, use `re2` when possible or always include timeouts with `re` and `regex`.
|
||||
|
||||
### Further Links
|
||||
|
||||
- [Rubular](https://rubular.com/) is a nice online tool to fiddle with Ruby Regexps.
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ Workflow:
|
|||
For a click-through demo, see [GitLab Duo Workflow](https://gitlab.navattic.com/duo-workflow).
|
||||
<!-- Demo published on 2025-03-18 -->
|
||||
|
||||
For an overview, watch <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [Enhancing your quality assurance with GitLab Duo Workflow](https://youtu.be/Tuj7TgqY81Q?si=IbxaKv7IhAHYnHkN). <!-- Video published on 2025-03-20-->
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you can use Workflow, you must:
|
||||
|
|
@ -183,3 +185,7 @@ On your GitLab Self-Managed instance, you can view these events on the
|
|||
Workflow is a private beta and your feedback is crucial to improve it for you and others.
|
||||
To report issues or suggest improvements,
|
||||
[complete this survey](https://gitlab.fra1.qualtrics.com/jfe/form/SV_9GmCPTV7oH9KNuu).
|
||||
|
||||
## Related topics
|
||||
|
||||
- [Use GitLab Duo Workflow to improve application quality assurance](https://about.gitlab.com/blog/2025/04/10/use-gitlab-duo-workflow-to-improve-application-quality-assurance/)
|
||||
|
|
|
|||
|
|
@ -77,12 +77,6 @@ To add an emoji reaction to a comment or description:
|
|||
To use them in a text box, type the filename between two colons.
|
||||
For example, `:thank-you:`.
|
||||
|
||||
You can upload custom emoji to a GitLab instance with the GraphQL API.
|
||||
For more information, see [Use custom emoji with GraphQL](../api/graphql/custom_emoji.md).
|
||||
|
||||
For a list of custom emoji available for GitLab.com, see
|
||||
[the `custom_emoji` project](https://gitlab.com/custom_emoji/custom_emoji/-/tree/main/img).
|
||||
|
||||
### Upload custom emoji to a group
|
||||
|
||||
{{< history >}}
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ Code Suggestions is aware of the context you're working in.
|
|||
| [Open tab files](#using-open-files-as-context) | Files open in tabs in your IDE. These files give GitLab Duo more information about the standards and practices in your code project. | Optional, but on by default. |
|
||||
| [Imported files](#using-imported-files-as-context) | Files imported in the current opened file. These imported files give GitLab Duo more information about the classes and methods used in the current file. | Optional and off by default. |
|
||||
|
||||
**Footnotes:**
|
||||
Footnotes:
|
||||
|
||||
1. Code completion is aware of all [supported languages](supported_extensions.md#supported-languages-by-ide).
|
||||
Code generation is aware of files in these languages only:
|
||||
|
|
@ -321,10 +321,10 @@ When using Code Suggestions, [code review best practice](../../../../development
|
|||
|
||||
To learn about the code that builds the prompt, see these files:
|
||||
|
||||
- **Code generation**:
|
||||
- Code generation:
|
||||
[`ee/lib/api/code_suggestions.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/api/code_suggestions.rb#L76)
|
||||
in the `gitlab` repository.
|
||||
- **Code completion**:
|
||||
- Code completion:
|
||||
[`ai_gateway/code_suggestions/processing/completions.py`](https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist/-/blob/fcb3f485a8f047a86a8166aad81f93b6d82106a7/ai_gateway/code_suggestions/processing/completions.py#L273)
|
||||
in the `modelops` repository.
|
||||
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ The Repository X-Ray searches a maximum of two directory levels from the reposit
|
|||
| Python | Poetry | `poetry.lock`, `pyproject.toml` | 17.5 or later |
|
||||
| Ruby | RubyGems | `Gemfile.lock` | 17.4 or later |
|
||||
|
||||
**Footnotes**:
|
||||
Footnotes:
|
||||
|
||||
1. For Python Pip, all configuration files matching the `*requirements*.txt` glob pattern are processed.
|
||||
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ To do this:
|
|||
|
||||
1. Find your desired language in the list of
|
||||
[language identifiers](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentItem).
|
||||
You need the **Identifier** for your languages in a later step.
|
||||
You need the identifier for your languages in a later step.
|
||||
1. In your IDE, on the top bar, select your IDE name, then select **Settings**.
|
||||
1. On the left sidebar, select **Tools > GitLab Duo**.
|
||||
1. Under **Code Suggestions Enabled Languages > Additional languages**, add the identifier for each language
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ For non-Code Suggestions troubleshooting for Microsoft Visual Studio, see
|
|||
|
||||
### IntelliCode is missing
|
||||
|
||||
Code Suggestions requires the **IntelliCode** component of Visual Studio. If the component
|
||||
Code Suggestions requires the IntelliCode component of Visual Studio. If the component
|
||||
is missing, you might see an error like this when you start Visual Studio:
|
||||
|
||||
```plaintext
|
||||
|
|
@ -211,7 +211,7 @@ but found 0 after applying applicable constraints.
|
|||
[...]
|
||||
```
|
||||
|
||||
To fix this problem, install the **IntelliCode** component:
|
||||
To fix this problem, install the IntelliCode component:
|
||||
|
||||
1. In the Windows start menu, search for the **Visual Studio Installer** and open it.
|
||||
1. Select your Visual Studio instance, then select **Modify**.
|
||||
|
|
|
|||
|
|
@ -11629,7 +11629,7 @@ msgstr ""
|
|||
msgid "CICD|Are you sure you want to remove %{namespace} from the job token allowlist? This action cannot be undone."
|
||||
msgstr ""
|
||||
|
||||
msgid "CICD|Authentication events from the last 30 days. %{linkStart}Learn more.%{linkEnd}"
|
||||
msgid "CICD|Authentication events using the job token. %{linkStart}Learn more.%{linkEnd}"
|
||||
msgstr ""
|
||||
|
||||
msgid "CICD|Authentication log"
|
||||
|
|
@ -11728,7 +11728,7 @@ msgstr ""
|
|||
msgid "CICD|Maintainer"
|
||||
msgstr ""
|
||||
|
||||
msgid "CICD|No authentication events in the last 30 days."
|
||||
msgid "CICD|No authentication events to display."
|
||||
msgstr ""
|
||||
|
||||
msgid "CICD|No resources selected (minimal access only)"
|
||||
|
|
@ -28487,6 +28487,9 @@ msgstr ""
|
|||
msgid "GlobalSearch|Groups"
|
||||
msgstr ""
|
||||
|
||||
msgid "GlobalSearch|Groups I'm a member of"
|
||||
msgstr ""
|
||||
|
||||
msgid "GlobalSearch|Help"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -28598,6 +28601,9 @@ msgstr ""
|
|||
msgid "GlobalSearch|Projects"
|
||||
msgstr ""
|
||||
|
||||
msgid "GlobalSearch|Projects I'm a member of"
|
||||
msgstr ""
|
||||
|
||||
msgid "GlobalSearch|Projects not indexed"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -39502,9 +39508,6 @@ msgstr ""
|
|||
msgid "NamespaceStorageSize|If %{namespace_name} exceeds the %{storage_docs_link_start}storage quota%{link_end}, your ability to write new data to this namespace will be restricted. %{read_only_link_start}Which actions become restricted?%{link_end}"
|
||||
msgstr ""
|
||||
|
||||
msgid "NamespaceStorageSize|If a project reaches 100%% of the %{storage_docs_link_start}storage quota%{link_end} (%{free_size_limit}) the project will be in a read-only state, and you won't be able to push to your repository or add large files."
|
||||
msgstr ""
|
||||
|
||||
msgid "NamespaceStorageSize|To manage your usage and prevent your projects from being placed in a read-only state, you should immediately %{manage_storage_link_start}reduce storage%{link_end}, or %{support_link_start}contact support%{link_end} to help you manage your usage."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -39523,16 +39526,22 @@ msgstr ""
|
|||
msgid "NamespaceStorageSize|To remove the read-only state %{manage_storage_link_start}manage your storage usage%{link_end}, or contact a user with the %{group_member_link_start}owner role for this namespace%{link_end} and ask them to %{purchase_more_link_start}purchase more storage%{link_end}."
|
||||
msgstr ""
|
||||
|
||||
msgid "NamespaceStorageSize|To remove the read-only state, reduce git repository and git LFS storage, or %{purchase_more_link_start}purchase more storage%{link_end}."
|
||||
msgid "NamespaceStorageSize|To remove the read-only state contact a user with the %{group_member_link_start}owner role for this namespace%{link_end} and ask them to %{purchase_more_link_start}purchase more storage%{link_end}."
|
||||
msgstr ""
|
||||
|
||||
msgid "NamespaceStorageSize|To remove the read-only state, reduce git repository and git LFS storage, or contact a user with the %{group_member_link_start}owner role for this namespace%{link_end} and ask them to %{purchase_more_link_start}purchase more storage%{link_end}."
|
||||
msgid "NamespaceStorageSize|To remove the read-only state, %{manage_storage_link_start}manage your storage usage%{link_end} or %{purchase_more_link_start}purchase more storage%{link_end}."
|
||||
msgstr ""
|
||||
|
||||
msgid "NamespaceStorageSize|To remove the read-only state, %{manage_storage_link_start}manage your storage usage%{link_end} or %{support_link_start}contact support%{link_end}."
|
||||
msgstr ""
|
||||
|
||||
msgid "NamespaceStorageSize|We've noticed an unusually high storage usage on %{namespace_name}"
|
||||
msgstr ""
|
||||
|
||||
msgid "NamespaceStorageSize|You have consumed all available %{storage_docs_link_start}storage%{link_end} and you can't push or add large files to projects over the free tier limit (%{free_size_limit})."
|
||||
msgid "NamespaceStorageSize|When a project reaches 100%% of the %{storage_docs_link_start}allocated storage%{link_end} (%{free_size_limit}) it will be placed in a read-only state. You won't be able to push and add large files to your repository."
|
||||
msgstr ""
|
||||
|
||||
msgid "NamespaceStorageSize|You have consumed all available %{storage_docs_link_start}storage%{link_end} and can't push or add large files to projects over the included storage (%{free_size_limit})."
|
||||
msgstr ""
|
||||
|
||||
msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} for %{namespace_name}"
|
||||
|
|
|
|||
|
|
@ -53,11 +53,8 @@ module QA
|
|||
end
|
||||
|
||||
def run_unregister_command!
|
||||
cmd = <<~CMD.tr("\n", ' ')
|
||||
docker exec --detach #{@name} sh -c "#{unregister_command}"
|
||||
CMD
|
||||
|
||||
shell(cmd, mask_secrets: [runner_auth_token])
|
||||
output = shell("docker exec #{@name} sh -c '#{unregister_command}'", mask_secrets: [runner_auth_token])
|
||||
confirm_unregistered(output)
|
||||
end
|
||||
|
||||
def tags=(tags)
|
||||
|
|
@ -115,13 +112,21 @@ module QA
|
|||
|
||||
def runner_auth_token
|
||||
runner_list = shell("docker exec #{@name} sh -c 'gitlab-runner list'")
|
||||
runner_list.match(/Token\e\[0;m=([^ ]+)/)&.[](1)
|
||||
runner_list.match(/Token\e\[0;m=([^ ]+)/)&.[](1) || raise("No token found in runner list output")
|
||||
end
|
||||
|
||||
def unregister_command
|
||||
"gitlab-runner unregister --url #{@address} --token #{runner_auth_token}"
|
||||
end
|
||||
|
||||
def unregister_message_pattern
|
||||
/Unregistering runner( manager)? from GitLab succeeded/
|
||||
end
|
||||
|
||||
def confirm_unregistered(output)
|
||||
raise("Failed to unregister. Shell response: #{output}") unless output&.match?(unregister_message_pattern)
|
||||
end
|
||||
|
||||
# Ping Cloudflare DNS, should fail
|
||||
# Ping Registry, should fail to resolve
|
||||
def prove_airgap
|
||||
|
|
|
|||
|
|
@ -11,10 +11,6 @@ module QA
|
|||
end
|
||||
|
||||
it 'user unregisters a runner with authentication token',
|
||||
quarantine: {
|
||||
issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/513860',
|
||||
type: :stale
|
||||
},
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/510652' do
|
||||
Flow::Login.sign_in
|
||||
|
||||
|
|
@ -28,16 +24,8 @@ module QA
|
|||
end
|
||||
end
|
||||
|
||||
# The output of the unregister command is verified inside the GitlabRunner class
|
||||
runner.unregister!
|
||||
|
||||
page.refresh
|
||||
|
||||
Page::Project::Settings::CiCd.perform do |settings|
|
||||
settings.expand_runners_settings do |page|
|
||||
expect(page).to have_content(executor)
|
||||
expect(page).to have_offline_runner
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -202,9 +202,10 @@ module QA
|
|||
|
||||
describe '#unregister!' do
|
||||
let(:run_unregister_command) { subject.send(:run_unregister_command!) }
|
||||
let(:unregister_message) { 'Unregistering runner manager from GitLab succeeded' }
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:shell)
|
||||
allow(subject).to receive(:shell).and_return(unregister_message)
|
||||
|
||||
subject.instance_eval do
|
||||
def runner_auth_token
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
require 'parallel'
|
||||
require 'rainbow'
|
||||
|
||||
UNUSED_METHODS = 56
|
||||
UNUSED_METHODS = 52
|
||||
|
||||
print_output = %w[true 1].include? ENV["REPORT_ALL_UNUSED_METHODS"]
|
||||
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ RSpec.describe 'Container Registry', :js, feature_category: :container_registry
|
|||
end
|
||||
|
||||
it 'shows the details breadcrumb' do
|
||||
expect(find_by_testid('breadcrumb-links')).to have_link 'my/image'
|
||||
expect(find_by_testid('breadcrumb-links')).to have_link 'Container registry'
|
||||
end
|
||||
|
||||
it 'shows the image title' do
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ RSpec.describe 'Container Registry', :js, feature_category: :container_registry
|
|||
end
|
||||
|
||||
it 'shows the details breadcrumb' do
|
||||
expect(find_by_testid('breadcrumb-links')).to have_link 'my/image'
|
||||
expect(find_by_testid('breadcrumb-links')).to have_link 'Container registry'
|
||||
end
|
||||
|
||||
it 'shows the image title' do
|
||||
|
|
|
|||
|
|
@ -336,15 +336,6 @@ describe('PackagesApp', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('calls the appropriate function to set the breadcrumbState', async () => {
|
||||
const { name, version } = packageData();
|
||||
createComponent();
|
||||
|
||||
await waitForPromises();
|
||||
|
||||
expect(breadCrumbState.updateName).toHaveBeenCalledWith(`${name} v${version}`);
|
||||
});
|
||||
|
||||
describe('delete package', () => {
|
||||
const originalReferrer = document.referrer;
|
||||
const setReferrer = (value = packageDetailsQuery().data.package.project.name) => {
|
||||
|
|
|
|||
|
|
@ -53,16 +53,13 @@ describe('Registry Breadcrumb', () => {
|
|||
});
|
||||
|
||||
it('passes root and details to `items` prop', () => {
|
||||
expect(wrapper.findComponent(GlBreadcrumb).props('items')).toEqual([
|
||||
{
|
||||
text: 'mock name',
|
||||
to: '/',
|
||||
},
|
||||
{
|
||||
text: 'mock name',
|
||||
href: '/details',
|
||||
},
|
||||
]);
|
||||
const breadcrumbItems = wrapper.findComponent(GlBreadcrumb).props('items');
|
||||
expect(breadcrumbItems).toHaveLength(2);
|
||||
expect(breadcrumbItems[0]).toEqual({
|
||||
text: 'mock name',
|
||||
to: '/',
|
||||
});
|
||||
expect(breadcrumbItems[1].href).toBe('/:id');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -274,15 +274,15 @@ describe('GlobalSearchAutocompleteItems', () => {
|
|||
|
||||
describe('tracking', () => {
|
||||
it.each`
|
||||
action | event
|
||||
${'Projects'} | ${EVENT_CLICK_PROJECT_RESULT_IN_COMMAND_PALETTE}
|
||||
${'Groups'} | ${EVENT_CLICK_GROUP_RESULT_IN_COMMAND_PALETTE}
|
||||
${'Merge requests'} | ${EVENT_CLICK_MERGE_REQUEST_RESULT_IN_COMMAND_PALETTE}
|
||||
${'Issues'} | ${EVENT_CLICK_ISSUE_RESULT_IN_COMMAND_PALETTE}
|
||||
${'Recent issues'} | ${EVENT_CLICK_RECENT_ISSUE_RESULT_IN_COMMAND_PALETTE}
|
||||
${'Recent epics'} | ${EVENT_CLICK_RECENT_EPIC_RESULT_IN_COMMAND_PALETTE}
|
||||
${'Recent merge requests'} | ${EVENT_CLICK_RECENT_MERGE_REQUEST_RESULT_IN_COMMAND_PALETTE}
|
||||
${undefined} | ${EVENT_CLICK_USER_RESULT_IN_COMMAND_PALETTE}
|
||||
action | event
|
||||
${"Projects I'm a member of"} | ${EVENT_CLICK_PROJECT_RESULT_IN_COMMAND_PALETTE}
|
||||
${"Groups I'm a member of"} | ${EVENT_CLICK_GROUP_RESULT_IN_COMMAND_PALETTE}
|
||||
${'Merge requests'} | ${EVENT_CLICK_MERGE_REQUEST_RESULT_IN_COMMAND_PALETTE}
|
||||
${'Issues'} | ${EVENT_CLICK_ISSUE_RESULT_IN_COMMAND_PALETTE}
|
||||
${'Recent issues'} | ${EVENT_CLICK_RECENT_ISSUE_RESULT_IN_COMMAND_PALETTE}
|
||||
${'Recent epics'} | ${EVENT_CLICK_RECENT_EPIC_RESULT_IN_COMMAND_PALETTE}
|
||||
${'Recent merge requests'} | ${EVENT_CLICK_RECENT_MERGE_REQUEST_RESULT_IN_COMMAND_PALETTE}
|
||||
${undefined} | ${EVENT_CLICK_USER_RESULT_IN_COMMAND_PALETTE}
|
||||
`(
|
||||
"triggers tracking event '$event' after emiting action '$action'",
|
||||
({ action, event }) => {
|
||||
|
|
|
|||
|
|
@ -87,9 +87,7 @@ describe('TokenAccess component', () => {
|
|||
|
||||
await waitForPromises();
|
||||
|
||||
expect(findCrudComponentBody().text()).toContain(
|
||||
'No authentication events in the last 30 days.',
|
||||
);
|
||||
expect(findCrudComponentBody().text()).toContain('No authentication events to display.');
|
||||
});
|
||||
|
||||
it('displays a table when data is available', async () => {
|
||||
|
|
|
|||
|
|
@ -1222,13 +1222,6 @@ describe('WorkItemDetail component', () => {
|
|||
describe('work item parent id', () => {
|
||||
const parentId = 'gid://gitlab/Issue/1';
|
||||
|
||||
it('passes the `parentWorkItemId` value down to the `WorkItemStickyHeader` component', async () => {
|
||||
createComponent();
|
||||
await waitForPromises();
|
||||
|
||||
expect(findStickyHeader().props('parentId')).toBe(parentId);
|
||||
});
|
||||
|
||||
it('passes the `parentWorkItemId` value down to the `WorkItemActions` component', async () => {
|
||||
createComponent();
|
||||
await waitForPromises();
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ describe('WorkItemStickyHeader', () => {
|
|||
discussionLocked = false,
|
||||
canUpdate = true,
|
||||
features = {},
|
||||
parentId = null,
|
||||
movedToWorkItemUrl = null,
|
||||
duplicatedToWorkItemUrl = null,
|
||||
promotedToEpicUrl = null,
|
||||
|
|
@ -34,19 +33,12 @@ describe('WorkItemStickyHeader', () => {
|
|||
duplicatedToWorkItemUrl,
|
||||
promotedToEpicUrl,
|
||||
}).data.workItem,
|
||||
fullPath: '/test',
|
||||
isStickyHeaderShowing: true,
|
||||
workItemNotificationsSubscribed: true,
|
||||
updateInProgress: false,
|
||||
parentWorkItemConfidentiality: false,
|
||||
showWorkItemCurrentUserTodos: true,
|
||||
isModal: false,
|
||||
currentUserTodos: [],
|
||||
workItemState: STATE_OPEN,
|
||||
isGroup: false,
|
||||
parentId,
|
||||
showSidebar: true,
|
||||
truncationEnabled: true,
|
||||
},
|
||||
provide: {
|
||||
glFeatures: {
|
||||
|
|
|
|||
|
|
@ -6,11 +6,6 @@ RSpec.describe UserDetail, feature_category: :system_access do
|
|||
it { is_expected.to belong_to(:user) }
|
||||
it { is_expected.to belong_to(:bot_namespace).inverse_of(:bot_user_details) }
|
||||
|
||||
specify do
|
||||
values = [:basics, :move_repository, :code_storage, :exploring, :ci, :other, :joining_team]
|
||||
is_expected.to define_enum_for(:registration_objective).with_values(values).with_suffix
|
||||
end
|
||||
|
||||
describe 'validations' do
|
||||
context 'for onboarding_status json schema' do
|
||||
let(:step_url) { '_some_string_' }
|
||||
|
|
|
|||
|
|
@ -135,9 +135,6 @@ RSpec.describe User, feature_category: :user_profile do
|
|||
it { is_expected.to delegate_method(:bio).to(:user_detail).allow_nil }
|
||||
it { is_expected.to delegate_method(:bio=).to(:user_detail).with_arguments(:args).allow_nil }
|
||||
|
||||
it { is_expected.to delegate_method(:registration_objective).to(:user_detail).allow_nil }
|
||||
it { is_expected.to delegate_method(:registration_objective=).to(:user_detail).with_arguments(:args).allow_nil }
|
||||
|
||||
it { is_expected.to delegate_method(:discord).to(:user_detail).allow_nil }
|
||||
it { is_expected.to delegate_method(:discord=).to(:user_detail).with_arguments(:args).allow_nil }
|
||||
|
||||
|
|
|
|||
|
|
@ -245,12 +245,22 @@ RSpec.describe API::Todos, feature_category: :source_code_management do
|
|||
end
|
||||
|
||||
context 'when user is a bot' do
|
||||
it_behaves_like 'internal event tracking' do
|
||||
let(:event) { 'request_todos_by_bot_user' }
|
||||
let(:user) { create(:user, :service_account) }
|
||||
let(:additional_properties) { { label: 'user_type', property: user.user_type } }
|
||||
let(:event_attribute_overrides) { { project: nil, namespace: nil } }
|
||||
subject(:api_request) { get api('/todos', user) }
|
||||
let(:user) { create(:user, :service_account) }
|
||||
|
||||
it "triggers an internal event" do
|
||||
expect { get api('/todos', user) }
|
||||
.to trigger_internal_events('request_todos_by_bot_user')
|
||||
.with(
|
||||
category: 'InternalEventTracking',
|
||||
user: user,
|
||||
additional_properties: {
|
||||
label: 'user_type',
|
||||
property: user.user_type
|
||||
}
|
||||
).and increment_usage_metrics(
|
||||
'redis_hll_counters.count_distinct_user_id_from_request_todos_by_bot_user_weekly',
|
||||
'redis_hll_counters.count_distinct_user_id_from_request_todos_by_bot_user_monthly'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
# - namespace
|
||||
# - category
|
||||
# - additional_properties
|
||||
# - event_attribute_overrides - is used when its necessary to override the attributes available in parent context.
|
||||
#
|
||||
# [Legacy] If present in the context, the following will be respected by the shared example but are discouraged:
|
||||
# - label
|
||||
|
|
@ -57,7 +56,7 @@ RSpec.shared_examples 'internal event tracking' do
|
|||
value: try(:value)
|
||||
}.compact
|
||||
}
|
||||
}.merge(try(:event_attribute_overrides) || {})
|
||||
}
|
||||
|
||||
expect { subject }
|
||||
.to trigger_internal_events(event)
|
||||
|
|
|
|||
|
|
@ -512,10 +512,6 @@ RSpec.describe 'Internal Events matchers', :clean_gitlab_redis_shared_state, fea
|
|||
let(:label) { expected_label }
|
||||
end
|
||||
|
||||
it_behaves_like 'internal event tracking' do
|
||||
let(:event_attribute_overrides) { { additional_properties: { label: expected_label } } }
|
||||
end
|
||||
|
||||
context 'with incorrect value being provided in additional_properties.' do
|
||||
let(:unexpected_label) { 'BAD label value' }
|
||||
|
||||
|
|
@ -531,10 +527,6 @@ RSpec.describe 'Internal Events matchers', :clean_gitlab_redis_shared_state, fea
|
|||
it_behaves_like 'internal event tracking' do
|
||||
let(:label) { unexpected_label }
|
||||
end
|
||||
|
||||
it_behaves_like 'internal event tracking' do
|
||||
let(:event_attribute_overrides) { { additional_properties: { label: unexpected_label } } }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue