Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
533fed8bd8
commit
24ed1c84da
|
|
@ -1465,15 +1465,6 @@ Layout/ArgumentAlignment:
|
|||
- 'spec/lib/gitlab/data_builder/push_spec.rb'
|
||||
- 'spec/lib/gitlab/database/migration_helpers_spec.rb'
|
||||
- 'spec/lib/gitlab/dependency_linker/parser/gemfile_spec.rb'
|
||||
- 'spec/lib/gitlab/diff/file_collection/compare_spec.rb'
|
||||
- 'spec/lib/gitlab/diff/file_collection/merge_request_diff_batch_spec.rb'
|
||||
- 'spec/lib/gitlab/diff/file_collection/paginated_merge_request_diff_spec.rb'
|
||||
- 'spec/lib/gitlab/diff/file_spec.rb'
|
||||
- 'spec/lib/gitlab/diff/highlight_cache_spec.rb'
|
||||
- 'spec/lib/gitlab/diff/line_spec.rb'
|
||||
- 'spec/lib/gitlab/diff/suggestion_diff_spec.rb'
|
||||
- 'spec/lib/gitlab/diff/suggestion_spec.rb'
|
||||
- 'spec/lib/gitlab/diff/suggestions_parser_spec.rb'
|
||||
- 'spec/lib/gitlab/email/hook/delivery_metrics_observer_spec.rb'
|
||||
- 'spec/lib/gitlab/email/hook/smime_signature_interceptor_spec.rb'
|
||||
- 'spec/lib/gitlab/error_tracking/processor/context_payload_processor_spec.rb'
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import {
|
|||
GlFormGroup,
|
||||
GlFormTextarea,
|
||||
GlButton,
|
||||
GlSprintf,
|
||||
GlFormRadio,
|
||||
GlFormRadioGroup,
|
||||
} from '@gitlab/ui';
|
||||
|
|
@ -56,6 +57,7 @@ export default {
|
|||
GlIcon,
|
||||
GlLink,
|
||||
GlButton,
|
||||
GlSprintf,
|
||||
GlFormInput,
|
||||
GlFormTextarea,
|
||||
GlFormGroup,
|
||||
|
|
@ -91,6 +93,9 @@ export default {
|
|||
projectDescription: {
|
||||
default: '',
|
||||
},
|
||||
projectDefaultBranch: {
|
||||
default: '',
|
||||
},
|
||||
projectVisibility: {
|
||||
default: '',
|
||||
},
|
||||
|
|
@ -116,6 +121,7 @@ export default {
|
|||
required: false,
|
||||
skipValidation: true,
|
||||
}),
|
||||
branches: initFormField({ value: '', required: true, skipValidation: true }),
|
||||
visibility: initFormField({ value: null }),
|
||||
},
|
||||
};
|
||||
|
|
@ -168,6 +174,18 @@ export default {
|
|||
|
||||
return allowedLevels;
|
||||
},
|
||||
branchesOptions() {
|
||||
return [
|
||||
{
|
||||
text: s__('ForkProject|All branches'),
|
||||
value: '',
|
||||
},
|
||||
{
|
||||
text: s__(`ForkProject|Only the default branch %{defaultBranch}`),
|
||||
value: this.projectDefaultBranch,
|
||||
},
|
||||
];
|
||||
},
|
||||
visibilityLevels() {
|
||||
return [
|
||||
{
|
||||
|
|
@ -245,7 +263,7 @@ export default {
|
|||
this.form.showValidation = false;
|
||||
|
||||
const { projectId } = this;
|
||||
const { name, slug, description, visibility, namespace } = this.form.fields;
|
||||
const { name, slug, description, branches, visibility, namespace } = this.form.fields;
|
||||
|
||||
const postParams = {
|
||||
id: projectId,
|
||||
|
|
@ -253,6 +271,7 @@ export default {
|
|||
namespace_id: namespace.value.id,
|
||||
path: slug.value,
|
||||
description: description.value,
|
||||
branches: branches.value,
|
||||
visibility: visibility.value,
|
||||
};
|
||||
|
||||
|
|
@ -263,6 +282,7 @@ export default {
|
|||
const { data } = await axios.post(url, postParams);
|
||||
redirectTo(data.web_url); // eslint-disable-line import/no-deprecated
|
||||
} catch (error) {
|
||||
this.isSaving = false;
|
||||
createAlert({
|
||||
message: s__(
|
||||
'ForkProject|An error occurred while forking the project. Please try again.',
|
||||
|
|
@ -348,6 +368,34 @@ export default {
|
|||
/>
|
||||
</gl-form-group>
|
||||
|
||||
<gl-form-group>
|
||||
<label>
|
||||
{{ s__('ForkProject|Branches to include') }}
|
||||
</label>
|
||||
<gl-form-radio-group
|
||||
v-model="form.fields.branches.value"
|
||||
data-testid="fork-branches-radio-group"
|
||||
name="branches"
|
||||
:aria-label="__('branches')"
|
||||
required
|
||||
>
|
||||
<gl-form-radio
|
||||
v-for="{ text, value } in branchesOptions"
|
||||
:key="value"
|
||||
:value="value"
|
||||
:data-testid="`radio-${value}`"
|
||||
>
|
||||
<div>
|
||||
<gl-sprintf :message="text">
|
||||
<template #defaultBranch>
|
||||
<code class="gl-ml-2">{{ projectDefaultBranch }}</code>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</div>
|
||||
</gl-form-radio>
|
||||
</gl-form-radio-group>
|
||||
</gl-form-group>
|
||||
|
||||
<gl-form-group
|
||||
v-validation:[form.showValidation]
|
||||
:invalid-feedback="s__('ForkProject|Please select a visibility level')"
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ const {
|
|||
projectId,
|
||||
projectName,
|
||||
projectPath,
|
||||
projectDefaultBranch,
|
||||
projectDescription,
|
||||
projectVisibility,
|
||||
restrictedVisibilityLevels,
|
||||
|
|
@ -38,6 +39,7 @@ new Vue({
|
|||
projectName,
|
||||
projectPath,
|
||||
projectDescription,
|
||||
projectDefaultBranch,
|
||||
projectVisibility,
|
||||
restrictedVisibilityLevels: JSON.parse(restrictedVisibilityLevels),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import {
|
|||
sprintfWorkItem,
|
||||
I18N_WORK_ITEM_ERROR_UPDATING,
|
||||
TRACKING_CATEGORY_SHOW,
|
||||
WORK_ITEM_TITLE_MAX_LENGTH,
|
||||
I18N_MAX_CHARS_IN_WORK_ITEM_TITLE_MESSAGE,
|
||||
} from '../constants';
|
||||
import { getUpdateWorkItemMutation } from './update_work_item';
|
||||
import ItemTitle from './item_title.vue';
|
||||
|
|
@ -56,6 +58,11 @@ export default {
|
|||
return;
|
||||
}
|
||||
|
||||
if (updatedTitle.length > WORK_ITEM_TITLE_MAX_LENGTH) {
|
||||
this.$emit('error', sprintfWorkItem(I18N_MAX_CHARS_IN_WORK_ITEM_TITLE_MESSAGE));
|
||||
return;
|
||||
}
|
||||
|
||||
const input = {
|
||||
id: this.workItemId,
|
||||
title: updatedTitle,
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ export const WORK_ITEM_TYPE_VALUE_REQUIREMENTS = 'Requirements';
|
|||
export const WORK_ITEM_TYPE_VALUE_KEY_RESULT = 'Key Result';
|
||||
export const WORK_ITEM_TYPE_VALUE_OBJECTIVE = 'Objective';
|
||||
|
||||
export const WORK_ITEM_TITLE_MAX_LENGTH = 255;
|
||||
|
||||
export const i18n = {
|
||||
fetchErrorTitle: s__('WorkItem|Work item not found'),
|
||||
fetchError: s__(
|
||||
|
|
@ -108,6 +110,11 @@ export const I18N_WORK_ITEM_ERROR_COPY_EMAIL = s__(
|
|||
'WorkItem|Something went wrong while copying the %{workItemType} email address. Please try again.',
|
||||
);
|
||||
|
||||
export const I18N_MAX_CHARS_IN_WORK_ITEM_TITLE_MESSAGE = sprintf(
|
||||
s__('WorkItem|Title cannot have more than %{WORK_ITEM_TITLE_MAX_LENGTH} characters.'),
|
||||
{ WORK_ITEM_TITLE_MAX_LENGTH },
|
||||
);
|
||||
|
||||
export const I18N_WORK_ITEM_COPY_CREATE_NOTE_EMAIL = s__(
|
||||
'WorkItem|Copy %{workItemType} email address',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1444,12 +1444,10 @@ class Project < ApplicationRecord
|
|||
end
|
||||
|
||||
def build_or_assign_import_data(data: nil, credentials: nil)
|
||||
return if data.nil? && credentials.nil?
|
||||
|
||||
project_import_data = import_data || build_import_data
|
||||
|
||||
project_import_data.merge_data(data.to_h)
|
||||
project_import_data.merge_credentials(credentials.to_h)
|
||||
project_import_data.merge_data(data.to_h) if data
|
||||
project_import_data.merge_credentials(credentials.to_h) if credentials
|
||||
|
||||
project_import_data
|
||||
end
|
||||
|
|
|
|||
|
|
@ -17,6 +17,10 @@ module Projects
|
|||
@valid_fork_targets ||= ForkTargetsFinder.new(@project, current_user).execute(options)
|
||||
end
|
||||
|
||||
def valid_fork_branch?(branch)
|
||||
@project.repository.branch_exists?(branch)
|
||||
end
|
||||
|
||||
def valid_fork_target?(namespace = target_namespace)
|
||||
return true if current_user.admin?
|
||||
|
||||
|
|
@ -68,7 +72,8 @@ module Projects
|
|||
external_authorization_classification_label: @project.external_authorization_classification_label,
|
||||
suggestion_commit_message: @project.suggestion_commit_message,
|
||||
merge_commit_template: @project.merge_commit_template,
|
||||
squash_commit_template: @project.squash_commit_template
|
||||
squash_commit_template: @project.squash_commit_template,
|
||||
import_data: { data: { fork_branch: branch } }
|
||||
}
|
||||
|
||||
if @project.avatar.present? && @project.avatar.image?
|
||||
|
|
@ -145,6 +150,12 @@ module Projects
|
|||
def stream_audit_event(forked_project)
|
||||
# Defined in EE
|
||||
end
|
||||
|
||||
def branch
|
||||
# We extract branch name from @params[:branches] because the front end
|
||||
# insists on sending it as 'branches'.
|
||||
@params[:branches]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -15,5 +15,5 @@
|
|||
.form-group
|
||||
= f.label :gitlab_shell_operation_limit, s_('ShellOperations|Maximum number of Git operations per minute'), class: 'gl-font-bold'
|
||||
= f.number_field :gitlab_shell_operation_limit, class: 'form-control gl-form-input'
|
||||
|
||||
%span.form-text.text-muted= _('Set to 0 to disable the limit.')
|
||||
= f.submit _('Save changes'), pajamas_button: true
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@
|
|||
= form_errors(@application_setting)
|
||||
|
||||
%fieldset
|
||||
= html_escape(_("Set any rate limit to %{code_open}0%{code_close} to disable the limit.")) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
|
||||
|
||||
= html_escape(_("Set to 0 to disable the limits."))
|
||||
|
||||
%fieldset
|
||||
.form-group
|
||||
|
|
|
|||
|
|
@ -11,16 +11,16 @@
|
|||
= f.label :raw_blob_request_limit, _('Raw blob request rate limit per minute'), class: 'label-bold'
|
||||
= f.number_field :raw_blob_request_limit, class: 'form-control gl-form-input'
|
||||
.form-text.text-muted
|
||||
= _('Maximum number of requests per minute for each raw path (default is `300`). Set to `0` to disable throttling.')
|
||||
= _('Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling.')
|
||||
.form-group
|
||||
= f.label :push_event_hooks_limit, class: 'label-bold'
|
||||
= f.number_field :push_event_hooks_limit, class: 'form-control gl-form-input'
|
||||
.form-text.text-muted
|
||||
= _('Maximum number of changes (branches or tags) in a single push above which webhooks and integrations are not triggered (default is `3`). Setting to `0` does not disable throttling.')
|
||||
= _('Maximum number of changes (branches or tags) in a single push above which webhooks and integrations are not triggered (default is 3). Setting to 0 does not disable throttling.')
|
||||
.form-group
|
||||
= f.label :push_event_activities_limit, class: 'label-bold'
|
||||
= f.number_field :push_event_activities_limit, class: 'form-control gl-form-input'
|
||||
.form-text.text-muted
|
||||
= _('Maximum number of changes (branches or tags) in a single push above which a bulk push event is created (default is `3`). Setting to `0` does not disable throttling.')
|
||||
= _('Maximum number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3). Setting to 0 does not disable throttling.')
|
||||
|
||||
= f.submit _('Save changes'), pajamas_button: true
|
||||
|
|
|
|||
|
|
@ -16,6 +16,6 @@
|
|||
= f.label :projects_api_rate_limit_unauthenticated, _('Maximum requests per 10 minutes per IP address'), class: 'label-bold'
|
||||
= f.number_field :projects_api_rate_limit_unauthenticated, class: 'form-control gl-form-input'
|
||||
.form-text.gl-text-gray-600
|
||||
= _("Set this number to 0 to disable the limit.")
|
||||
= _("Set to 0 to disable the limit.")
|
||||
|
||||
= f.submit _('Save changes'), data: { qa_selector: 'save_changes_button' }, pajamas_button: true
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
project_id: @project.id,
|
||||
project_name: @project.name,
|
||||
project_path: @project.path,
|
||||
project_default_branch: @project.default_branch,
|
||||
project_description: @project.description,
|
||||
project_visibility: @project.visibility,
|
||||
restricted_visibility_levels: Gitlab::CurrentSettings.restricted_visibility_levels.to_json } }
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
class RepositoryForkWorker # rubocop:disable Scalability/IdempotentWorker
|
||||
include ApplicationWorker
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
|
||||
data_consistency :always
|
||||
|
||||
|
|
@ -12,10 +13,8 @@ class RepositoryForkWorker # rubocop:disable Scalability/IdempotentWorker
|
|||
feature_category :source_code_management
|
||||
|
||||
def perform(*args)
|
||||
target_project_id = args.shift
|
||||
target_project = Project.find(target_project_id)
|
||||
@target_project_id = args.shift
|
||||
|
||||
source_project = target_project.forked_from_project
|
||||
unless source_project
|
||||
return target_project.import_state.mark_as_failed(_('Source project cannot be found.'))
|
||||
end
|
||||
|
|
@ -25,6 +24,21 @@ class RepositoryForkWorker # rubocop:disable Scalability/IdempotentWorker
|
|||
|
||||
private
|
||||
|
||||
def target_project
|
||||
Project.find(@target_project_id)
|
||||
end
|
||||
strong_memoize_attr :target_project
|
||||
|
||||
def source_project
|
||||
@source_project ||= target_project.forked_from_project
|
||||
end
|
||||
|
||||
def branch
|
||||
return unless target_project.import_data&.data
|
||||
|
||||
target_project.import_data.data['fork_branch']
|
||||
end
|
||||
|
||||
def fork_repository(target_project, source_project)
|
||||
return unless start_fork(target_project)
|
||||
|
||||
|
|
@ -46,7 +60,7 @@ class RepositoryForkWorker # rubocop:disable Scalability/IdempotentWorker
|
|||
source_repo = source_project.repository.raw
|
||||
target_repo = target_project.repository.raw
|
||||
|
||||
::Gitlab::GitalyClient::RepositoryService.new(target_repo).fork_repository(source_repo)
|
||||
::Gitlab::GitalyClient::RepositoryService.new(target_repo).fork_repository(source_repo, branch)
|
||||
rescue GRPC::BadStatus => e
|
||||
Gitlab::ErrorTracking.track_exception(e, source_project_id: source_project.id, target_project_id: target_project.id)
|
||||
|
||||
|
|
|
|||
|
|
@ -11,3 +11,7 @@ description: Storing namespaces records for groups, users and projects
|
|||
introduced_by_url: https://github.com/gitlabhq/gitlabhq/pull/2051
|
||||
milestone: "<6.0"
|
||||
gitlab_schema: gitlab_main_cell
|
||||
schema_inconsistencies:
|
||||
- type: missing_indexes
|
||||
object_name: index_namespaces_on_created_at
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/134948
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class DropIndexNamespacesOnCreatedAtForGitlabCom < Gitlab::Database::Migration[2.1]
|
||||
disable_ddl_transaction!
|
||||
|
||||
TABLE_NAME = :namespaces
|
||||
INDEX_NAME = :index_namespaces_on_created_at
|
||||
|
||||
def up
|
||||
return unless should_run?
|
||||
|
||||
remove_concurrent_index_by_name TABLE_NAME, INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
return unless should_run?
|
||||
|
||||
add_concurrent_index TABLE_NAME, :created_at, name: INDEX_NAME
|
||||
end
|
||||
|
||||
def should_run?
|
||||
Gitlab.com_except_jh?
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class DropProjectSettingsJitsuKey < Gitlab::Database::Migration[2.2]
|
||||
milestone '16.6'
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
with_lock_retries do
|
||||
remove_column :project_settings, :jitsu_key, if_exists: true
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
with_lock_retries do
|
||||
add_column :project_settings, :jitsu_key, :text, if_not_exists: true
|
||||
end
|
||||
|
||||
add_text_limit :project_settings, :jitsu_key, 100
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
8ad5065584f72084ee929e479725593330d0d13542dc4939476d62f831c6f2e8
|
||||
|
|
@ -0,0 +1 @@
|
|||
dc0065c2caffdf5bbf79c1e94f8bdb6d415a836cc575109d25df8217423be0e1
|
||||
|
|
@ -21829,7 +21829,6 @@ CREATE TABLE project_settings (
|
|||
selective_code_owner_removals boolean DEFAULT false NOT NULL,
|
||||
issue_branch_template text,
|
||||
show_diff_preview_in_email boolean DEFAULT true NOT NULL,
|
||||
jitsu_key text,
|
||||
suggested_reviewers_enabled boolean DEFAULT false NOT NULL,
|
||||
only_allow_merge_if_all_status_checks_passed boolean DEFAULT false NOT NULL,
|
||||
mirror_branch_regex text,
|
||||
|
|
@ -21847,7 +21846,6 @@ CREATE TABLE project_settings (
|
|||
encrypted_product_analytics_configurator_connection_string_iv bytea,
|
||||
pages_multiple_versions_enabled boolean DEFAULT false NOT NULL,
|
||||
CONSTRAINT check_1a30456322 CHECK ((char_length(pages_unique_domain) <= 63)),
|
||||
CONSTRAINT check_2981f15877 CHECK ((char_length(jitsu_key) <= 100)),
|
||||
CONSTRAINT check_3a03e7557a CHECK ((char_length(previous_default_branch) <= 4096)),
|
||||
CONSTRAINT check_3ca5cbffe6 CHECK ((char_length(issue_branch_template) <= 255)),
|
||||
CONSTRAINT check_4b142e71f3 CHECK ((char_length(product_analytics_data_collector_host) <= 255)),
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ POST /projects/:id/ci/lint
|
|||
| `content` | string | Yes | The CI/CD configuration content. |
|
||||
| `dry_run` | boolean | No | Run [pipeline creation simulation](../ci/lint.md#simulate-a-pipeline), or only do static check. Default: `false`. |
|
||||
| `include_jobs` | boolean | No | If the list of jobs that would exist in a static check or pipeline simulation should be included in the response. Default: `false`. |
|
||||
| `ref` | string | No | When `dry_run` is `true`, sets the branch or tag to use. Defaults to the project's default branch when not set. |
|
||||
| `ref` | string | No | When `dry_run` is `true`, sets the branch or tag context to use to validate the CI/CD YAML configuration. Defaults to the project's default branch when not set. |
|
||||
|
||||
Example request:
|
||||
|
||||
|
|
@ -71,7 +71,7 @@ GET /projects/:id/ci/lint
|
|||
|----------------|---------|----------|-------------|
|
||||
| `dry_run` | boolean | No | Run pipeline creation simulation, or only do static check. |
|
||||
| `include_jobs` | boolean | No | If the list of jobs that would exist in a static check or pipeline simulation should be included in the response. Default: `false`. |
|
||||
| `ref` | string | No | When `dry_run` is `true`, sets the branch or tag to use. Defaults to the project's default branch when not set. |
|
||||
| `ref` | string | No | When `dry_run` is `true`, sets the branch or tag context to use to validate the CI/CD YAML configuration. Defaults to the project's default branch when not set. |
|
||||
| `sha` | string | No | The commit SHA of a branch or tag. Defaults to the SHA of the head of the project's default branch when not set. |
|
||||
|
||||
Example request:
|
||||
|
|
|
|||
|
|
@ -1794,6 +1794,7 @@ POST /projects/:id/fork
|
|||
| `namespace` | integer or string | No | _(Deprecated)_ The ID or path of the namespace that the project is forked to. |
|
||||
| `path` | string | No | The path assigned to the resultant project after forking. |
|
||||
| `visibility` | string | No | The [visibility level](#project-visibility-level) assigned to the resultant project after forking. |
|
||||
| `branches` | string | No | Branches to fork (empty for all branches). |
|
||||
|
||||
## List forks of a project
|
||||
|
||||
|
|
|
|||
|
|
@ -470,6 +470,7 @@ module API
|
|||
optional :description, type: String, desc: 'The description that will be assigned to the fork', documentation: { example: 'Description' }
|
||||
optional :visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The visibility of the fork'
|
||||
optional :mr_default_target_self, type: Boolean, desc: 'Merge requests of this forked project targets itself by default'
|
||||
optional :branches, type: String, desc: 'Branches to fork'
|
||||
end
|
||||
post ':id/fork', feature_category: :source_code_management do
|
||||
Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20759')
|
||||
|
|
@ -489,6 +490,7 @@ module API
|
|||
|
||||
service = ::Projects::ForkService.new(user_project, current_user, fork_params)
|
||||
|
||||
not_found!('Source Branch') if fork_params[:branches].present? && !service.valid_fork_branch?(fork_params[:branches])
|
||||
not_found!('Target Namespace') unless service.valid_fork_target?
|
||||
|
||||
forked_project = service.execute
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
variables:
|
||||
AUTO_BUILD_IMAGE_VERSION: 'v1.44.0'
|
||||
AUTO_BUILD_IMAGE_VERSION: 'v1.46.0'
|
||||
|
||||
build:
|
||||
stage: build
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
variables:
|
||||
AUTO_BUILD_IMAGE_VERSION: 'v1.44.0'
|
||||
AUTO_BUILD_IMAGE_VERSION: 'v1.46.0'
|
||||
|
||||
build:
|
||||
stage: build
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ module Gitlab
|
|||
'_test_gitlab_main_cell_' => :gitlab_main_cell,
|
||||
'_test_gitlab_main_' => :gitlab_main,
|
||||
'_test_gitlab_ci_' => :gitlab_ci,
|
||||
'_test_gitlab_jh_' => :gitlab_jh,
|
||||
'_test_gitlab_embedding_' => :gitlab_embedding,
|
||||
'_test_gitlab_geo_' => :gitlab_geo,
|
||||
'_test_gitlab_pm_' => :gitlab_pm,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
module Gitlab
|
||||
module Database
|
||||
class TablesLocker
|
||||
GITLAB_SCHEMAS_TO_IGNORE = %i[gitlab_embedding gitlab_geo].freeze
|
||||
GITLAB_SCHEMAS_TO_IGNORE = %i[gitlab_embedding gitlab_geo gitlab_jh].freeze
|
||||
|
||||
def initialize(logger: nil, dry_run: false, include_partitions: true)
|
||||
@logger = logger
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
module Gitlab
|
||||
module Database
|
||||
class TablesTruncate
|
||||
GITLAB_SCHEMAS_TO_IGNORE = %i[gitlab_geo gitlab_embedding].freeze
|
||||
GITLAB_SCHEMAS_TO_IGNORE = %i[gitlab_geo gitlab_embedding gitlab_jh].freeze
|
||||
|
||||
def initialize(database_name:, min_batch_size: 5, logger: nil, until_table: nil, dry_run: false)
|
||||
@database_name = database_name
|
||||
|
|
|
|||
|
|
@ -136,10 +136,13 @@ module Gitlab
|
|||
response.base.presence
|
||||
end
|
||||
|
||||
def fork_repository(source_repository)
|
||||
def fork_repository(source_repository, branch = nil)
|
||||
revision = branch.present? ? "refs/heads/#{branch}" : ""
|
||||
|
||||
request = Gitaly::CreateForkRequest.new(
|
||||
repository: @gitaly_repo,
|
||||
source_repository: source_repository.gitaly_repository
|
||||
source_repository: source_repository.gitaly_repository,
|
||||
revision: revision
|
||||
)
|
||||
|
||||
gitaly_client_call(
|
||||
|
|
|
|||
|
|
@ -20861,9 +20861,15 @@ msgstr ""
|
|||
msgid "ForkProject|A fork is a copy of a project."
|
||||
msgstr ""
|
||||
|
||||
msgid "ForkProject|All branches"
|
||||
msgstr ""
|
||||
|
||||
msgid "ForkProject|An error occurred while forking the project. Please try again."
|
||||
msgstr ""
|
||||
|
||||
msgid "ForkProject|Branches to include"
|
||||
msgstr ""
|
||||
|
||||
msgid "ForkProject|Cancel"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -20879,6 +20885,9 @@ msgstr ""
|
|||
msgid "ForkProject|Internal"
|
||||
msgstr ""
|
||||
|
||||
msgid "ForkProject|Only the default branch %{defaultBranch}"
|
||||
msgstr ""
|
||||
|
||||
msgid "ForkProject|Please select a namespace"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -29147,10 +29156,10 @@ msgstr ""
|
|||
msgid "Maximum number of %{name} (%{count}) exceeded"
|
||||
msgstr ""
|
||||
|
||||
msgid "Maximum number of changes (branches or tags) in a single push above which a bulk push event is created (default is `3`). Setting to `0` does not disable throttling."
|
||||
msgid "Maximum number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3). Setting to 0 does not disable throttling."
|
||||
msgstr ""
|
||||
|
||||
msgid "Maximum number of changes (branches or tags) in a single push above which webhooks and integrations are not triggered (default is `3`). Setting to `0` does not disable throttling."
|
||||
msgid "Maximum number of changes (branches or tags) in a single push above which webhooks and integrations are not triggered (default is 3). Setting to 0 does not disable throttling."
|
||||
msgstr ""
|
||||
|
||||
msgid "Maximum number of comments exceeded"
|
||||
|
|
@ -29171,7 +29180,7 @@ msgstr ""
|
|||
msgid "Maximum number of requests per minute for an unauthenticated IP address"
|
||||
msgstr ""
|
||||
|
||||
msgid "Maximum number of requests per minute for each raw path (default is `300`). Set to `0` to disable throttling."
|
||||
msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
|
||||
msgstr ""
|
||||
|
||||
msgid "Maximum number of stages per value stream exceeded"
|
||||
|
|
@ -44247,9 +44256,6 @@ msgstr ""
|
|||
msgid "Set a password on your account to pull or push via %{protocol}."
|
||||
msgstr ""
|
||||
|
||||
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
|
||||
msgstr ""
|
||||
|
||||
msgid "Set due date"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -44355,6 +44361,12 @@ msgstr ""
|
|||
msgid "Set to 0 for no size limit."
|
||||
msgstr ""
|
||||
|
||||
msgid "Set to 0 to disable the limit."
|
||||
msgstr ""
|
||||
|
||||
msgid "Set to 0 to disable the limits."
|
||||
msgstr ""
|
||||
|
||||
msgid "Set to 0 to disable timeout."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -54394,6 +54406,9 @@ msgstr ""
|
|||
msgid "WorkItem|This work item is not available. It either doesn't exist or you don't have permission to view it."
|
||||
msgstr ""
|
||||
|
||||
msgid "WorkItem|Title cannot have more than %{WORK_ITEM_TITLE_MAX_LENGTH} characters."
|
||||
msgstr ""
|
||||
|
||||
msgid "WorkItem|Turn off confidentiality"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -55922,6 +55937,9 @@ msgstr[1] ""
|
|||
msgid "branch name"
|
||||
msgstr ""
|
||||
|
||||
msgid "branches"
|
||||
msgstr ""
|
||||
|
||||
msgid "builds"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ module RuboCop
|
|||
swap_foreign_keys
|
||||
swap_indexes
|
||||
reset_trigger_function
|
||||
cleanup_conversion_of_integer_to_bigint
|
||||
revert_initialize_conversion_of_integer_to_bigint
|
||||
].sort.freeze
|
||||
|
||||
MSG = "The method is not allowed to be called within the `with_lock_retries` block, the only allowed methods are: #{ALLOWED_MIGRATION_METHODS.join(', ')}".freeze
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ RSpec.shared_examples 'validate dictionary' do |objects, directory_path, require
|
|||
introduced_by_url
|
||||
milestone
|
||||
gitlab_schema
|
||||
schema_inconsistencies
|
||||
]
|
||||
end
|
||||
|
||||
|
|
@ -169,7 +170,7 @@ RSpec.shared_examples 'validate dictionary' do |objects, directory_path, require
|
|||
end
|
||||
|
||||
RSpec.describe 'Views documentation', feature_category: :database do
|
||||
database_base_models = Gitlab::Database.database_base_models.select { |k, _| k != 'geo' }
|
||||
database_base_models = Gitlab::Database.database_base_models.select { |k, _| %w[geo jh].exclude?(k) }
|
||||
views = database_base_models.flat_map { |_, m| m.connection.views }.sort.uniq
|
||||
directory_path = File.join('db', 'docs', 'views')
|
||||
required_fields = %i[feature_categories view_name gitlab_schema]
|
||||
|
|
@ -178,7 +179,7 @@ RSpec.describe 'Views documentation', feature_category: :database do
|
|||
end
|
||||
|
||||
RSpec.describe 'Tables documentation', feature_category: :database do
|
||||
database_base_models = Gitlab::Database.database_base_models.select { |k, _| k != 'geo' }
|
||||
database_base_models = Gitlab::Database.database_base_models.select { |k, _| %w[geo jh].exclude?(k) }
|
||||
tables = database_base_models.flat_map { |_, m| m.connection.tables }.sort.uniq
|
||||
directory_path = File.join('db', 'docs')
|
||||
required_fields = %i[feature_categories table_name gitlab_schema]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,11 @@
|
|||
import { GlFormInputGroup, GlFormInput, GlForm, GlFormRadioGroup, GlFormRadio } from '@gitlab/ui';
|
||||
import {
|
||||
GlFormInputGroup,
|
||||
GlFormInput,
|
||||
GlForm,
|
||||
GlFormRadioGroup,
|
||||
GlFormRadio,
|
||||
GlSprintf,
|
||||
} from '@gitlab/ui';
|
||||
import { getByRole } from '@testing-library/dom';
|
||||
import { mount, shallowMount } from '@vue/test-utils';
|
||||
import axios from 'axios';
|
||||
|
|
@ -41,6 +48,7 @@ describe('ForkForm component', () => {
|
|||
projectPath: 'project-name',
|
||||
projectDescription: 'some project description',
|
||||
projectVisibility: 'private',
|
||||
projectDefaultBranch: 'main',
|
||||
restrictedVisibilityLevels: [],
|
||||
};
|
||||
|
||||
|
|
@ -96,6 +104,7 @@ describe('ForkForm component', () => {
|
|||
GlFormInput,
|
||||
GlFormRadioGroup,
|
||||
GlFormRadio,
|
||||
GlSprintf,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
@ -118,13 +127,13 @@ describe('ForkForm component', () => {
|
|||
const findInternalRadio = () => wrapper.find('[data-testid="radio-internal"]');
|
||||
const findPublicRadio = () => wrapper.find('[data-testid="radio-public"]');
|
||||
const findForkNameInput = () => wrapper.find('[data-testid="fork-name-input"]');
|
||||
const findGlFormRadioGroup = () => wrapper.findComponent(GlFormRadioGroup);
|
||||
const findForkUrlInput = () => wrapper.findComponent(ProjectNamespace);
|
||||
const findForkSlugInput = () => wrapper.find('[data-testid="fork-slug-input"]');
|
||||
const findForkDescriptionTextarea = () =>
|
||||
wrapper.find('[data-testid="fork-description-textarea"]');
|
||||
const findVisibilityRadioGroup = () =>
|
||||
wrapper.find('[data-testid="fork-visibility-radio-group"]');
|
||||
const findBranchesRadioGroup = () => wrapper.find('[data-testid="fork-branches-radio-group"]');
|
||||
|
||||
it('will go to cancelPath when click cancel button', () => {
|
||||
createComponent();
|
||||
|
|
@ -203,11 +212,25 @@ describe('ForkForm component', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('branches options', () => {
|
||||
const formRadios = () => findBranchesRadioGroup().findAllComponents(GlFormRadio);
|
||||
it('displays 2 branches options', () => {
|
||||
createComponent();
|
||||
expect(formRadios()).toHaveLength(2);
|
||||
});
|
||||
|
||||
it('displays the correct description for each option', () => {
|
||||
createComponent();
|
||||
expect(formRadios().at(0).text()).toBe('All branches');
|
||||
expect(formRadios().at(1).text()).toMatchInterpolatedText('Only the default branch main');
|
||||
});
|
||||
});
|
||||
|
||||
describe('visibility level', () => {
|
||||
it('displays the correct description', () => {
|
||||
createComponent();
|
||||
|
||||
const formRadios = wrapper.findAllComponents(GlFormRadio);
|
||||
const formRadios = findVisibilityRadioGroup().findAllComponents(GlFormRadio);
|
||||
|
||||
Object.keys(PROJECT_VISIBILITY_TYPE).forEach((visibilityType, index) => {
|
||||
expect(formRadios.at(index).text()).toBe(PROJECT_VISIBILITY_TYPE[visibilityType]);
|
||||
|
|
@ -217,7 +240,7 @@ describe('ForkForm component', () => {
|
|||
it('displays all 3 visibility levels', () => {
|
||||
createComponent();
|
||||
|
||||
expect(wrapper.findAllComponents(GlFormRadio)).toHaveLength(3);
|
||||
expect(findVisibilityRadioGroup().findAllComponents(GlFormRadio)).toHaveLength(3);
|
||||
});
|
||||
|
||||
describe('when the namespace is changed', () => {
|
||||
|
|
@ -236,7 +259,7 @@ describe('ForkForm component', () => {
|
|||
it('resets the visibility to max allowed below current level', async () => {
|
||||
createFullComponent({ projectVisibility: 'public' }, { namespaces });
|
||||
|
||||
expect(findGlFormRadioGroup().vm.$attrs.checked).toBe('public');
|
||||
expect(findVisibilityRadioGroup().vm.$attrs.checked).toBe('public');
|
||||
|
||||
fillForm({
|
||||
name: 'one',
|
||||
|
|
@ -251,7 +274,7 @@ describe('ForkForm component', () => {
|
|||
it('does not reset the visibility when current level is allowed', async () => {
|
||||
createFullComponent({ projectVisibility: 'public' }, { namespaces });
|
||||
|
||||
expect(findGlFormRadioGroup().vm.$attrs.checked).toBe('public');
|
||||
expect(findVisibilityRadioGroup().vm.$attrs.checked).toBe('public');
|
||||
|
||||
fillForm({
|
||||
name: 'two',
|
||||
|
|
@ -266,7 +289,7 @@ describe('ForkForm component', () => {
|
|||
it('does not reset the visibility when visibility cap is increased', async () => {
|
||||
createFullComponent({ projectVisibility: 'public' }, { namespaces });
|
||||
|
||||
expect(findGlFormRadioGroup().vm.$attrs.checked).toBe('public');
|
||||
expect(findVisibilityRadioGroup().vm.$attrs.checked).toBe('public');
|
||||
|
||||
fillForm({
|
||||
name: 'three',
|
||||
|
|
@ -291,7 +314,7 @@ describe('ForkForm component', () => {
|
|||
{ namespaces },
|
||||
);
|
||||
|
||||
await findGlFormRadioGroup().vm.$emit('input', 'internal');
|
||||
await findVisibilityRadioGroup().vm.$emit('input', 'internal');
|
||||
fillForm({
|
||||
name: 'five',
|
||||
id: 5,
|
||||
|
|
@ -469,7 +492,7 @@ describe('ForkForm component', () => {
|
|||
jest.spyOn(axios, 'post');
|
||||
|
||||
setupComponent();
|
||||
await findGlFormRadioGroup().vm.$emit('input', null);
|
||||
await findVisibilityRadioGroup().vm.$emit('input', null);
|
||||
|
||||
await nextTick();
|
||||
|
||||
|
|
@ -533,6 +556,7 @@ describe('ForkForm component', () => {
|
|||
|
||||
const url = `/api/${GON_API_VERSION}/projects/${projectId}/fork`;
|
||||
const project = {
|
||||
branches: '',
|
||||
description: projectDescription,
|
||||
id: projectId,
|
||||
name: projectName,
|
||||
|
|
|
|||
|
|
@ -131,5 +131,25 @@ describe('WorkItemTitle component', () => {
|
|||
property: 'type_Task',
|
||||
});
|
||||
});
|
||||
|
||||
describe('when title has more than 255 characters', () => {
|
||||
const title = new Array(257).join('a');
|
||||
|
||||
it('does not call a mutation', () => {
|
||||
createComponent();
|
||||
|
||||
findItemTitle().vm.$emit('title-changed', title);
|
||||
|
||||
expect(mutationSuccessHandler).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('emits an error message', () => {
|
||||
createComponent();
|
||||
|
||||
findItemTitle().vm.$emit('title-changed', title);
|
||||
|
||||
expect(wrapper.emitted('error')).toEqual([['Title cannot have more than 255 characters.']]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ RSpec.describe Admin::ComponentsHelper, feature_category: :database do
|
|||
}
|
||||
main[:ci] = { adapter_name: 'PostgreSQL', version: expected_version } if Gitlab::Database.has_config?(:ci)
|
||||
main[:geo] = { adapter_name: 'PostgreSQL', version: expected_version } if Gitlab::Database.has_config?(:geo)
|
||||
main[:jh] = { adapter_name: 'PostgreSQL', version: expected_version } if Gitlab::Database.has_config?(:jh)
|
||||
|
||||
main
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,9 +10,11 @@ RSpec.describe Gitlab::Diff::FileCollection::Compare do
|
|||
let(:start_commit) { sample_image_commit }
|
||||
let(:head_commit) { sample_commit }
|
||||
let(:raw_compare) do
|
||||
Gitlab::Git::Compare.new(project.repository.raw_repository,
|
||||
start_commit.id,
|
||||
head_commit.id)
|
||||
Gitlab::Git::Compare.new(
|
||||
project.repository.raw_repository,
|
||||
start_commit.id,
|
||||
head_commit.id
|
||||
)
|
||||
end
|
||||
|
||||
let(:diffable) { Compare.new(raw_compare, project) }
|
||||
|
|
|
|||
|
|
@ -10,10 +10,7 @@ RSpec.describe Gitlab::Diff::FileCollection::MergeRequestDiffBatch, feature_cate
|
|||
let(:diff_files_relation) { diffable.merge_request_diff_files }
|
||||
|
||||
subject do
|
||||
described_class.new(diffable,
|
||||
batch_page,
|
||||
batch_size,
|
||||
diff_options: nil)
|
||||
described_class.new(diffable, batch_page, batch_size, diff_options: nil)
|
||||
end
|
||||
|
||||
let(:diff_files) { subject.diff_files }
|
||||
|
|
@ -87,10 +84,7 @@ RSpec.describe Gitlab::Diff::FileCollection::MergeRequestDiffBatch, feature_cate
|
|||
context 'last page' do
|
||||
it 'returns correct diff files' do
|
||||
last_page = diff_files_relation.count - batch_size
|
||||
collection = described_class.new(diffable,
|
||||
last_page,
|
||||
batch_size,
|
||||
diff_options: nil)
|
||||
collection = described_class.new(diffable, last_page, batch_size, diff_options: nil)
|
||||
|
||||
expected_batch_files = diff_files_relation.offset(last_page).limit(batch_size).map(&:new_path)
|
||||
|
||||
|
|
@ -101,10 +95,7 @@ RSpec.describe Gitlab::Diff::FileCollection::MergeRequestDiffBatch, feature_cate
|
|||
|
||||
it_behaves_like 'unfoldable diff' do
|
||||
subject do
|
||||
described_class.new(merge_request.merge_request_diff,
|
||||
batch_page,
|
||||
batch_size,
|
||||
diff_options: nil)
|
||||
described_class.new(merge_request.merge_request_diff, batch_page, batch_size, diff_options: nil)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -118,10 +109,7 @@ RSpec.describe Gitlab::Diff::FileCollection::MergeRequestDiffBatch, feature_cate
|
|||
let(:stub_path) { '.gitignore' }
|
||||
|
||||
subject do
|
||||
described_class.new(merge_request.merge_request_diff,
|
||||
batch_page,
|
||||
batch_size,
|
||||
**collection_default_args)
|
||||
described_class.new(merge_request.merge_request_diff, batch_page, batch_size, **collection_default_args)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -136,10 +124,7 @@ RSpec.describe Gitlab::Diff::FileCollection::MergeRequestDiffBatch, feature_cate
|
|||
end
|
||||
|
||||
subject do
|
||||
described_class.new(merge_request.merge_request_diff,
|
||||
batch_page,
|
||||
batch_size,
|
||||
**collection_default_args)
|
||||
described_class.new(merge_request.merge_request_diff, batch_page, batch_size, **collection_default_args)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -11,9 +11,7 @@ RSpec.describe Gitlab::Diff::FileCollection::PaginatedMergeRequestDiff, feature_
|
|||
let(:diff_files) { subject.diff_files }
|
||||
|
||||
subject do
|
||||
described_class.new(diffable,
|
||||
page,
|
||||
per_page)
|
||||
described_class.new(diffable, page, per_page)
|
||||
end
|
||||
|
||||
describe '#diff_files' do
|
||||
|
|
@ -79,9 +77,7 @@ RSpec.describe Gitlab::Diff::FileCollection::PaginatedMergeRequestDiff, feature_
|
|||
context 'when last page' do
|
||||
it 'returns correct diff files' do
|
||||
last_page = diff_files_relation.count - per_page
|
||||
collection = described_class.new(diffable,
|
||||
last_page,
|
||||
per_page)
|
||||
collection = described_class.new(diffable, last_page, per_page)
|
||||
|
||||
expected_batch_files = diff_files_relation.page(last_page).per(per_page).map(&:new_path)
|
||||
|
||||
|
|
@ -92,9 +88,7 @@ RSpec.describe Gitlab::Diff::FileCollection::PaginatedMergeRequestDiff, feature_
|
|||
|
||||
it_behaves_like 'unfoldable diff' do
|
||||
subject do
|
||||
described_class.new(merge_request.merge_request_diff,
|
||||
page,
|
||||
per_page)
|
||||
described_class.new(merge_request.merge_request_diff, page, per_page)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -106,9 +100,7 @@ RSpec.describe Gitlab::Diff::FileCollection::PaginatedMergeRequestDiff, feature_
|
|||
let(:diffable) { merge_request.merge_request_diff }
|
||||
|
||||
subject do
|
||||
described_class.new(merge_request.merge_request_diff,
|
||||
page,
|
||||
per_page)
|
||||
described_class.new(merge_request.merge_request_diff, page, per_page)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -407,10 +407,7 @@ RSpec.describe Gitlab::Diff::File do
|
|||
|
||||
context 'diff file stats' do
|
||||
let(:diff_file) do
|
||||
described_class.new(diff,
|
||||
diff_refs: commit.diff_refs,
|
||||
repository: project.repository,
|
||||
stats: stats)
|
||||
described_class.new(diff, diff_refs: commit.diff_refs, repository: project.repository, stats: stats)
|
||||
end
|
||||
|
||||
let(:raw_diff) do
|
||||
|
|
|
|||
|
|
@ -49,10 +49,12 @@ RSpec.describe Gitlab::Diff::HighlightCache, :clean_gitlab_redis_cache, feature_
|
|||
let(:diff_file) do
|
||||
diffs = merge_request.diffs
|
||||
raw_diff = diffs.diffable.raw_diffs(diffs.diff_options.merge(paths: ['CHANGELOG'])).first
|
||||
Gitlab::Diff::File.new(raw_diff,
|
||||
repository: diffs.project.repository,
|
||||
diff_refs: diffs.diff_refs,
|
||||
fallback_diff_refs: diffs.fallback_diff_refs)
|
||||
Gitlab::Diff::File.new(
|
||||
raw_diff,
|
||||
repository: diffs.project.repository,
|
||||
diff_refs: diffs.diff_refs,
|
||||
fallback_diff_refs: diffs.fallback_diff_refs
|
||||
)
|
||||
end
|
||||
|
||||
before do
|
||||
|
|
@ -227,10 +229,12 @@ RSpec.describe Gitlab::Diff::HighlightCache, :clean_gitlab_redis_cache, feature_
|
|||
let(:diff_file) do
|
||||
diffs = merge_request.diffs
|
||||
raw_diff = diffs.diffable.raw_diffs(diffs.diff_options.merge(paths: ['CHANGELOG'])).first
|
||||
Gitlab::Diff::File.new(raw_diff,
|
||||
repository: diffs.project.repository,
|
||||
diff_refs: diffs.diff_refs,
|
||||
fallback_diff_refs: diffs.fallback_diff_refs)
|
||||
Gitlab::Diff::File.new(
|
||||
raw_diff,
|
||||
repository: diffs.project.repository,
|
||||
diff_refs: diffs.diff_refs,
|
||||
fallback_diff_refs: diffs.fallback_diff_refs
|
||||
)
|
||||
end
|
||||
|
||||
it "uses ActiveSupport::Gzip when reading from the cache" do
|
||||
|
|
|
|||
|
|
@ -11,10 +11,16 @@ RSpec.describe Gitlab::Diff::Line do
|
|||
end
|
||||
|
||||
let(:line) do
|
||||
described_class.new('<input>', 'match', 0, 0, 1,
|
||||
parent_file: double(:file),
|
||||
line_code: double(:line_code),
|
||||
rich_text: rich_text)
|
||||
described_class.new(
|
||||
'<input>',
|
||||
'match',
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
parent_file: double(:file),
|
||||
line_code: double(:line_code),
|
||||
rich_text: rich_text
|
||||
)
|
||||
end
|
||||
|
||||
let(:rich_text) { nil }
|
||||
|
|
|
|||
|
|
@ -22,9 +22,7 @@ RSpec.describe Gitlab::Diff::SuggestionDiff do
|
|||
end
|
||||
|
||||
let(:suggestion) do
|
||||
instance_double(Suggestion, from_line: 12,
|
||||
from_content: from_content,
|
||||
to_content: to_content)
|
||||
instance_double(Suggestion, from_line: 12, from_content: from_content, to_content: to_content)
|
||||
end
|
||||
|
||||
subject { described_class.new(suggestion).diff_lines }
|
||||
|
|
@ -56,9 +54,12 @@ RSpec.describe Gitlab::Diff::SuggestionDiff do
|
|||
it 'returns a correct value if there is no newline at the end of the file' do
|
||||
from_content = "One line test"
|
||||
to_content = "Successful test!"
|
||||
suggestion = instance_double(Suggestion, from_line: 1,
|
||||
from_content: from_content,
|
||||
to_content: to_content)
|
||||
suggestion = instance_double(
|
||||
Suggestion,
|
||||
from_line: 1,
|
||||
from_content: from_content,
|
||||
to_content: to_content
|
||||
)
|
||||
|
||||
diff_lines = described_class.new(suggestion).diff_lines
|
||||
|
||||
|
|
|
|||
|
|
@ -5,10 +5,12 @@ require 'spec_helper'
|
|||
RSpec.describe Gitlab::Diff::Suggestion do
|
||||
shared_examples 'correct suggestion raw content' do
|
||||
it 'returns correct raw data' do
|
||||
expect(suggestion.to_hash).to include(from_content: expected_lines.join,
|
||||
to_content: "#{text}\n",
|
||||
lines_above: above,
|
||||
lines_below: below)
|
||||
expect(suggestion.to_hash).to include(
|
||||
from_content: expected_lines.join,
|
||||
to_content: "#{text}\n",
|
||||
lines_above: above,
|
||||
lines_below: below
|
||||
)
|
||||
end
|
||||
|
||||
it 'returns diff lines with correct line numbers' do
|
||||
|
|
@ -25,11 +27,13 @@ RSpec.describe Gitlab::Diff::Suggestion do
|
|||
let(:merge_request) { create(:merge_request) }
|
||||
let(:project) { merge_request.project }
|
||||
let(:position) do
|
||||
Gitlab::Diff::Position.new(old_path: "files/ruby/popen.rb",
|
||||
new_path: "files/ruby/popen.rb",
|
||||
old_line: nil,
|
||||
new_line: 9,
|
||||
diff_refs: merge_request.diff_refs)
|
||||
Gitlab::Diff::Position.new(
|
||||
old_path: "files/ruby/popen.rb",
|
||||
new_path: "files/ruby/popen.rb",
|
||||
old_line: nil,
|
||||
new_line: 9,
|
||||
diff_refs: merge_request.diff_refs
|
||||
)
|
||||
end
|
||||
|
||||
let(:diff_file) do
|
||||
|
|
|
|||
|
|
@ -7,11 +7,13 @@ RSpec.describe Gitlab::Diff::SuggestionsParser do
|
|||
let(:merge_request) { create(:merge_request) }
|
||||
let(:project) { merge_request.project }
|
||||
let(:position) do
|
||||
Gitlab::Diff::Position.new(old_path: "files/ruby/popen.rb",
|
||||
new_path: "files/ruby/popen.rb",
|
||||
old_line: nil,
|
||||
new_line: 9,
|
||||
diff_refs: merge_request.diff_refs)
|
||||
Gitlab::Diff::Position.new(
|
||||
old_path: "files/ruby/popen.rb",
|
||||
new_path: "files/ruby/popen.rb",
|
||||
old_line: nil,
|
||||
new_line: 9,
|
||||
diff_refs: merge_request.diff_refs
|
||||
)
|
||||
end
|
||||
|
||||
let(:diff_file) do
|
||||
|
|
@ -19,8 +21,7 @@ RSpec.describe Gitlab::Diff::SuggestionsParser do
|
|||
end
|
||||
|
||||
subject do
|
||||
described_class.parse(markdown, project: merge_request.project,
|
||||
position: position)
|
||||
described_class.parse(markdown, project: merge_request.project, position: position)
|
||||
end
|
||||
|
||||
def blob_lines_data(from_line, to_line)
|
||||
|
|
@ -59,15 +60,19 @@ RSpec.describe Gitlab::Diff::SuggestionsParser do
|
|||
from_line = position.new_line
|
||||
to_line = position.new_line
|
||||
|
||||
expect(subject.first.to_hash).to include(from_content: blob_lines_data(from_line, to_line),
|
||||
to_content: " foo\n bar\n",
|
||||
lines_above: 0,
|
||||
lines_below: 0)
|
||||
expect(subject.first.to_hash).to include(
|
||||
from_content: blob_lines_data(from_line, to_line),
|
||||
to_content: " foo\n bar\n",
|
||||
lines_above: 0,
|
||||
lines_below: 0
|
||||
)
|
||||
|
||||
expect(subject.second.to_hash).to include(from_content: blob_lines_data(from_line, to_line),
|
||||
to_content: " xpto\n baz\n",
|
||||
lines_above: 0,
|
||||
lines_below: 0)
|
||||
expect(subject.second.to_hash).to include(
|
||||
from_content: blob_lines_data(from_line, to_line),
|
||||
to_content: " xpto\n baz\n",
|
||||
lines_above: 0,
|
||||
lines_below: 0
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -105,30 +110,36 @@ RSpec.describe Gitlab::Diff::SuggestionsParser do
|
|||
from_line = position.new_line - 2
|
||||
to_line = position.new_line + 1
|
||||
|
||||
expect(subject.first.to_hash).to include(from_content: blob_lines_data(from_line, to_line),
|
||||
to_content: " # above and below\n",
|
||||
lines_above: 2,
|
||||
lines_below: 1)
|
||||
expect(subject.first.to_hash).to include(
|
||||
from_content: blob_lines_data(from_line, to_line),
|
||||
to_content: " # above and below\n",
|
||||
lines_above: 2,
|
||||
lines_below: 1
|
||||
)
|
||||
end
|
||||
|
||||
it 'suggestion with above param has correct data' do
|
||||
from_line = position.new_line - 3
|
||||
to_line = position.new_line
|
||||
|
||||
expect(subject.second.to_hash).to eq(from_content: blob_lines_data(from_line, to_line),
|
||||
to_content: " # only above\n",
|
||||
lines_above: 3,
|
||||
lines_below: 0)
|
||||
expect(subject.second.to_hash).to eq(
|
||||
from_content: blob_lines_data(from_line, to_line),
|
||||
to_content: " # only above\n",
|
||||
lines_above: 3,
|
||||
lines_below: 0
|
||||
)
|
||||
end
|
||||
|
||||
it 'suggestion with below param has correct data' do
|
||||
from_line = position.new_line
|
||||
to_line = position.new_line + 3
|
||||
|
||||
expect(subject.third.to_hash).to eq(from_content: blob_lines_data(from_line, to_line),
|
||||
to_content: " # only below\n",
|
||||
lines_above: 0,
|
||||
lines_below: 3)
|
||||
expect(subject.third.to_hash).to eq(
|
||||
from_content: blob_lines_data(from_line, to_line),
|
||||
to_content: " # only below\n",
|
||||
lines_above: 0,
|
||||
lines_below: 3
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -140,6 +140,44 @@ RSpec.describe Gitlab::GitalyClient::RepositoryService, feature_category: :gital
|
|||
end
|
||||
end
|
||||
|
||||
describe '#fork_repository' do
|
||||
let(:source_repository) { Gitlab::Git::Repository.new('default', 'repo/path', '', 'group/project') }
|
||||
|
||||
context 'when branch is not provided' do
|
||||
it 'sends a create_fork message' do
|
||||
expected_request = gitaly_request_with_params(
|
||||
source_repository: source_repository.gitaly_repository,
|
||||
revision: ""
|
||||
)
|
||||
|
||||
expect_any_instance_of(Gitaly::RepositoryService::Stub)
|
||||
.to receive(:create_fork)
|
||||
.with(expected_request, kind_of(Hash))
|
||||
.and_return(double(value: true))
|
||||
|
||||
client.fork_repository(source_repository)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when branch is provided' do
|
||||
it 'sends a create_fork message including revision' do
|
||||
branch = 'wip'
|
||||
|
||||
expected_request = gitaly_request_with_params(
|
||||
source_repository: source_repository.gitaly_repository,
|
||||
revision: "refs/heads/#{branch}"
|
||||
)
|
||||
|
||||
expect_any_instance_of(Gitaly::RepositoryService::Stub)
|
||||
.to receive(:create_fork)
|
||||
.with(expected_request, kind_of(Hash))
|
||||
.and_return(double(value: true))
|
||||
|
||||
client.fork_repository(source_repository, branch)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#import_repository' do
|
||||
let(:source) { 'https://example.com/git/repo.git' }
|
||||
|
||||
|
|
|
|||
|
|
@ -6023,12 +6023,10 @@ RSpec.describe MergeRequest, factory_default: :keep, feature_category: :code_rev
|
|||
allow(merge_request_diff).to receive(:patch_id_sha).and_return(nil)
|
||||
allow(merge_request).to receive(:diff_refs).and_return(diff_refs)
|
||||
|
||||
allow_next_instance_of(Repository) do |repo|
|
||||
allow(repo)
|
||||
.to receive(:get_patch_id)
|
||||
.with(diff_refs.base_sha, diff_refs.head_sha)
|
||||
.and_return(patch_id)
|
||||
end
|
||||
allow(merge_request.project.repository)
|
||||
.to receive(:get_patch_id)
|
||||
.with(diff_refs.base_sha, diff_refs.head_sha)
|
||||
.and_return(patch_id)
|
||||
end
|
||||
|
||||
it { is_expected.to eq(patch_id) }
|
||||
|
|
|
|||
|
|
@ -510,6 +510,26 @@ RSpec.describe Projects::ForkService, feature_category: :source_code_management
|
|||
end
|
||||
end
|
||||
|
||||
describe '#valid_fork_branch?' do
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:project) { create(:project, :small_repo, creator_id: user.id) }
|
||||
let_it_be(:branch) { nil }
|
||||
|
||||
subject { described_class.new(project, user).valid_fork_branch?(branch) }
|
||||
|
||||
context 'when branch exists' do
|
||||
let(:branch) { project.default_branch_or_main }
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
|
||||
context 'when branch does not exist' do
|
||||
let(:branch) { 'branch-that-does-not-exist' }
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#valid_fork_target?' do
|
||||
let(:project) { Project.new }
|
||||
let(:params) { {} }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
RSpec.shared_examples 'Prometheus Alert based health indicator' do
|
||||
let(:schema) { :main }
|
||||
let(:connection) { Gitlab::Database.database_base_models[schema].connection }
|
||||
let(:connection) { Gitlab::Database.database_base_models_with_gitlab_shared[schema].connection }
|
||||
|
||||
around do |example|
|
||||
Gitlab::Database::SharedModel.using_connection(connection) do
|
||||
|
|
@ -124,7 +124,7 @@ RSpec.shared_examples 'Prometheus Alert based health indicator' do
|
|||
end
|
||||
end
|
||||
|
||||
Gitlab::Database.database_base_models.each do |database_base_model, connection|
|
||||
Gitlab::Database.database_base_models_with_gitlab_shared.each do |database_base_model, connection|
|
||||
next unless connection.present?
|
||||
|
||||
it_behaves_like 'Patroni Apdex Evaluator', database_base_model.to_sym
|
||||
|
|
|
|||
|
|
@ -149,6 +149,7 @@ RSpec.describe 'gitlab:background_migrations namespace rake tasks', :suppress_gi
|
|||
context 'with two connections sharing the same database' do
|
||||
before do
|
||||
skip_if_database_exists(:ci)
|
||||
skip_if_database_exists(:jh)
|
||||
end
|
||||
|
||||
it 'skips the shared database' do
|
||||
|
|
|
|||
|
|
@ -579,6 +579,10 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout, feature_categor
|
|||
allow(File).to receive(:open).with(Rails.root.join('ee/db/geo/structure.sql').to_s, any_args).and_yield(output)
|
||||
allow(File).to receive(:open).with(Rails.root.join('ee/db/embedding/structure.sql').to_s, any_args).and_yield(output)
|
||||
end
|
||||
|
||||
if Gitlab.jh?
|
||||
allow(File).to receive(:open).with(Rails.root.join('jh/db/structure.sql').to_s, any_args).and_yield(output)
|
||||
end
|
||||
end
|
||||
|
||||
after do
|
||||
|
|
|
|||
|
|
@ -19,11 +19,11 @@ RSpec.describe RepositoryForkWorker, feature_category: :source_code_management d
|
|||
fork_project(project, forked_project.creator, target_project: forked_project, repository: true)
|
||||
end
|
||||
|
||||
shared_examples 'RepositoryForkWorker performing' do
|
||||
def expect_fork_repository(success:)
|
||||
shared_examples 'RepositoryForkWorker performing' do |branch|
|
||||
def expect_fork_repository(success:, branch:)
|
||||
allow(::Gitlab::GitalyClient::RepositoryService).to receive(:new).and_call_original
|
||||
expect_next_instance_of(::Gitlab::GitalyClient::RepositoryService, forked_project.repository.raw) do |svc|
|
||||
exp = expect(svc).to receive(:fork_repository).with(project.repository.raw)
|
||||
exp = expect(svc).to receive(:fork_repository).with(project.repository.raw, branch)
|
||||
|
||||
if success
|
||||
exp.and_return(true)
|
||||
|
|
@ -39,20 +39,20 @@ RSpec.describe RepositoryForkWorker, feature_category: :source_code_management d
|
|||
it 'creates a new repository from a fork' do
|
||||
allow(subject).to receive(:jid).and_return(jid)
|
||||
|
||||
expect_fork_repository(success: true)
|
||||
expect_fork_repository(success: true, branch: branch)
|
||||
|
||||
perform!
|
||||
end
|
||||
end
|
||||
|
||||
it "creates a new repository from a fork" do
|
||||
expect_fork_repository(success: true)
|
||||
expect_fork_repository(success: true, branch: branch)
|
||||
|
||||
perform!
|
||||
end
|
||||
|
||||
it 'protects the default branch' do
|
||||
expect_fork_repository(success: true)
|
||||
expect_fork_repository(success: true, branch: branch)
|
||||
|
||||
perform!
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ RSpec.describe RepositoryForkWorker, feature_category: :source_code_management d
|
|||
end
|
||||
|
||||
it 'flushes various caches' do
|
||||
expect_fork_repository(success: true)
|
||||
expect_fork_repository(success: true, branch: branch)
|
||||
|
||||
# Works around https://github.com/rspec/rspec-mocks/issues/910
|
||||
expect(Project).to receive(:find).with(forked_project.id).and_return(forked_project)
|
||||
|
|
@ -79,13 +79,13 @@ RSpec.describe RepositoryForkWorker, feature_category: :source_code_management d
|
|||
it 'handles bad fork' do
|
||||
error_message = "Unable to fork project #{forked_project.id} for repository #{project.disk_path} -> #{forked_project.disk_path}: Failed to create fork repository"
|
||||
|
||||
expect_fork_repository(success: false)
|
||||
expect_fork_repository(success: false, branch: branch)
|
||||
|
||||
expect { perform! }.to raise_error(StandardError, error_message)
|
||||
end
|
||||
|
||||
it 'calls Projects::LfsPointers::LfsLinkService#execute with OIDs of source project LFS objects' do
|
||||
expect_fork_repository(success: true)
|
||||
expect_fork_repository(success: true, branch: branch)
|
||||
expect_next_instance_of(Projects::LfsPointers::LfsLinkService) do |service|
|
||||
expect(service).to receive(:execute).with(project.lfs_objects_oids)
|
||||
end
|
||||
|
|
@ -96,7 +96,7 @@ RSpec.describe RepositoryForkWorker, feature_category: :source_code_management d
|
|||
it "handles LFS objects link failure" do
|
||||
error_message = "Unable to fork project #{forked_project.id} for repository #{project.disk_path} -> #{forked_project.disk_path}: Source project has too many LFS objects"
|
||||
|
||||
expect_fork_repository(success: true)
|
||||
expect_fork_repository(success: true, branch: branch)
|
||||
expect_next_instance_of(Projects::LfsPointers::LfsLinkService) do |service|
|
||||
expect(service).to receive(:execute).and_raise(Projects::LfsPointers::LfsLinkService::TooManyOidsError)
|
||||
end
|
||||
|
|
@ -113,6 +113,16 @@ RSpec.describe RepositoryForkWorker, feature_category: :source_code_management d
|
|||
it_behaves_like 'RepositoryForkWorker performing'
|
||||
end
|
||||
|
||||
context 'when a specific branch is requested' do
|
||||
def perform!
|
||||
forked_project.create_import_data(data: { fork_branch: 'wip' })
|
||||
|
||||
subject.perform(forked_project.id)
|
||||
end
|
||||
|
||||
it_behaves_like 'RepositoryForkWorker performing', 'wip'
|
||||
end
|
||||
|
||||
context 'project ID, storage and repo paths passed' do
|
||||
def perform!
|
||||
subject.perform(forked_project.id, 'repos/path', project.disk_path)
|
||||
|
|
|
|||
Loading…
Reference in New Issue