Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
64879e0d25
commit
c83db9983a
|
|
@ -0,0 +1,24 @@
|
|||
## Request
|
||||
|
||||
<!--
|
||||
Please briefly describe what you are looking to add or change and select the approrpiate check-box.
|
||||
-->
|
||||
- [] This is an update to an existing rule
|
||||
- [] This is a new rule
|
||||
|
||||
|
||||
## Vendor
|
||||
|
||||
<!--
|
||||
Please add a link to the vendor, documentation and any contact information you may have.
|
||||
-->
|
||||
|
||||
## Examples
|
||||
|
||||
<!--
|
||||
Please provide a list of examples of what this secret type could look like.
|
||||
-->
|
||||
|
||||
|
||||
/label ~"section::sec" ~"devops::application security testing" ~"group::secret detection" ~"GitLab Ultimate" ~"Category:Secret Detection" ~"Secret Detection:Pattern Change" ~"type::maintenance"
|
||||
/assign @abellucci @amarpatel
|
||||
|
|
@ -28,7 +28,6 @@ Gitlab/ServiceResponse:
|
|||
- 'app/services/packages/mark_package_for_destruction_service.rb'
|
||||
- 'app/services/packages/rubygems/dependency_resolver_service.rb'
|
||||
- 'app/services/snippets/base_service.rb'
|
||||
- 'app/services/snippets/destroy_service.rb'
|
||||
- 'app/services/timelogs/base_service.rb'
|
||||
- 'app/services/work_items/create_and_link_service.rb'
|
||||
- 'app/services/work_items/create_from_task_service.rb'
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
7d35879381a67a26332ecdd66392a2ad30bf64ca
|
||||
fe81274a218800d7e46002719c712915c8e491bf
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { GlBadge, GlPopover, GlSkeletonLoader } from '@gitlab/ui';
|
||||
import { GlIcon, GlBadge, GlPopover, GlSkeletonLoader } from '@gitlab/ui';
|
||||
import { STATUS_CLOSED, STATUS_MERGED } from '~/issues/constants';
|
||||
import { __ } from '~/locale';
|
||||
import CiIcon from '~/vue_shared/components/ci_icon/ci_icon.vue';
|
||||
|
|
@ -8,6 +8,7 @@ import query from '../queries/merge_request.query.graphql';
|
|||
|
||||
export default {
|
||||
components: {
|
||||
GlIcon,
|
||||
GlBadge,
|
||||
GlPopover,
|
||||
GlSkeletonLoader,
|
||||
|
|
@ -108,7 +109,8 @@ export default {
|
|||
<h5 v-if="!$apollo.queries.mergeRequest.loading" class="my-2">{{ title }}</h5>
|
||||
<!-- eslint-disable @gitlab/vue-require-i18n-strings -->
|
||||
<div class="gl-text-subtle">
|
||||
{{ `${namespacePath}!${iid}` }}
|
||||
<gl-icon name="merge-request" />
|
||||
<span class="gl-text-subtle">{{ `${namespacePath}!${iid}` }}</span>
|
||||
</div>
|
||||
<!-- eslint-enable @gitlab/vue-require-i18n-strings -->
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ export default {
|
|||
variables() {
|
||||
return {
|
||||
...this.variables,
|
||||
includeMergeabilityChecks: this.showMergeChecksSuccess,
|
||||
perPage: PER_PAGE,
|
||||
};
|
||||
},
|
||||
|
|
@ -43,6 +44,7 @@ export default {
|
|||
},
|
||||
},
|
||||
},
|
||||
inject: { showMergeChecksSuccess: { default: false } },
|
||||
props: {
|
||||
query: {
|
||||
type: String,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<script>
|
||||
import { GlBadge, GlTooltipDirective as GlTooltip } from '@gitlab/ui';
|
||||
import { __ } from '~/locale';
|
||||
import { TYPENAME_USER } from '~/graphql_shared/constants';
|
||||
import { convertToGraphQLId } from '~/graphql_shared/utils';
|
||||
import { BADGE_METHODS } from '../utils/status_badge';
|
||||
|
|
@ -29,6 +30,21 @@ export default {
|
|||
return this.mergeRequest.reviewers.nodes.find((r) => r.id === this.currentUserId);
|
||||
},
|
||||
badgeData() {
|
||||
if (this.mergeRequest.mergeabilityChecks) {
|
||||
const failedChecks = this.mergeRequest.mergeabilityChecks.filter(
|
||||
({ status }) => status === 'FAILED',
|
||||
);
|
||||
|
||||
if (failedChecks.length === 0) {
|
||||
return {
|
||||
icon: 'status-success',
|
||||
variant: 'success',
|
||||
text: __('Ready to merge'),
|
||||
iconOpticallyAligned: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return BADGE_METHODS[this.listId]?.(this);
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ export function initMergeRequestDashboard(el) {
|
|||
apolloProvider,
|
||||
provide: {
|
||||
mergeRequestsSearchDashboardPath: el.dataset.mergeRequestsSearchDashboardPath,
|
||||
showMergeChecksSuccess: el.dataset.showMergeChecksSuccess === 'true',
|
||||
},
|
||||
render(createElement) {
|
||||
return createElement(App, {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ query requestingReview(
|
|||
$perPage: Int!
|
||||
$afterCursor: String
|
||||
$sort: MergeRequestSort = UPDATED_DESC
|
||||
$includeMergeabilityChecks: Boolean = false
|
||||
) {
|
||||
currentUser {
|
||||
id
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ query assigneeOrReviewer(
|
|||
$perPage: Int!
|
||||
$afterCursor: String
|
||||
$sort: MergeRequestSort = UPDATED_DESC
|
||||
$includeMergeabilityChecks: Boolean = false
|
||||
) {
|
||||
currentUser {
|
||||
id
|
||||
|
|
|
|||
|
|
@ -56,5 +56,8 @@ fragment MergeRequestDashboardFragment on MergeRequest {
|
|||
mergedAt
|
||||
createdAt
|
||||
updatedAt
|
||||
mergeabilityChecks @include(if: $includeMergeabilityChecks) {
|
||||
status
|
||||
}
|
||||
...MergeRequestApprovalFragment
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ query reviewRequests(
|
|||
$perPage: Int!
|
||||
$afterCursor: String
|
||||
$sort: MergeRequestSort = UPDATED_DESC
|
||||
$includeMergeabilityChecks: Boolean = false
|
||||
) {
|
||||
currentUser {
|
||||
id
|
||||
|
|
|
|||
|
|
@ -573,10 +573,11 @@
|
|||
$anchor-offset: 20px;
|
||||
|
||||
a.anchor {
|
||||
float: left;
|
||||
margin-left: calc(-1 * $anchor-offset);
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
position: absolute;
|
||||
width: $anchor-offset;
|
||||
|
||||
&::after {
|
||||
@include gl-dark-invert-keep-hue;
|
||||
|
|
@ -587,15 +588,11 @@
|
|||
|
||||
&:hover > a.anchor::after {
|
||||
visibility: visible;
|
||||
position: absolute;
|
||||
width: $anchor-offset;
|
||||
}
|
||||
|
||||
> a.anchor:focus::after {
|
||||
visibility: visible;
|
||||
outline: auto;
|
||||
position: absolute;
|
||||
width: $anchor-offset;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,8 +48,8 @@ module Snippets
|
|||
can?(current_user, :admin_snippet, snippet)
|
||||
end
|
||||
|
||||
def service_response_error(message, http_status)
|
||||
ServiceResponse.error(message: message, http_status: http_status)
|
||||
def service_response_error(message, reason)
|
||||
ServiceResponse.error(message: message, reason: reason)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
#js-merge-request-dashboard-config
|
||||
|
||||
- if merge_request_dashboard_enabled?(current_user) && !current_page?(merge_requests_search_dashboard_path)
|
||||
#js-merge-request-dashboard{ data: { base_path: merge_requests_dashboard_path, merge_requests_search_dashboard_path: merge_requests_search_dashboard_path(assignee_username: current_user.username), initial_data: merge_request_dashboard_data.to_json } }
|
||||
#js-merge-request-dashboard{ data: { base_path: merge_requests_dashboard_path, merge_requests_search_dashboard_path: merge_requests_search_dashboard_path(assignee_username: current_user.username), initial_data: merge_request_dashboard_data.to_json, show_merge_checks_success: Feature.enabled?(:merge_request_dashboard_merge_checks, current_user, type: :gitlab_com_derisk).to_s } }
|
||||
= gl_loading_icon(size: 'lg')
|
||||
|
||||
- if !merge_request_dashboard_enabled?(current_user) || current_page?(merge_requests_search_dashboard_path)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
name: merge_request_dashboard_merge_checks
|
||||
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/518710
|
||||
introduced_by_url:
|
||||
rollout_issue_url:
|
||||
milestone: '17.10'
|
||||
group: group::code review
|
||||
type: gitlab_com_derisk
|
||||
default_enabled: false
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
migration_job_name: BackfillMergeRequestContextCommitDiffFilesProjectId
|
||||
description: Backfills sharding key `merge_request_context_commit_diff_files.project_id` from `merge_request_context_commits`.
|
||||
feature_category: code_review_workflow
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/183935
|
||||
milestone: '17.11'
|
||||
queued_migration_version: 20250308115805
|
||||
finalized_by: # version of the migration that finalized this BBM
|
||||
|
|
@ -5,4 +5,4 @@ feature_category: subscription_management
|
|||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/174626
|
||||
milestone: '17.7'
|
||||
queued_migration_version: 20241203172717
|
||||
finalized_by: 20241203172717
|
||||
finalized_by: 20250312151614
|
||||
|
|
|
|||
|
|
@ -18,5 +18,4 @@ desired_sharding_key:
|
|||
table: incident_management_oncall_rotations
|
||||
sharding_key: project_id
|
||||
belongs_to: rotation
|
||||
awaiting_backfill_on_parent: true
|
||||
table_size: small
|
||||
|
|
|
|||
|
|
@ -9,14 +9,6 @@ description: Persists information about on-call rotation
|
|||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49058
|
||||
milestone: '13.7'
|
||||
gitlab_schema: gitlab_main_cell
|
||||
desired_sharding_key:
|
||||
project_id:
|
||||
references: projects
|
||||
backfill_via:
|
||||
parent:
|
||||
foreign_key: oncall_schedule_id
|
||||
table: incident_management_oncall_schedules
|
||||
sharding_key: project_id
|
||||
belongs_to: schedule
|
||||
desired_sharding_key_migration_job_name: BackfillIncidentManagementOncallRotationsProjectId
|
||||
sharding_key:
|
||||
project_id: projects
|
||||
table_size: small
|
||||
|
|
|
|||
|
|
@ -18,5 +18,4 @@ desired_sharding_key:
|
|||
table: incident_management_oncall_rotations
|
||||
sharding_key: project_id
|
||||
belongs_to: rotation
|
||||
awaiting_backfill_on_parent: true
|
||||
table_size: small
|
||||
|
|
|
|||
|
|
@ -18,3 +18,4 @@ desired_sharding_key:
|
|||
sharding_key: project_id
|
||||
belongs_to: merge_request_context_commit
|
||||
table_size: small
|
||||
desired_sharding_key_migration_job_name: BackfillMergeRequestContextCommitDiffFilesProjectId
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddProjectIdToMergeRequestContextCommitDiffFiles < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.11'
|
||||
|
||||
def change
|
||||
add_column :merge_request_context_commit_diff_files, :project_id, :bigint
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class IndexMergeRequestContextCommitDiffFilesOnProjectId < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.11'
|
||||
disable_ddl_transaction!
|
||||
|
||||
INDEX_NAME = 'index_merge_request_context_commit_diff_files_on_project_id'
|
||||
|
||||
def up
|
||||
add_concurrent_index :merge_request_context_commit_diff_files, :project_id, name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
remove_concurrent_index_by_name :merge_request_context_commit_diff_files, INDEX_NAME
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddMergeRequestContextCommitDiffFilesProjectIdFk < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.11'
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_concurrent_foreign_key :merge_request_context_commit_diff_files, :projects, column: :project_id,
|
||||
on_delete: :cascade
|
||||
end
|
||||
|
||||
def down
|
||||
with_lock_retries do
|
||||
remove_foreign_key :merge_request_context_commit_diff_files, column: :project_id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddMergeRequestContextCommitDiffFilesProjectIdTrigger < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.11'
|
||||
|
||||
def up
|
||||
install_sharding_key_assignment_trigger(
|
||||
table: :merge_request_context_commit_diff_files,
|
||||
sharding_key: :project_id,
|
||||
parent_table: :merge_request_context_commits,
|
||||
parent_sharding_key: :project_id,
|
||||
foreign_key: :merge_request_context_commit_id
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
remove_sharding_key_assignment_trigger(
|
||||
table: :merge_request_context_commit_diff_files,
|
||||
sharding_key: :project_id,
|
||||
parent_table: :merge_request_context_commits,
|
||||
parent_sharding_key: :project_id,
|
||||
foreign_key: :merge_request_context_commit_id
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class QueueBackfillMergeRequestContextCommitDiffFilesProjectId < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.11'
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_main_cell
|
||||
|
||||
MIGRATION = "BackfillMergeRequestContextCommitDiffFilesProjectId"
|
||||
STRATEGY = 'PrimaryKeyBatchingStrategy'
|
||||
DELAY_INTERVAL = 2.minutes
|
||||
BATCH_SIZE = 1000
|
||||
SUB_BATCH_SIZE = 100
|
||||
|
||||
def up
|
||||
model = define_batchable_model('merge_request_context_commit_diff_files')
|
||||
max_merge_request_context_commit_id = model.maximum(:merge_request_context_commit_id)
|
||||
max_relative_order = model.maximum(:relative_order)
|
||||
|
||||
max_merge_request_context_commit_id ||= 0
|
||||
max_relative_order ||= 0
|
||||
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration.create!(
|
||||
gitlab_schema: :gitlab_main_cell,
|
||||
job_class_name: MIGRATION,
|
||||
job_arguments: [
|
||||
:project_id,
|
||||
:merge_request_context_commits,
|
||||
:project_id,
|
||||
:merge_request_context_commit_id
|
||||
],
|
||||
table_name: :merge_request_context_commit_diff_files,
|
||||
column_name: :merge_request_context_commit_id,
|
||||
min_cursor: [0, 0],
|
||||
max_cursor: [max_merge_request_context_commit_id, max_relative_order],
|
||||
interval: DELAY_INTERVAL,
|
||||
pause_ms: 100,
|
||||
batch_class_name: STRATEGY,
|
||||
batch_size: BATCH_SIZE,
|
||||
sub_batch_size: SUB_BATCH_SIZE,
|
||||
status_event: :execute
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
delete_batched_background_migration(
|
||||
MIGRATION,
|
||||
:merge_request_context_commit_diff_files,
|
||||
:merge_request_context_commit_id,
|
||||
[
|
||||
:project_id,
|
||||
:merge_request_context_commits,
|
||||
:project_id,
|
||||
:merge_request_context_commit_id
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class FinalizeBackfillSubscriptionAddOnPurchasesStartedAt < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.10'
|
||||
disable_ddl_transaction!
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||
|
||||
TABLE_NAME = :subscription_add_on_purchases
|
||||
COLUMN_NAME = :id
|
||||
|
||||
def up
|
||||
ensure_batched_background_migration_is_finished(
|
||||
job_class_name: 'BackfillSubscriptionAddOnPurchasesStartedAt',
|
||||
table_name: TABLE_NAME,
|
||||
column_name: COLUMN_NAME,
|
||||
job_arguments: []
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
# no-op
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddIncidentManagementOncallRotationProjectIdNotNull < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.11'
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_not_null_constraint :incident_management_oncall_rotations, :project_id
|
||||
end
|
||||
|
||||
def down
|
||||
remove_not_null_constraint :incident_management_oncall_rotations, :project_id
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
291851377bba797384039b76be45cfdc55c3ed29fff681266bda61c350d245a7
|
||||
|
|
@ -0,0 +1 @@
|
|||
80bbe5353965d1e04165311820c906037e4778043ff42ffcf08f47adb1815846
|
||||
|
|
@ -0,0 +1 @@
|
|||
41e55d4ccec654a4947ca9d9044cd03866b86247f8a64b9902121698d292fe2c
|
||||
|
|
@ -0,0 +1 @@
|
|||
01121faa2ac6fb6c452c65e0aeacb388d989c65699addb21a797c1942605a277
|
||||
|
|
@ -0,0 +1 @@
|
|||
3938a36e27902e5d629029cf1991224c7563213c3fa9b5c602f93c1722e9716c
|
||||
|
|
@ -0,0 +1 @@
|
|||
f499be508b6263c95072ac9f1da9f404c84d0ccb5471bee263c17a63a2adb904
|
||||
|
|
@ -0,0 +1 @@
|
|||
2ca858d5a77dc2560ea3865ae2ec5ae7aade28c07865bd0a92855daf61d9fd3c
|
||||
|
|
@ -2941,6 +2941,22 @@ RETURN NEW;
|
|||
END
|
||||
$$;
|
||||
|
||||
CREATE FUNCTION trigger_91e1012b9851() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
IF NEW."project_id" IS NULL THEN
|
||||
SELECT "project_id"
|
||||
INTO NEW."project_id"
|
||||
FROM "merge_request_context_commits"
|
||||
WHERE "merge_request_context_commits"."id" = NEW."merge_request_context_commit_id";
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
|
||||
END
|
||||
$$;
|
||||
|
||||
CREATE FUNCTION trigger_9259aae92378() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
|
|
@ -15084,6 +15100,7 @@ CREATE TABLE incident_management_oncall_rotations (
|
|||
active_period_start time without time zone,
|
||||
active_period_end time without time zone,
|
||||
project_id bigint,
|
||||
CONSTRAINT check_28c39f8a0c CHECK ((project_id IS NOT NULL)),
|
||||
CONSTRAINT check_5209fb5d02 CHECK ((char_length(name) <= 200))
|
||||
);
|
||||
|
||||
|
|
@ -16357,7 +16374,8 @@ CREATE TABLE merge_request_context_commit_diff_files (
|
|||
"binary" boolean,
|
||||
merge_request_context_commit_id bigint NOT NULL,
|
||||
generated boolean,
|
||||
encoded_file_path boolean DEFAULT false NOT NULL
|
||||
encoded_file_path boolean DEFAULT false NOT NULL,
|
||||
project_id bigint
|
||||
);
|
||||
|
||||
CREATE TABLE merge_request_context_commits (
|
||||
|
|
@ -34285,6 +34303,8 @@ CREATE UNIQUE INDEX index_merge_request_cleanup_schedules_on_merge_request_id ON
|
|||
|
||||
CREATE INDEX index_merge_request_cleanup_schedules_on_status ON merge_request_cleanup_schedules USING btree (status);
|
||||
|
||||
CREATE INDEX index_merge_request_context_commit_diff_files_on_project_id ON merge_request_context_commit_diff_files USING btree (project_id);
|
||||
|
||||
CREATE INDEX index_merge_request_context_commits_on_project_id ON merge_request_context_commits USING btree (project_id);
|
||||
|
||||
CREATE UNIQUE INDEX index_merge_request_diff_commit_users_on_name_and_email ON merge_request_diff_commit_users USING btree (name, email);
|
||||
|
|
@ -39273,6 +39293,8 @@ CREATE TRIGGER trigger_8fbb044c64ad BEFORE INSERT OR UPDATE ON design_management
|
|||
|
||||
CREATE TRIGGER trigger_90fa5c6951f1 BEFORE INSERT OR UPDATE ON dast_profiles_tags FOR EACH ROW EXECUTE FUNCTION trigger_90fa5c6951f1();
|
||||
|
||||
CREATE TRIGGER trigger_91e1012b9851 BEFORE INSERT OR UPDATE ON merge_request_context_commit_diff_files FOR EACH ROW EXECUTE FUNCTION trigger_91e1012b9851();
|
||||
|
||||
CREATE TRIGGER trigger_9259aae92378 BEFORE INSERT OR UPDATE ON packages_build_infos FOR EACH ROW EXECUTE FUNCTION trigger_9259aae92378();
|
||||
|
||||
CREATE TRIGGER trigger_93a5b044f4e8 BEFORE INSERT OR UPDATE ON snippet_user_mentions FOR EACH ROW EXECUTE FUNCTION trigger_93a5b044f4e8();
|
||||
|
|
@ -41277,6 +41299,9 @@ ALTER TABLE ONLY project_topics
|
|||
ALTER TABLE ONLY web_hooks
|
||||
ADD CONSTRAINT fk_db1ea5699b FOREIGN KEY (integration_id) REFERENCES integrations(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY merge_request_context_commit_diff_files
|
||||
ADD CONSTRAINT fk_db51fb6abe FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY work_item_dates_sources
|
||||
ADD CONSTRAINT fk_dbbe8917ee FOREIGN KEY (due_date_sourcing_work_item_id) REFERENCES issues(id) ON DELETE SET NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ title: GitLab for Slack app administration
|
|||
{{< details >}}
|
||||
|
||||
- Tier: Free, Premium, Ultimate
|
||||
- Offering: GitLab Self-Managed
|
||||
- Offering: GitLab Self-Managed, GitLab Dedicated
|
||||
|
||||
{{< /details >}}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,10 @@ title: AI gateway
|
|||
|
||||
The [AI gateway](https://handbook.gitlab.com/handbook/engineering/architecture/design-documents/ai_gateway/) is a standalone service that gives access to AI-powered GitLab Duo features.
|
||||
|
||||
GitLab operates an instance of *AI gateway* that is used by all GitLab instances, including self-managed, GitLab Dedicated, and GitLab.com via [Cloud Connector](../../development/cloud_connector/_index.md).
|
||||
GitLab operates an instance of AI gateway that is used by GitLab Self-Managed, GitLab Dedicated, and GitLab.com through the [Cloud Connector](../../development/cloud_connector/_index.md).
|
||||
|
||||
On GitLab Self-Managed, this GitLab instance of AI gateway applies regardless of whether you are using the
|
||||
cloud-based AI gateway hosted by GitLab, or using [GitLab Duo Self-Hosted](../../administration/gitlab_duo_self_hosted/_index.md) to self-host the AI gateway.
|
||||
|
||||
This page describes where the AI gateway is deployed, and answers questions about region selection, data routing, and data sovereignty.
|
||||
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ module API
|
|||
response = service.execute
|
||||
|
||||
if response.error?
|
||||
render_api_error!({ error: response.message }, response.http_status)
|
||||
render_api_error!({ error: response.message }, response.reason)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ module API
|
|||
response = service.execute
|
||||
|
||||
if response.error?
|
||||
render_api_error!({ error: response.message }, response.http_status)
|
||||
render_api_error!({ error: response.message }, response.reason)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module BackgroundMigration
|
||||
class BackfillMergeRequestContextCommitDiffFilesProjectId < BatchedMigrationJob
|
||||
operation_name :backfill_merge_request_context_commit_diff_files_project_id
|
||||
feature_category :code_review_workflow
|
||||
cursor :merge_request_context_commit_id, :relative_order
|
||||
|
||||
def perform
|
||||
each_sub_batch do |relation|
|
||||
connection.execute(<<~SQL)
|
||||
WITH batched_relation AS (
|
||||
#{relation.where(project_id: nil).select(:merge_request_context_commit_id, :relative_order).to_sql}
|
||||
)
|
||||
UPDATE merge_request_context_commit_diff_files
|
||||
SET project_id = merge_request_context_commits.project_id
|
||||
FROM batched_relation
|
||||
INNER JOIN merge_request_context_commits ON batched_relation.merge_request_context_commit_id = merge_request_context_commits.id
|
||||
WHERE merge_request_context_commit_diff_files.merge_request_context_commit_id = batched_relation.merge_request_context_commit_id
|
||||
AND merge_request_context_commit_diff_files.relative_order = batched_relation.relative_order;
|
||||
SQL
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1225,6 +1225,9 @@ msgstr ""
|
|||
msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more%{help_link_end}."
|
||||
msgstr ""
|
||||
|
||||
msgid "%{projectsCount}, %{subGroupsCount}"
|
||||
msgstr ""
|
||||
|
||||
msgid "%{project} has %{number} fork"
|
||||
msgid_plural "%{project} has %{number} forks"
|
||||
msgstr[0] ""
|
||||
|
|
@ -48140,6 +48143,9 @@ msgstr ""
|
|||
msgid "Ready to get started with GitLab? Follow these steps to get familiar with us:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Ready to merge"
|
||||
msgstr ""
|
||||
|
||||
msgid "Ready to merge by members who can write to the target branch."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -52664,6 +52670,9 @@ msgstr ""
|
|||
msgid "SecurityExclusions|ex: spec/**/*.rb"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|Add project to this group to start tracking their security posture."
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|CS"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -52676,6 +52685,12 @@ msgstr ""
|
|||
msgid "SecurityInventory|IaC"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|Manage security configuration"
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|No projects found."
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory|SAST"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -52688,6 +52703,9 @@ msgstr ""
|
|||
msgid "SecurityInventory|View security coverage and vulnerabilities for all the projects in this group. Data is refreshed and may be upto 24 hours behind."
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityInventory||An error occurred while fetching subgroups and projects. Please try again."
|
||||
msgstr ""
|
||||
|
||||
msgid "SecurityOrchestration| and "
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -61506,6 +61524,9 @@ msgstr ""
|
|||
msgid "Tool"
|
||||
msgstr ""
|
||||
|
||||
msgid "Tool Coverage"
|
||||
msgstr ""
|
||||
|
||||
msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -215,8 +215,6 @@ spec/frontend/todos/components/filtered_search_tokens/project_token_spec.js
|
|||
spec/frontend/tooltips/components/tooltips_spec.js
|
||||
spec/frontend/tooltips/index_spec.js
|
||||
spec/frontend/vue_alerts_spec.js
|
||||
spec/frontend/vue_merge_request_widget/components/mr_widget_pipeline_spec.js
|
||||
spec/frontend/vue_merge_request_widget/components/states/merge_failed_pipeline_confirmation_dialog_spec.js
|
||||
spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js
|
||||
spec/frontend/vue_popovers_spec.js
|
||||
spec/frontend/vue_shared/components/confirm_modal_spec.js
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ describe('Merge requests query component', () => {
|
|||
perPage: 20,
|
||||
state: 'opened',
|
||||
sort: 'UPDATED_DESC',
|
||||
includeMergeabilityChecks: false,
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -108,6 +109,7 @@ describe('Merge requests query component', () => {
|
|||
perPage: 20,
|
||||
state: 'opened',
|
||||
sort: 'UPDATED_DESC',
|
||||
includeMergeabilityChecks: false,
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -46,4 +46,29 @@ describe('Merge request status badge component', () => {
|
|||
|
||||
expect(findStatusBadge().element).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe('ready to merge', () => {
|
||||
it('renders ready to merge badge when there is no failed merge checks', () => {
|
||||
createComponent({
|
||||
mergeRequest: {
|
||||
mergeabilityChecks: [{ status: 'SUCCESS' }],
|
||||
},
|
||||
});
|
||||
|
||||
expect(findStatusBadge().text()).toBe('Ready to merge');
|
||||
expect(findStatusBadge().attributes('icon')).toBe('status-success');
|
||||
});
|
||||
|
||||
it('renders normal status badge when there is failed merge checks', () => {
|
||||
createComponent({
|
||||
mergeRequest: {
|
||||
mergeabilityChecks: [{ status: 'FAILED' }],
|
||||
reviewers: { nodes: [] },
|
||||
},
|
||||
listId: 'assigned_to_you',
|
||||
});
|
||||
|
||||
expect(findStatusBadge().text()).toBe('Reviewers needed');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -122,7 +122,9 @@ if (global.document) {
|
|||
MountingPortal: {
|
||||
template: '<h1>MOUNTING-PORTAL</h1>',
|
||||
},
|
||||
Wormhole: {},
|
||||
Wormhole: {
|
||||
hasTarget: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
VTU.config.global.renderStubDefaultSlot = true;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,197 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::BackgroundMigration::BackfillMergeRequestContextCommitDiffFilesProjectId, feature_category: :code_review_workflow do
|
||||
let(:connection) { ApplicationRecord.connection }
|
||||
let(:organization) { organizations.create!(name: 'organization', path: 'organization') }
|
||||
let(:start_cursor) { [0, 0] }
|
||||
let(:end_cursor) { [merge_request_context_commits.maximum(:id), 1] }
|
||||
|
||||
let(:migration) do
|
||||
described_class.new(
|
||||
start_cursor: start_cursor,
|
||||
end_cursor: end_cursor,
|
||||
batch_table: :merge_request_context_commit_diff_files,
|
||||
batch_column: :merge_request_context_commit_id,
|
||||
sub_batch_size: 2,
|
||||
pause_ms: 0,
|
||||
connection: connection
|
||||
)
|
||||
end
|
||||
|
||||
shared_context 'for database tables' do
|
||||
let(:namespaces) { table(:namespaces) }
|
||||
let(:organizations) { table(:organizations) }
|
||||
let(:merge_request_context_commits) { table(:merge_request_context_commits) { |t| t.primary_key = :id } }
|
||||
let(:merge_requests) { table(:merge_requests) { |t| t.primary_key = :id } }
|
||||
let(:projects) { table(:projects) }
|
||||
let(:merge_request_context_commit_diff_files) do
|
||||
table(:merge_request_context_commit_diff_files) { |t| t.primary_key = :merge_request_context_commit_id }
|
||||
end
|
||||
end
|
||||
|
||||
shared_context 'for namespaces' do
|
||||
let(:namespace1) { namespaces.create!(name: 'namespace 1', path: 'namespace1', organization_id: organization.id) }
|
||||
let(:namespace2) { namespaces.create!(name: 'namespace 2', path: 'namespace2', organization_id: organization.id) }
|
||||
let(:namespace3) { namespaces.create!(name: 'namespace 3', path: 'namespace3', organization_id: organization.id) }
|
||||
let(:namespace4) { namespaces.create!(name: 'namespace 4', path: 'namespace4', organization_id: organization.id) }
|
||||
end
|
||||
|
||||
shared_context 'for projects' do
|
||||
let(:project1) do
|
||||
projects.create!(
|
||||
namespace_id: namespace1.id,
|
||||
project_namespace_id: namespace1.id,
|
||||
organization_id: organization.id
|
||||
)
|
||||
end
|
||||
|
||||
let(:project2) do
|
||||
projects.create!(
|
||||
namespace_id: namespace2.id,
|
||||
project_namespace_id: namespace2.id,
|
||||
organization_id: organization.id
|
||||
)
|
||||
end
|
||||
|
||||
let(:project3) do
|
||||
projects.create!(
|
||||
namespace_id: namespace3.id,
|
||||
project_namespace_id: namespace3.id,
|
||||
organization_id: organization.id
|
||||
)
|
||||
end
|
||||
|
||||
let(:project4) do
|
||||
projects.create!(
|
||||
namespace_id: namespace4.id,
|
||||
project_namespace_id: namespace4.id,
|
||||
organization_id: organization.id
|
||||
)
|
||||
end
|
||||
|
||||
let(:commit) { OpenSSL::Digest::SHA256.hexdigest(SecureRandom.hex) }
|
||||
end
|
||||
|
||||
shared_context 'for merge requests' do
|
||||
let!(:merge_request_1) do
|
||||
merge_requests.create!(
|
||||
target_project_id: project1.id,
|
||||
target_branch: 'master',
|
||||
source_branch: 'feature',
|
||||
source_project_id: project1.id
|
||||
)
|
||||
end
|
||||
|
||||
let!(:merge_request_2) do
|
||||
merge_requests.create!(
|
||||
target_project_id: project2.id,
|
||||
target_branch: 'master',
|
||||
source_branch: 'feature',
|
||||
source_project_id: project2.id
|
||||
)
|
||||
end
|
||||
|
||||
let!(:merge_request_3) do
|
||||
merge_requests.create!(
|
||||
target_project_id: project3.id,
|
||||
target_branch: 'master',
|
||||
source_branch: 'feature',
|
||||
source_project_id: project3.id
|
||||
)
|
||||
end
|
||||
|
||||
let!(:merge_request_4) do
|
||||
merge_requests.create!(
|
||||
target_project_id: project4.id,
|
||||
target_branch: 'master',
|
||||
source_branch: 'feature',
|
||||
source_project_id: project4.id
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
shared_context 'for merge requests context diff and commits' do
|
||||
let!(:merge_request_context_commit1) do
|
||||
merge_request_context_commits.create!(
|
||||
relative_order: 0,
|
||||
sha: commit,
|
||||
merge_request_id: merge_request_1.id,
|
||||
project_id: project1.id
|
||||
)
|
||||
end
|
||||
|
||||
let!(:merge_request_context_commit2) do
|
||||
merge_request_context_commits.create!(
|
||||
relative_order: 0,
|
||||
sha: commit,
|
||||
merge_request_id: merge_request_2.id,
|
||||
project_id: project2.id
|
||||
)
|
||||
end
|
||||
|
||||
let!(:merge_request_context_commit3) do
|
||||
merge_request_context_commits.create!(
|
||||
relative_order: 0,
|
||||
sha: commit,
|
||||
merge_request_id: merge_request_3.id,
|
||||
project_id: project3.id
|
||||
)
|
||||
end
|
||||
|
||||
let!(:merge_request_context_commit4) do
|
||||
merge_request_context_commits.create!(
|
||||
relative_order: 0,
|
||||
sha: commit,
|
||||
merge_request_id: merge_request_4.id,
|
||||
project_id: project4.id
|
||||
)
|
||||
end
|
||||
|
||||
let!(:merge_request_context_commit_diff_file_1) do
|
||||
merge_request_context_commit_diff_files.create!(merge_request_context_commit_id: merge_request_context_commit1.id,
|
||||
relative_order: 0, sha: commit, new_file: true, renamed_file: false, deleted_file: true,
|
||||
too_large: false, a_mode: 100500, b_mode: 100755, new_path: 'new_path', old_path: 'old_path', project_id: nil)
|
||||
end
|
||||
|
||||
let!(:merge_request_context_commit_diff_file_2) do
|
||||
merge_request_context_commit_diff_files.create!(merge_request_context_commit_id: merge_request_context_commit2.id,
|
||||
relative_order: 0, sha: commit, new_file: true, renamed_file: false, deleted_file: true,
|
||||
too_large: false, a_mode: 100500, b_mode: 100755, new_path: 'new_path', old_path: 'old_path', project_id: nil)
|
||||
end
|
||||
|
||||
let!(:merge_request_context_commit_diff_file_3) do
|
||||
merge_request_context_commit_diff_files.create!(merge_request_context_commit_id: merge_request_context_commit3.id,
|
||||
relative_order: 0, sha: commit, new_file: true, renamed_file: false, deleted_file: true,
|
||||
too_large: false, a_mode: 100500, b_mode: 100755, new_path: 'new_path', old_path: 'old_path', project_id: nil)
|
||||
end
|
||||
|
||||
let!(:merge_request_context_commit_diff_file_4) do
|
||||
merge_request_context_commit_diff_files.create!(merge_request_context_commit_id: merge_request_context_commit4.id,
|
||||
relative_order: 0, sha: commit, new_file: true, renamed_file: false, deleted_file: true, too_large: false,
|
||||
a_mode: 100500, b_mode: 100755, new_path: 'new_path', old_path: 'old_path', project_id: project4.id)
|
||||
end
|
||||
end
|
||||
|
||||
include_context 'for database tables'
|
||||
include_context 'for namespaces'
|
||||
include_context 'for projects'
|
||||
include_context 'for merge requests'
|
||||
include_context 'for merge requests context diff and commits'
|
||||
|
||||
describe '#perform' do
|
||||
it 'backfills merge_request_context_commit_diff_files.project_id correctly for relevant records' do
|
||||
migration.perform
|
||||
|
||||
expect(merge_request_context_commit_diff_file_1.reload.project_id).to eq(merge_request_context_commit1.project_id)
|
||||
expect(merge_request_context_commit_diff_file_2.reload.project_id).to eq(merge_request_context_commit2.project_id)
|
||||
expect(merge_request_context_commit_diff_file_3.reload.project_id).to eq(merge_request_context_commit3.project_id)
|
||||
end
|
||||
|
||||
it 'does not update merge_request_context_commit_diff_files with pre-existing project_id' do
|
||||
expect { migration.perform }
|
||||
.not_to change { merge_request_context_commit_diff_file_4.reload.project_id }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require_migration!
|
||||
|
||||
RSpec.describe QueueBackfillMergeRequestContextCommitDiffFilesProjectId, feature_category: :code_review_workflow do
|
||||
let!(:batched_migration) { described_class::MIGRATION }
|
||||
|
||||
it 'schedules a new batched migration' do
|
||||
reversible_migration do |migration|
|
||||
migration.before -> {
|
||||
expect(batched_migration).not_to have_scheduled_batched_migration
|
||||
}
|
||||
|
||||
migration.after -> {
|
||||
expect(batched_migration).to have_scheduled_batched_migration(
|
||||
table_name: :merge_request_context_commit_diff_files,
|
||||
column_name: :merge_request_context_commit_id,
|
||||
interval: described_class::DELAY_INTERVAL,
|
||||
batch_size: described_class::BATCH_SIZE,
|
||||
sub_batch_size: described_class::SUB_BATCH_SIZE,
|
||||
gitlab_schema: :gitlab_main_cell,
|
||||
job_arguments: [
|
||||
:project_id,
|
||||
:merge_request_context_commits,
|
||||
:project_id,
|
||||
:merge_request_context_commit_id
|
||||
]
|
||||
)
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -396,6 +396,24 @@ RSpec.describe API::ProjectSnippets, :aggregate_failures, feature_category: :sou
|
|||
expect(json_response['message']).to eq('404 Snippet Not Found')
|
||||
end
|
||||
|
||||
context "when destruction fails" do
|
||||
let(:error_message) { "some service error message" }
|
||||
let(:error_response) { ServiceResponse.error(message: error_message, reason: :bad_request) }
|
||||
|
||||
before do
|
||||
allow_next_instance_of(::Snippets::DestroyService) do |service|
|
||||
allow(service).to receive(:execute).and_return(error_response)
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns an error when DestroyService fails' do
|
||||
delete api(path, admin, admin_mode: true)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:bad_request)
|
||||
expect(json_response['message']).to eq({ "error" => error_message })
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like '412 response' do
|
||||
subject(:request) { api(path, admin, admin_mode: true) }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -546,6 +546,24 @@ RSpec.describe API::Snippets, :aggregate_failures, factory_default: :keep, featu
|
|||
expect(json_response['message']).to eq('404 Snippet Not Found')
|
||||
end
|
||||
|
||||
context "when destruction fails" do
|
||||
let(:error_message) { "some service error message" }
|
||||
let(:error_response) { ServiceResponse.error(message: error_message, reason: :bad_request) }
|
||||
|
||||
before do
|
||||
allow_next_instance_of(::Snippets::DestroyService) do |service|
|
||||
allow(service).to receive(:execute).and_return(error_response)
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns an error when DestroyService fails' do
|
||||
delete api("/snippets/#{public_snippet.id}", personal_access_token: user_token)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:bad_request)
|
||||
expect(json_response['message']).to eq({ "error" => error_message })
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like '412 response' do
|
||||
let(:request) { api("/snippets/#{public_snippet.id}", personal_access_token: user_token) }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ RSpec.describe Snippets::DestroyService, feature_category: :source_code_manageme
|
|||
|
||||
it 'returns a ServiceResponse error' do
|
||||
expect(subject).to be_error
|
||||
expect(subject.reason).to eq(404)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -28,6 +29,17 @@ RSpec.describe Snippets::DestroyService, feature_category: :source_code_manageme
|
|||
end
|
||||
end
|
||||
|
||||
shared_examples 'an unauthorized destroy' do
|
||||
it 'does not delete the snippet' do
|
||||
expect { subject }.not_to change { Snippet.count }
|
||||
end
|
||||
|
||||
it 'returns ServiceResponse error' do
|
||||
expect(subject).to be_error
|
||||
expect(subject.reason).to eq(403)
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'an unsuccessful destroy' do
|
||||
it 'does not delete the snippet' do
|
||||
expect { subject }.not_to change { Snippet.count }
|
||||
|
|
@ -35,6 +47,7 @@ RSpec.describe Snippets::DestroyService, feature_category: :source_code_manageme
|
|||
|
||||
it 'returns ServiceResponse error' do
|
||||
expect(subject).to be_error
|
||||
expect(subject.reason).to eq(400)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -116,7 +129,7 @@ RSpec.describe Snippets::DestroyService, feature_category: :source_code_manageme
|
|||
context 'when user is not able to admin_project_snippet' do
|
||||
let(:author) { other_user }
|
||||
|
||||
it_behaves_like 'an unsuccessful destroy'
|
||||
it_behaves_like 'an unauthorized destroy'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -139,7 +152,7 @@ RSpec.describe Snippets::DestroyService, feature_category: :source_code_manageme
|
|||
context 'when user is not able to admin_personal_snippet' do
|
||||
let(:author) { other_user }
|
||||
|
||||
it_behaves_like 'an unsuccessful destroy'
|
||||
it_behaves_like 'an unauthorized destroy'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue