Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
a99c04f018
commit
901ecdbf5c
|
@ -57,6 +57,22 @@ export default {
|
|||
return this.isReference && this.nodeProps.referenceType === 'issue';
|
||||
},
|
||||
|
||||
isLabel() {
|
||||
return this.isReference && this.nodeProps.referenceType === 'label';
|
||||
},
|
||||
|
||||
isEpic() {
|
||||
return this.isReference && this.nodeProps.referenceType === 'epic';
|
||||
},
|
||||
|
||||
isSnippet() {
|
||||
return this.isReference && this.nodeProps.referenceType === 'snippet';
|
||||
},
|
||||
|
||||
isVulnerability() {
|
||||
return this.isReference && this.nodeProps.referenceType === 'vulnerability';
|
||||
},
|
||||
|
||||
isMergeRequest() {
|
||||
return this.isReference && this.nodeProps.referenceType === 'merge_request';
|
||||
},
|
||||
|
@ -86,10 +102,17 @@ export default {
|
|||
case 'issue':
|
||||
case 'merge_request':
|
||||
return `${this.char}${item.iid}`;
|
||||
case 'snippet':
|
||||
return `${this.char}${item.id}`;
|
||||
case 'milestone':
|
||||
case 'label':
|
||||
return `${this.char}${item.title}`;
|
||||
case 'command':
|
||||
return `${this.char}${item.name} `;
|
||||
case 'epic':
|
||||
return `${item.reference}`;
|
||||
case 'vulnerability':
|
||||
return `[vulnerability:${item.id}]`;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
|
@ -184,16 +207,32 @@ export default {
|
|||
<small>{{ item.iid }}</small>
|
||||
{{ item.title }}
|
||||
</span>
|
||||
<span v-if="isVulnerability || isSnippet">
|
||||
<small>{{ item.id }}</small>
|
||||
{{ item.title }}
|
||||
</span>
|
||||
<span v-if="isEpic">
|
||||
<small>{{ item.reference }}</small>
|
||||
{{ item.title }}
|
||||
</span>
|
||||
<span v-if="isMilestone">
|
||||
{{ item.title }}
|
||||
</span>
|
||||
<span v-if="isLabel" class="gl-display-flex gl-align-items-center">
|
||||
<span
|
||||
data-testid="label-color-box"
|
||||
class="gl-rounded-base gl-display-block gl-w-5 gl-h-5 gl-mr-3"
|
||||
:style="{ backgroundColor: item.color }"
|
||||
></span>
|
||||
{{ item.title }}
|
||||
</span>
|
||||
<span v-if="isCommand">
|
||||
/{{ item.name }} <small> {{ item.params[0] }} </small><br />
|
||||
<em>
|
||||
<small> {{ item.description }} </small>
|
||||
</em>
|
||||
</span>
|
||||
<div v-if="isEmoji" class="gl-display-flex gl-flex gl-align-items-center">
|
||||
<div v-if="isEmoji" class="gl-display-flex gl-align-items-center">
|
||||
<div class="gl-pr-4 gl-font-lg">{{ item.e }}</div>
|
||||
<div class="gl-flex-grow-1">
|
||||
{{ item.name }}<br />
|
||||
|
|
|
@ -121,7 +121,6 @@ export default Node.create({
|
|||
dataSource: gl.GfmAutoComplete?.dataSources.members,
|
||||
nodeType: 'reference',
|
||||
nodeProps: {
|
||||
className: 'gfm gfm-project_member',
|
||||
referenceType: 'user',
|
||||
},
|
||||
search: (query) => ({ name, username }) => find(name, query) || find(username, query),
|
||||
|
@ -132,18 +131,56 @@ export default Node.create({
|
|||
dataSource: gl.GfmAutoComplete?.dataSources.issues,
|
||||
nodeType: 'reference',
|
||||
nodeProps: {
|
||||
className: 'gfm gfm-issue',
|
||||
referenceType: 'issue',
|
||||
},
|
||||
search: (query) => ({ iid, title }) => find(iid, query) || find(title, query),
|
||||
}),
|
||||
createSuggestionPlugin({
|
||||
editor: this.editor,
|
||||
char: '$',
|
||||
dataSource: gl.GfmAutoComplete?.dataSources.snippets,
|
||||
nodeType: 'reference',
|
||||
nodeProps: {
|
||||
referenceType: 'snippet',
|
||||
},
|
||||
search: (query) => ({ id, title }) => find(id, query) || find(title, query),
|
||||
}),
|
||||
createSuggestionPlugin({
|
||||
editor: this.editor,
|
||||
char: '~',
|
||||
dataSource: gl.GfmAutoComplete?.dataSources.labels,
|
||||
nodeType: 'reference',
|
||||
nodeProps: {
|
||||
referenceType: 'label',
|
||||
},
|
||||
search: (query) => ({ title }) => find(title, query),
|
||||
}),
|
||||
createSuggestionPlugin({
|
||||
editor: this.editor,
|
||||
char: '&',
|
||||
dataSource: gl.GfmAutoComplete?.dataSources.epics,
|
||||
nodeType: 'reference',
|
||||
nodeProps: {
|
||||
referenceType: 'epic',
|
||||
},
|
||||
search: (query) => ({ iid, title }) => find(iid, query) || find(title, query),
|
||||
}),
|
||||
createSuggestionPlugin({
|
||||
editor: this.editor,
|
||||
char: '[vulnerability:',
|
||||
dataSource: gl.GfmAutoComplete?.dataSources.vulnerabilities,
|
||||
nodeType: 'reference',
|
||||
nodeProps: {
|
||||
referenceType: 'vulnerability',
|
||||
},
|
||||
search: (query) => ({ id, title }) => find(id, query) || find(title, query),
|
||||
}),
|
||||
createSuggestionPlugin({
|
||||
editor: this.editor,
|
||||
char: '!',
|
||||
dataSource: gl.GfmAutoComplete?.dataSources.mergeRequests,
|
||||
nodeType: 'reference',
|
||||
nodeProps: {
|
||||
className: 'gfm gfm-issue',
|
||||
referenceType: 'merge_request',
|
||||
},
|
||||
search: (query) => ({ iid, title }) => find(iid, query) || find(title, query),
|
||||
|
@ -154,7 +191,6 @@ export default Node.create({
|
|||
dataSource: gl.GfmAutoComplete?.dataSources.milestones,
|
||||
nodeType: 'reference',
|
||||
nodeProps: {
|
||||
className: 'gfm gfm-milestone',
|
||||
referenceType: 'milestone',
|
||||
},
|
||||
search: (query) => ({ iid, title }) => find(iid, query) || find(title, query),
|
||||
|
|
|
@ -202,6 +202,7 @@ export const fetchDiffFilesMeta = ({ commit, state }) => {
|
|||
const worker = new TreeWorker();
|
||||
const urlParams = {
|
||||
view: 'inline',
|
||||
w: state.showWhitespace ? '0' : '1',
|
||||
};
|
||||
|
||||
commit(types.SET_LOADING, true);
|
||||
|
|
|
@ -75,19 +75,6 @@ $item-remove-button-space: 42px;
|
|||
}
|
||||
}
|
||||
|
||||
.item-body,
|
||||
.card-header {
|
||||
.health-label-short {
|
||||
max-width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.card-header {
|
||||
.health-label-short {
|
||||
display: initial;
|
||||
}
|
||||
}
|
||||
|
||||
.item-meta {
|
||||
flex-basis: 100%;
|
||||
font-size: $gl-font-size;
|
||||
|
@ -212,11 +199,6 @@ $item-remove-button-space: 42px;
|
|||
max-width: 90%;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
.health-label-short {
|
||||
max-width: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Small devices (landscape phones, 768px and up) */
|
||||
|
@ -239,11 +221,6 @@ $item-remove-button-space: 42px;
|
|||
}
|
||||
}
|
||||
|
||||
.card-header {
|
||||
.health-label-short {
|
||||
max-width: 60px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Medium devices (desktops, 992px and up) */
|
||||
|
@ -257,12 +234,6 @@ $item-remove-button-space: 42px;
|
|||
font-size: inherit; // Base size given to `item-meta` is `$gl-font-size-small`
|
||||
}
|
||||
}
|
||||
|
||||
.card-header {
|
||||
.health-label-short {
|
||||
max-width: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Large devices (large desktops, 1200px and up) */
|
||||
|
@ -309,15 +280,3 @@ $item-remove-button-space: 42px;
|
|||
flex-basis: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 1500px) {
|
||||
.card-header {
|
||||
.health-label-short {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.health-label-long {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -554,7 +554,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
|
|||
end
|
||||
|
||||
def endpoint_metadata_url(project, merge_request)
|
||||
params = request.query_parameters.merge(view: 'inline', diff_head: true)
|
||||
params = request.query_parameters.merge(view: 'inline', diff_head: true, w: current_user&.show_whitespace_in_diffs ? '0' : '1')
|
||||
|
||||
diffs_metadata_project_json_merge_request_path(project, merge_request, 'json', params)
|
||||
end
|
||||
|
|
|
@ -52,7 +52,8 @@ module ResolvesMergeRequests
|
|||
head_pipeline: [:merge_request_diff, { head_pipeline: [:merge_request] }],
|
||||
timelogs: [:timelogs],
|
||||
pipelines: [:merge_request_diffs], # used by `recent_diff_head_shas` to load pipelines
|
||||
committers: [merge_request_diff: [:merge_request_diff_commits]]
|
||||
committers: [merge_request_diff: [:merge_request_diff_commits]],
|
||||
suggested_reviewers: [:predictions]
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -17,6 +17,10 @@ module Types
|
|||
field :value, GraphQL::Types::String,
|
||||
null: true,
|
||||
description: 'Value of the variable.'
|
||||
|
||||
field :value_options, [GraphQL::Types::String],
|
||||
null: true,
|
||||
description: 'Value options for the variable.'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -58,7 +58,8 @@ module BulkImports
|
|||
pipeline_name: pipeline[:pipeline],
|
||||
minimum_source_version: minimum_version,
|
||||
maximum_source_version: maximum_version,
|
||||
source_version: source_version.to_s
|
||||
source_version: source_version.to_s,
|
||||
importer: 'gitlab_migration'
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ module IncidentManagement
|
|||
@issuable = issuable
|
||||
@param_errors = []
|
||||
|
||||
super(project: issuable.project, current_user: current_user, params: Hash(params))
|
||||
super(project: issuable.project, current_user: current_user, params: params)
|
||||
end
|
||||
|
||||
def execute
|
||||
|
|
|
@ -154,10 +154,13 @@ class IssuableBaseService < ::BaseProjectService
|
|||
end
|
||||
|
||||
def filter_escalation_status(issuable)
|
||||
status_params = params.delete(:escalation_status) || {}
|
||||
status_params.permit! if status_params.respond_to?(:permit!)
|
||||
|
||||
result = ::IncidentManagement::IssuableEscalationStatuses::PrepareUpdateService.new(
|
||||
issuable,
|
||||
current_user,
|
||||
params.delete(:escalation_status)
|
||||
status_params
|
||||
).execute
|
||||
|
||||
return unless result.success? && result[:escalation_status].present?
|
||||
|
@ -270,8 +273,9 @@ class IssuableBaseService < ::BaseProjectService
|
|||
# To be overridden by subclasses
|
||||
end
|
||||
|
||||
def after_update(issuable)
|
||||
def after_update(issuable, old_associations)
|
||||
handle_description_updated(issuable)
|
||||
handle_label_changes(issuable, old_associations[:labels])
|
||||
end
|
||||
|
||||
def handle_description_updated(issuable)
|
||||
|
@ -327,7 +331,7 @@ class IssuableBaseService < ::BaseProjectService
|
|||
affected_assignees = (old_associations[:assignees] + new_assignees) - (old_associations[:assignees] & new_assignees)
|
||||
|
||||
invalidate_cache_counts(issuable, users: affected_assignees.compact)
|
||||
after_update(issuable)
|
||||
after_update(issuable, old_associations)
|
||||
issuable.create_new_cross_references!(current_user)
|
||||
execute_hooks(
|
||||
issuable,
|
||||
|
@ -367,7 +371,8 @@ class IssuableBaseService < ::BaseProjectService
|
|||
|
||||
handle_task_changes(issuable)
|
||||
invalidate_cache_counts(issuable, users: issuable.assignees.to_a)
|
||||
after_update(issuable)
|
||||
# not passing old_associations here to keep `update_task` as fast as possible
|
||||
after_update(issuable, {})
|
||||
execute_hooks(issuable, 'update', old_associations: nil)
|
||||
|
||||
if issuable.is_a?(MergeRequest)
|
||||
|
@ -542,6 +547,8 @@ class IssuableBaseService < ::BaseProjectService
|
|||
end
|
||||
|
||||
def has_label_changes?(issuable, old_labels)
|
||||
return false if old_labels.nil?
|
||||
|
||||
Set.new(issuable.labels) != Set.new(old_labels)
|
||||
end
|
||||
|
||||
|
@ -553,12 +560,15 @@ class IssuableBaseService < ::BaseProjectService
|
|||
|
||||
# override if needed
|
||||
def handle_label_changes(issuable, old_labels)
|
||||
return unless has_label_changes?(issuable, old_labels)
|
||||
return false unless has_label_changes?(issuable, old_labels)
|
||||
|
||||
# reset to preserve the label sort order (title ASC)
|
||||
issuable.labels.reset
|
||||
|
||||
GraphqlTriggers.issuable_labels_updated(issuable)
|
||||
|
||||
# return true here to avoid checking for label changes in sub classes
|
||||
true
|
||||
end
|
||||
|
||||
# override if needed
|
||||
|
|
|
@ -68,6 +68,19 @@ module Issues
|
|||
rebalance_if_needed(issue)
|
||||
end
|
||||
|
||||
def handle_escalation_status_change(issue)
|
||||
return unless issue.supports_escalation?
|
||||
|
||||
if issue.escalation_status
|
||||
::IncidentManagement::IssuableEscalationStatuses::AfterUpdateService.new(
|
||||
issue,
|
||||
current_user
|
||||
).execute
|
||||
else
|
||||
::IncidentManagement::IssuableEscalationStatuses::CreateService.new(issue).execute
|
||||
end
|
||||
end
|
||||
|
||||
def issuable_for_positioning(id, positioning_scope)
|
||||
return unless id
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ module Issues
|
|||
user_agent_detail_service.create
|
||||
handle_add_related_issue(issue)
|
||||
resolve_discussions_with_issue(issue)
|
||||
create_escalation_status(issue)
|
||||
handle_escalation_status_change(issue)
|
||||
create_timeline_event(issue)
|
||||
try_to_associate_contacts(issue)
|
||||
|
||||
|
@ -102,10 +102,6 @@ module Issues
|
|||
|
||||
attr_reader :spam_params, :extra_params
|
||||
|
||||
def create_escalation_status(issue)
|
||||
::IncidentManagement::IssuableEscalationStatuses::CreateService.new(issue).execute if issue.supports_escalation?
|
||||
end
|
||||
|
||||
def create_timeline_event(issue)
|
||||
return unless issue.incident?
|
||||
|
||||
|
|
|
@ -63,7 +63,6 @@ module Issues
|
|||
|
||||
handle_assignee_changes(issue, old_assignees)
|
||||
handle_confidential_change(issue)
|
||||
handle_label_changes(issue, old_labels)
|
||||
handle_added_labels(issue, old_labels)
|
||||
handle_milestone_change(issue)
|
||||
handle_added_mentions(issue, old_mentioned_users)
|
||||
|
@ -201,15 +200,6 @@ module Issues
|
|||
::IncidentManagement::AddSeveritySystemNoteWorker.perform_async(issue.id, current_user.id)
|
||||
end
|
||||
|
||||
def handle_escalation_status_change(issue)
|
||||
return unless issue.supports_escalation? && issue.escalation_status
|
||||
|
||||
::IncidentManagement::IssuableEscalationStatuses::AfterUpdateService.new(
|
||||
issue,
|
||||
current_user
|
||||
).execute
|
||||
end
|
||||
|
||||
def create_confidentiality_note(issue)
|
||||
SystemNoteService.change_issue_confidentiality(issue, issue.project, current_user)
|
||||
end
|
||||
|
|
|
@ -38,7 +38,6 @@ module MergeRequests
|
|||
handle_target_branch_change(merge_request)
|
||||
handle_milestone_change(merge_request)
|
||||
handle_draft_status_change(merge_request, changed_fields)
|
||||
handle_label_changes(merge_request, old_labels)
|
||||
|
||||
track_title_and_desc_edits(changed_fields)
|
||||
track_discussion_lock_toggle(merge_request, changed_fields)
|
||||
|
@ -71,7 +70,7 @@ module MergeRequests
|
|||
MergeRequests::CloseService
|
||||
end
|
||||
|
||||
def after_update(issuable)
|
||||
def after_update(issuable, old_associations)
|
||||
super
|
||||
issuable.cache_merge_request_closes_issues!(current_user)
|
||||
end
|
||||
|
|
|
@ -49,7 +49,7 @@ module WorkItems
|
|||
super
|
||||
end
|
||||
|
||||
def after_update(work_item)
|
||||
def after_update(work_item, old_associations)
|
||||
super
|
||||
|
||||
GraphqlTriggers.issuable_title_updated(work_item) if work_item.previous_changes.key?(:title)
|
||||
|
|
|
@ -18,7 +18,8 @@ module BulkImports
|
|||
bulk_import_entity_id: entity_id,
|
||||
bulk_import_id: bulk_import_id(entity_id),
|
||||
current_stage: current_stage,
|
||||
message: 'Stage running'
|
||||
message: 'Stage running',
|
||||
importer: 'gitlab_migration'
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -30,7 +31,8 @@ module BulkImports
|
|||
bulk_import_entity_id: entity_id,
|
||||
bulk_import_id: bulk_import_id(entity_id),
|
||||
current_stage: current_stage,
|
||||
message: 'Stage starting'
|
||||
message: 'Stage starting',
|
||||
importer: 'gitlab_migration'
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -47,12 +49,13 @@ module BulkImports
|
|||
bulk_import_entity_id: entity_id,
|
||||
bulk_import_id: bulk_import_id(entity_id),
|
||||
current_stage: current_stage,
|
||||
message: e.message
|
||||
message: e.message,
|
||||
importer: 'gitlab_migration'
|
||||
)
|
||||
)
|
||||
|
||||
Gitlab::ErrorTracking.track_exception(
|
||||
e, bulk_import_entity_id: entity_id, bulk_import_id: bulk_import_id(entity_id)
|
||||
e, bulk_import_entity_id: entity_id, bulk_import_id: bulk_import_id(entity_id), importer: 'gitlab_migration'
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
@ -42,7 +42,9 @@ module BulkImports
|
|||
structured_payload(
|
||||
log_attributes(exception, entity).merge(
|
||||
bulk_import_id: entity.bulk_import_id,
|
||||
bulk_import_entity_type: entity.source_type
|
||||
bulk_import_entity_type: entity.source_type,
|
||||
message: "Request to export #{entity.source_type} failed",
|
||||
importer: 'gitlab_migration'
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -83,7 +85,8 @@ module BulkImports
|
|||
log_attributes(e, entity).merge(
|
||||
message: 'Failed to fetch source entity id',
|
||||
bulk_import_id: entity.bulk_import_id,
|
||||
bulk_import_entity_type: entity.source_type
|
||||
bulk_import_entity_type: entity.source_type,
|
||||
importer: 'gitlab_migration'
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -21,7 +21,9 @@ module BulkImports
|
|||
structured_payload(
|
||||
bulk_import_entity_id: pipeline_tracker.entity.id,
|
||||
bulk_import_id: pipeline_tracker.entity.bulk_import_id,
|
||||
pipeline_name: pipeline_tracker.pipeline_name
|
||||
pipeline_name: pipeline_tracker.pipeline_name,
|
||||
message: 'Pipeline starting',
|
||||
importer: 'gitlab_migration'
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -32,7 +34,8 @@ module BulkImports
|
|||
bulk_import_entity_id: entity_id,
|
||||
bulk_import_id: bulk_import_id(entity_id),
|
||||
pipeline_tracker_id: pipeline_tracker_id,
|
||||
message: 'Unstarted pipeline not found'
|
||||
message: 'Unstarted pipeline not found',
|
||||
importer: 'gitlab_migration'
|
||||
)
|
||||
)
|
||||
end
|
||||
|
@ -74,7 +77,8 @@ module BulkImports
|
|||
bulk_import_entity_id: pipeline_tracker.entity.id,
|
||||
bulk_import_id: pipeline_tracker.entity.bulk_import_id,
|
||||
pipeline_name: pipeline_tracker.pipeline_name,
|
||||
message: exception.message
|
||||
message: exception.message,
|
||||
importer: 'gitlab_migration'
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -82,7 +86,8 @@ module BulkImports
|
|||
exception,
|
||||
bulk_import_entity_id: pipeline_tracker.entity.id,
|
||||
bulk_import_id: pipeline_tracker.entity.bulk_import_id,
|
||||
pipeline_name: pipeline_tracker.pipeline_name
|
||||
pipeline_name: pipeline_tracker.pipeline_name,
|
||||
importer: 'gitlab_migration'
|
||||
)
|
||||
|
||||
BulkImports::Failure.create(
|
||||
|
@ -150,7 +155,8 @@ module BulkImports
|
|||
bulk_import_entity_id: pipeline_tracker.entity.id,
|
||||
bulk_import_id: pipeline_tracker.entity.bulk_import_id,
|
||||
pipeline_name: pipeline_tracker.pipeline_name,
|
||||
message: "Retrying error: #{exception.message}"
|
||||
message: "Retrying error: #{exception.message}",
|
||||
importer: 'gitlab_migration'
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -165,7 +171,8 @@ module BulkImports
|
|||
bulk_import_entity_id: pipeline_tracker.entity.id,
|
||||
bulk_import_id: pipeline_tracker.entity.bulk_import_id,
|
||||
pipeline_name: pipeline_tracker.pipeline_name,
|
||||
message: 'Skipping pipeline due to failed entity'
|
||||
message: 'Skipping pipeline due to failed entity',
|
||||
importer: 'gitlab_migration'
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -680,3 +680,18 @@ unlike with issues or merge requests.
|
|||
```ruby
|
||||
ApplicationSetting.current
|
||||
```
|
||||
|
||||
### Open object in `irb`
|
||||
|
||||
Sometimes it is easier to go through a method if you are in the context of the object. You can shim into the namespace of `Object` to let you open `irb` in the context of any object:
|
||||
|
||||
```ruby
|
||||
Object.define_method(:irb) { binding.irb }
|
||||
|
||||
project = Project.last
|
||||
# => #<Project id:2537 root/discard>>
|
||||
project.irb
|
||||
# Notice new context
|
||||
irb(#<Project>)> web_url
|
||||
# => "https://gitlab-example/root/discard"
|
||||
```
|
||||
|
|
|
@ -62,21 +62,6 @@ Notify.test_email(e, "Test email for #{n}", 'Test email').deliver_now
|
|||
Notify.test_email(u.email, "Test email for #{u.name}", 'Test email').deliver_now
|
||||
```
|
||||
|
||||
## Open object in `irb`
|
||||
|
||||
Sometimes it is easier to go through a method if you are in the context of the object. You can shim into the namespace of `Object` to let you open `irb` in the context of any object:
|
||||
|
||||
```ruby
|
||||
Object.define_method(:irb) { binding.irb }
|
||||
|
||||
project = Project.last
|
||||
# => #<Project id:2537 root/discard>>
|
||||
project.irb
|
||||
# Notice new context
|
||||
irb(#<Project>)> web_url
|
||||
# => "https://gitlab-example/root/discard"
|
||||
```
|
||||
|
||||
## Time an operation
|
||||
|
||||
```ruby
|
||||
|
@ -359,37 +344,6 @@ repeat the above procedure after,
|
|||
and report the output to
|
||||
[GitLab Support](https://about.gitlab.com/support/).
|
||||
|
||||
## Repository
|
||||
|
||||
### Search sequence of pushes to a repository
|
||||
|
||||
If it seems that a commit has gone "missing", search the sequence of pushes to a repository.
|
||||
[This StackOverflow article](https://stackoverflow.com/questions/13468027/the-mystery-of-the-missing-commit-across-merges)
|
||||
describes how you can end up in this state without a force push. Another cause can be a misconfigured [server hook](../server_hooks.md) that changes a HEAD ref via a `git reset` operation.
|
||||
|
||||
If you look at the output from the sample code below for the target branch, you
|
||||
see a discontinuity in the from/to commits as you step through the output. The `commit_from` of each new push should equal the `commit_to` of the previous push. A break in that sequence indicates one or more commits have been "lost" from the repository history.
|
||||
|
||||
The following example checks the last 100 pushes and prints the `commit_from` and `commit_to` entries:
|
||||
|
||||
```ruby
|
||||
p = Project.find_by_full_path('u/p')
|
||||
p.events.pushed_action.last(100).each do |e|
|
||||
printf "%-20.20s %8s...%8s (%s)
|
||||
", e.push_event_payload[:ref], e.push_event_payload[:commit_from], e.push_event_payload[:commit_to], e.author.try(:username)
|
||||
end
|
||||
```
|
||||
|
||||
Example output showing break in sequence at line 4:
|
||||
|
||||
```plaintext
|
||||
master f21b07713251e04575908149bdc8ac1f105aabc3...6bc56c1f46244792222f6c85b11606933af171de (root)
|
||||
master 6bc56c1f46244792222f6c85b11606933af171de...132da6064f5d3453d445fd7cb452b148705bdc1b (root)
|
||||
master 132da6064f5d3453d445fd7cb452b148705bdc1b...a62e1e693150a2e46ace0ce696cd4a52856dfa65 (root)
|
||||
master 58b07b719a4b0039fec810efa52f479ba1b84756...f05321a5b5728bd8a89b7bf530aa44043c951dce (root)
|
||||
master f05321a5b5728bd8a89b7bf530aa44043c951dce...7d02e575fd790e76a3284ee435368279a5eb3773 (root)
|
||||
```
|
||||
|
||||
## Mirrors
|
||||
|
||||
### Find mirrors with "bad decrypt" errors
|
||||
|
|
|
@ -10406,6 +10406,7 @@ CI/CD config variables.
|
|||
| <a id="ciconfigvariabledescription"></a>`description` | [`String`](#string) | Description for the CI/CD config variable. |
|
||||
| <a id="ciconfigvariablekey"></a>`key` | [`String`](#string) | Name of the variable. |
|
||||
| <a id="ciconfigvariablevalue"></a>`value` | [`String`](#string) | Value of the variable. |
|
||||
| <a id="ciconfigvariablevalueoptions"></a>`valueOptions` | [`[String!]`](#string) | Value options for the variable. |
|
||||
|
||||
### `CiGroup`
|
||||
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 80 KiB |
|
@ -24,6 +24,8 @@ We use the following terms to describe components and properties of the Pods arc
|
|||
|
||||
A Pod is a set of infrastructure components that contains multiple top-level namespaces that belong to different organizations. The components include both datastores (PostgreSQL, Redis etc.) and stateless services (web etc.). The infrastructure components provided within a Pod are shared among organizations and their top-level namespaces but not shared with other Pods. This isolation of infrastructure components means that Pods are independent from each other.
|
||||
|
||||
![Term Pod](term-pod.png)
|
||||
|
||||
#### Pod properties
|
||||
|
||||
- Each pod is independent from the others
|
||||
|
@ -40,6 +42,14 @@ Discouraged synonyms: GitLab instance, cluster, shard
|
|||
|
||||
A cluster is a collection of Pods.
|
||||
|
||||
![Term Cluster](term-cluster.png)
|
||||
|
||||
#### Cluster properties
|
||||
|
||||
- A cluster holds cluster-wide metadata, for example Users, Routes, Settings.
|
||||
|
||||
Discouraged synonyms: whale
|
||||
|
||||
### Organizations
|
||||
|
||||
GitLab references [Organizations in the initial set up](../../../topics/set_up_organization.md) and users can add a (free text) organization to their profile. There is no Organization entity established in the GitLab codebase.
|
||||
|
@ -54,6 +64,9 @@ Organizations work under the following assumptions:
|
|||
1. Features need to work within an organization.
|
||||
1. Only few features need to work across organizations.
|
||||
1. Users understand that the majority of pages they view are only scoped to a single organization at a time.
|
||||
1. Organizations are located on a single pod.
|
||||
|
||||
![Term Organization](term-organization.png)
|
||||
|
||||
#### Organization properties
|
||||
|
||||
|
@ -81,6 +94,8 @@ Top-level namespaces may [be replaced by workspaces](https://gitlab.com/gitlab-o
|
|||
|
||||
Discouraged synonyms: Root-level namespace
|
||||
|
||||
![Term Top-level Namespace](term-top-level-namespace.png)
|
||||
|
||||
#### Top-level namespace properties
|
||||
|
||||
- Top-level namespaces belonging to an organization are located on the same Pod
|
||||
|
@ -174,7 +189,7 @@ Organizations solve the following problems:
|
|||
1. Self-managed instances would set a default organization.
|
||||
1. Organizations can control user-profiles in a central way. This could be achieved by having an organization specific user-profile. Such a profile makes it possible for the organization administrators to control the user role in a company, enforce user emails, or show a graphical indicator of a user being part of the organization. An example would be a "GitLab Employee stamp" on comments.
|
||||
|
||||
![Move to Organizations](2022-10-05-Pods-Organizations-Iteration0.png)
|
||||
![Move to Organizations](iteration0-organizations-introduction.png)
|
||||
|
||||
#### Why would customers opt-in to Organizations?
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 319 KiB |
Binary file not shown.
After Width: | Height: | Size: 265 KiB |
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
|
@ -172,8 +172,12 @@ To create a group runner:
|
|||
1. [Install GitLab Runner](https://docs.gitlab.com/runner/install/).
|
||||
1. On the top bar, select **Main menu > Groups** and find your group.
|
||||
1. On the left sidebar, select **CI/CD > Runners**.
|
||||
1. Note the URL and token.
|
||||
1. [Register the runner](https://docs.gitlab.com/runner/register/).
|
||||
1. In the top-right corner, select **Register a group runner**.
|
||||
1. Select **Show runner installation and registration instructions**.
|
||||
These instructions include the token, URL, and a command to register a runner.
|
||||
|
||||
Alternately, you can copy the registration token and follow the documentation for
|
||||
how to [register a runner](https://docs.gitlab.com/runner/register/).
|
||||
|
||||
### View and manage group runners
|
||||
|
||||
|
|
|
@ -14,10 +14,6 @@ Use these runners to build, test, and deploy apps for the Apple ecosystem (macOS
|
|||
of all the capabilities of the GitLab single DevOps platform and not have to manage or operate a
|
||||
build environment.
|
||||
|
||||
CI/CD minutes used on GitLab SaaS macOS runners are included in your CI/CD minute consumption totals. CI jobs that run on macOS **will** consume CI minutes at a faster rate than CI jobs on the GitLab SaaS runners on Linux.
|
||||
|
||||
Refer to the CI/CD minutes [cost factor](../../../ci/pipelines/cicd_minutes.md#cost-factor) for the cost factor applied to the GitLab SaaS macOS runners.
|
||||
|
||||
Jobs handled by macOS shared runners on GitLab.com **time out after 2 hours**, regardless of the timeout configured in a project.
|
||||
|
||||
## Access request process
|
||||
|
|
|
@ -2165,7 +2165,7 @@ This example creates four paths of execution:
|
|||
explicitly defined for all jobs that use the `needs` keyword, or are referenced
|
||||
in a job's `needs` section.
|
||||
- In GitLab 13.9 and older, if `needs` refers to a job that might not be added to
|
||||
a pipeline because of `only`, `except`, or `rules`, the pipeline might fail to create.
|
||||
a pipeline because of `only`, `except`, or `rules`, the pipeline might fail to create. In GitLab 13.10 and later, use the [`needs:optional`](#needsoptional) keyword to resolve a failed pipeline creation.
|
||||
|
||||
#### `needs:artifacts`
|
||||
|
||||
|
|
|
@ -96,6 +96,9 @@ when transitioning to the `pending` state. This job is responsible for creating
|
|||
a multi-project or child pipeline. The workflow loop starts again
|
||||
from the `CreatePipelineService` every time a downstream pipeline is triggered.
|
||||
|
||||
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
|
||||
You can watch a walkthrough of the architecture in [CI Backend Architectural Walkthrough](https://www.youtube.com/watch?v=ew4BwohS5OY).
|
||||
|
||||
## Job scheduling
|
||||
|
||||
When a Pipeline is created all its jobs are created at once for all stages, with an initial state of `created`. This makes it possible to visualize the full content of a pipeline.
|
||||
|
|
|
@ -149,7 +149,7 @@ with [domain expertise](#domain-experts).
|
|||
| `~UX` user-facing changes (*3*) | [Product Designer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_reviewers_UX). Refer to the [design and user interface guidelines](contributing/design.md) for details. |
|
||||
| Adding a new JavaScript library (*1*) | - [Frontend foundations member](https://about.gitlab.com/direction/ecosystem/foundations/) if the library significantly increases the [bundle size](https://gitlab.com/gitlab-org/frontend/playground/webpack-memory-metrics/-/blob/master/doc/report.md).<br/>- A [legal department member](https://about.gitlab.com/handbook/legal/) if the license used by the new library hasn't been approved for use in GitLab.<br/><br/>More information about license compatibility can be found in our [GitLab Licensing and Compatibility documentation](licensing.md). |
|
||||
| A new dependency or a file system change | - [Distribution team member](https://about.gitlab.com/company/team/). See how to work with the [Distribution team](https://about.gitlab.com/handbook/engineering/development/enablement/systems/distribution/#how-to-work-with-distribution) for more details.<br/>- For Rubygems, request an [AppSec review](gemfile.md#request-an-appsec-review). |
|
||||
| `~documentation` changes | [Technical writer](https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments) based on assignments in the appropriate [DevOps stage group](https://about.gitlab.com/handbook/product/categories/#devops-stages). |
|
||||
| `~documentation` or `~UI text` changes | [Technical writer](https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments) based on assignments in the appropriate [DevOps stage group](https://about.gitlab.com/handbook/product/categories/#devops-stages). |
|
||||
| Changes to development guidelines | Follow the [review process](development_processes.md#development-guidelines-review) and get the approvals accordingly. |
|
||||
| End-to-end **and** non-end-to-end changes (*4*) | [Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors). |
|
||||
| Only End-to-end changes (*4*) **or** if the MR author is a [Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors) | [Quality maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_qa). |
|
||||
|
|
|
@ -335,8 +335,10 @@ If you update the `CODEOWNERS` file, close the merge request and create a new on
|
|||
|
||||
### User not shown as possible approver
|
||||
|
||||
A user might not show as an approver on the Code Owner merge request approval rules.
|
||||
A user might not show as an approver on the Code Owner merge request approval rules
|
||||
if any of these conditions are true:
|
||||
|
||||
This result occurs when a rule prevents the specific user from approving the merge request.
|
||||
Check the project
|
||||
[merge request approval setting](merge_requests/approvals/settings.md#edit-merge-request-approval-settings).
|
||||
- A rule prevents the specific user from approving the merge request.
|
||||
Check the project [merge request approval](merge_requests/approvals/settings.md#edit-merge-request-approval-settings) settings.
|
||||
- A Code Owner group has a visibility of **private**, and the current user is not a
|
||||
member of the Code Owner group.
|
||||
|
|
|
@ -306,3 +306,33 @@ The same approach should also allow misidentified file types to be fixed.
|
|||
```
|
||||
|
||||
`*.txt` files have an entry in the heuristics file. This example prevents parsing of these files.
|
||||
|
||||
### Search sequence of pushes to a repository
|
||||
|
||||
If it seems that a commit has gone "missing", search the sequence of pushes to a repository.
|
||||
[This StackOverflow article](https://stackoverflow.com/questions/13468027/the-mystery-of-the-missing-commit-across-merges)
|
||||
describes how you can end up in this state without a force push. Another cause can be a misconfigured [server hook](../../../administration/server_hooks.md) that changes a HEAD ref in a `git reset` operation.
|
||||
|
||||
If you look at the output from the sample code below for the target branch, you
|
||||
see a discontinuity in the from/to commits as you step through the output.
|
||||
The `commit_from` of each new push should equal the `commit_to` of the previous push.
|
||||
A break in that sequence indicates one or more commits have been "lost" from the repository history.
|
||||
|
||||
Using the [rails console](../../../administration/operations/rails_console.md#starting-a-rails-console-session), the following example checks the last 100 pushes and prints the `commit_from` and `commit_to` entries:
|
||||
|
||||
```ruby
|
||||
p = Project.find_by_full_path('project/path')
|
||||
p.events.pushed_action.last(100).each do |e|
|
||||
puts "%-20.20s %8s...%8s (%s)", e.push_event_payload[:ref], e.push_event_payload[:commit_from], e.push_event_payload[:commit_to], e.author.try(:username)
|
||||
end ; nil
|
||||
```
|
||||
|
||||
Example output showing break in sequence at line 4:
|
||||
|
||||
```plaintext
|
||||
master f21b07713251e04575908149bdc8ac1f105aabc3...6bc56c1f46244792222f6c85b11606933af171de root
|
||||
master 6bc56c1f46244792222f6c85b11606933af171de...132da6064f5d3453d445fd7cb452b148705bdc1b root
|
||||
master 132da6064f5d3453d445fd7cb452b148705bdc1b...a62e1e693150a2e46ace0ce696cd4a52856dfa65 root
|
||||
master 58b07b719a4b0039fec810efa52f479ba1b84756...f05321a5b5728bd8a89b7bf530aa44043c951dce root
|
||||
master f05321a5b5728bd8a89b7bf530aa44043c951dce...7d02e575fd790e76a3284ee435368279a5eb3773 root
|
||||
```
|
||||
|
|
|
@ -28,7 +28,8 @@ module BulkImports
|
|||
bulk_import_entity_id: context.entity.id,
|
||||
bulk_import_entity_type: context.entity.source_type,
|
||||
pipeline_class: self.class.name,
|
||||
message: "Entity #{entity.status_name}"
|
||||
message: "Entity #{entity.status_name}",
|
||||
importer: 'gitlab_migration'
|
||||
)
|
||||
|
||||
context.portable.try(:after_import)
|
||||
|
|
|
@ -54,7 +54,8 @@ module BulkImports
|
|||
skip!(
|
||||
'Skipping pipeline due to failed entity',
|
||||
pipeline_step: step,
|
||||
step_class: class_name
|
||||
step_class: class_name,
|
||||
importer: 'gitlab_migration'
|
||||
)
|
||||
rescue BulkImports::NetworkError => e
|
||||
if e.retriable?(context.tracker)
|
||||
|
@ -111,7 +112,9 @@ module BulkImports
|
|||
bulk_import_id: context.bulk_import_id,
|
||||
pipeline_step: step,
|
||||
exception_class: exception.class.to_s,
|
||||
exception_message: exception.message
|
||||
exception_message: exception.message,
|
||||
message: "Pipeline failed",
|
||||
importer: 'gitlab_migration'
|
||||
)
|
||||
|
||||
BulkImports::Failure.create(attributes)
|
||||
|
@ -135,7 +138,8 @@ module BulkImports
|
|||
bulk_import_entity_id: context.entity.id,
|
||||
bulk_import_entity_type: context.entity.source_type,
|
||||
pipeline_class: pipeline,
|
||||
context_extra: context.extra
|
||||
context_extra: context.extra,
|
||||
importer: 'gitlab_migration'
|
||||
}
|
||||
|
||||
defaults
|
||||
|
|
|
@ -50,7 +50,7 @@ module Gitlab
|
|||
|
||||
entry :variables, Entry::Variables,
|
||||
description: 'Environment variables that will be used.',
|
||||
metadata: { allowed_value_data: %i[value description] },
|
||||
metadata: { allowed_value_data: %i[value description], allow_array_value: true },
|
||||
reserved: true
|
||||
|
||||
entry :stages, Entry::Stages,
|
||||
|
|
|
@ -10,6 +10,7 @@ module Gitlab
|
|||
class Variable < ::Gitlab::Config::Entry::Simplifiable
|
||||
strategy :SimpleVariable, if: -> (config) { SimpleVariable.applies_to?(config) }
|
||||
strategy :ComplexVariable, if: -> (config) { ComplexVariable.applies_to?(config) }
|
||||
strategy :ComplexArrayVariable, if: -> (config) { ComplexArrayVariable.applies_to?(config) }
|
||||
|
||||
class SimpleVariable < ::Gitlab::Config::Entry::Node
|
||||
include ::Gitlab::Config::Entry::Validatable
|
||||
|
@ -39,7 +40,7 @@ module Gitlab
|
|||
|
||||
class << self
|
||||
def applies_to?(config)
|
||||
config.is_a?(Hash)
|
||||
config.is_a?(Hash) && !config[:value].is_a?(Array)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -86,6 +87,34 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
class ComplexArrayVariable < ComplexVariable
|
||||
include ::Gitlab::Config::Entry::Validatable
|
||||
|
||||
class << self
|
||||
def applies_to?(config)
|
||||
config.is_a?(Hash) && config[:value].is_a?(Array)
|
||||
end
|
||||
end
|
||||
|
||||
validations do
|
||||
validates :config_value, array_of_strings: true, allow_nil: false, if: :config_value_defined?
|
||||
|
||||
validate do
|
||||
next if opt(:allow_array_value)
|
||||
|
||||
errors.add(:config, 'value must be an alphanumeric string')
|
||||
end
|
||||
end
|
||||
|
||||
def value
|
||||
config_value.first
|
||||
end
|
||||
|
||||
def value_with_data
|
||||
super.merge(value_options: config_value).compact
|
||||
end
|
||||
end
|
||||
|
||||
class UnknownStrategy < ::Gitlab::Config::Entry::Node
|
||||
def errors
|
||||
["variable definition must be either a string or a hash"]
|
||||
|
|
|
@ -36,7 +36,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def composable_metadata
|
||||
{ allowed_value_data: opt(:allowed_value_data) }
|
||||
{ allowed_value_data: opt(:allowed_value_data), allow_array_value: opt(:allow_array_value) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -151,7 +151,7 @@ module Gitlab
|
|||
|
||||
def limit_value
|
||||
# note: only first _or_ last can be specified, not both
|
||||
@limit_value ||= [first, last, max_page_size, GitlabSchema.default_max_page_size].compact.min
|
||||
@limit_value ||= [first, last, max_page_size || GitlabSchema.default_max_page_size].compact.min
|
||||
end
|
||||
|
||||
def loaded?(items)
|
||||
|
|
|
@ -89,12 +89,12 @@ module Sidebars
|
|||
::Sidebars::MenuItem.new(
|
||||
title: _('Google Cloud'),
|
||||
link: project_google_cloud_configuration_path(context.project),
|
||||
active_routes: { controller: [
|
||||
:configuration,
|
||||
:service_accounts,
|
||||
:databases,
|
||||
:deployments,
|
||||
:gcp_regions
|
||||
active_routes: { controller: %w[
|
||||
projects/google_cloud/configuration
|
||||
projects/google_cloud/service_accounts
|
||||
projects/google_cloud/databases
|
||||
projects/google_cloud/deployments
|
||||
projects/google_cloud/gcp_regions
|
||||
] },
|
||||
item_id: :google_cloud
|
||||
)
|
||||
|
|
|
@ -46905,9 +46905,6 @@ msgstr ""
|
|||
msgid "at least the Reporter role, the author, and assignees"
|
||||
msgstr ""
|
||||
|
||||
msgid "at risk"
|
||||
msgstr ""
|
||||
|
||||
msgid "attach a new file"
|
||||
msgstr ""
|
||||
|
||||
|
@ -48294,9 +48291,6 @@ msgstr ""
|
|||
msgid "my-topic"
|
||||
msgstr ""
|
||||
|
||||
msgid "need attention"
|
||||
msgstr ""
|
||||
|
||||
msgid "needs to be between 10 minutes and 1 month"
|
||||
msgstr ""
|
||||
|
||||
|
@ -48345,9 +48339,6 @@ msgstr ""
|
|||
msgid "nounSeries|%{item}, and %{lastItem}"
|
||||
msgstr ""
|
||||
|
||||
msgid "on track"
|
||||
msgstr ""
|
||||
|
||||
msgid "only %{parent_types} can be parent of Task."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -77,7 +77,8 @@ RSpec.describe Projects::MergeRequestsController do
|
|||
merge_request,
|
||||
'json',
|
||||
diff_head: true,
|
||||
view: 'inline'))
|
||||
view: 'inline',
|
||||
w: '0'))
|
||||
end
|
||||
|
||||
context 'when diff files were cleaned' do
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
import { GlAvatarLabeled, GlDropdownItem } from '@gitlab/ui';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
|
||||
import SuggestionsDropdown from '~/content_editor/components/suggestions_dropdown.vue';
|
||||
|
||||
describe('~/content_editor/components/suggestions_dropdown', () => {
|
||||
let wrapper;
|
||||
|
||||
const buildWrapper = ({ propsData = {} } = {}) => {
|
||||
wrapper = shallowMount(SuggestionsDropdown, {
|
||||
propsData: {
|
||||
nodeType: 'reference',
|
||||
...propsData,
|
||||
},
|
||||
});
|
||||
const buildWrapper = ({ propsData } = {}) => {
|
||||
wrapper = extendedWrapper(
|
||||
shallowMount(SuggestionsDropdown, {
|
||||
propsData: {
|
||||
nodeType: 'reference',
|
||||
command: jest.fn(),
|
||||
...propsData,
|
||||
},
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const exampleUser = { username: 'root', avatar_url: 'root_avatar.png', type: 'User' };
|
||||
|
@ -23,6 +27,25 @@ describe('~/content_editor/components/suggestions_dropdown', () => {
|
|||
description: 'Set due date',
|
||||
params: ['<in 2 days | this Friday | December 31st>'],
|
||||
};
|
||||
const exampleEpic = {
|
||||
iid: 8884,
|
||||
title: '❓ Remote Development | Solution validation',
|
||||
reference: 'gitlab-org&8884',
|
||||
};
|
||||
const exampleLabel = {
|
||||
title: 'devops::create',
|
||||
color: '#E44D2A',
|
||||
type: 'GroupLabel',
|
||||
textColor: '#FFFFFF',
|
||||
};
|
||||
const exampleVulnerability = {
|
||||
id: 60850147,
|
||||
title: 'System procs network activity',
|
||||
};
|
||||
const exampleSnippet = {
|
||||
id: 2420859,
|
||||
title: 'Project creation QueryRecorder logs',
|
||||
};
|
||||
const exampleEmoji = {
|
||||
c: 'people',
|
||||
e: '😃',
|
||||
|
@ -40,13 +63,17 @@ describe('~/content_editor/components/suggestions_dropdown', () => {
|
|||
|
||||
describe('on item select', () => {
|
||||
it.each`
|
||||
nodeType | referenceType | char | reference | insertedText | insertedProps
|
||||
${'reference'} | ${'user'} | ${'@'} | ${exampleUser} | ${`@root`} | ${{}}
|
||||
${'reference'} | ${'issue'} | ${'#'} | ${exampleIssue} | ${`#123`} | ${{}}
|
||||
${'reference'} | ${'merge_request'} | ${'!'} | ${exampleMergeRequest} | ${`!224`} | ${{}}
|
||||
${'reference'} | ${'milestone'} | ${'%'} | ${exampleMilestone} | ${`%1.3`} | ${{}}
|
||||
${'reference'} | ${'command'} | ${'/'} | ${exampleCommand} | ${'/due '} | ${{}}
|
||||
${'emoji'} | ${'emoji'} | ${':'} | ${exampleEmoji} | ${`😃`} | ${insertedEmojiProps}
|
||||
nodeType | referenceType | char | reference | insertedText | insertedProps
|
||||
${'reference'} | ${'user'} | ${'@'} | ${exampleUser} | ${`@root`} | ${{}}
|
||||
${'reference'} | ${'issue'} | ${'#'} | ${exampleIssue} | ${`#123`} | ${{}}
|
||||
${'reference'} | ${'merge_request'} | ${'!'} | ${exampleMergeRequest} | ${`!224`} | ${{}}
|
||||
${'reference'} | ${'milestone'} | ${'%'} | ${exampleMilestone} | ${`%1.3`} | ${{}}
|
||||
${'reference'} | ${'command'} | ${'/'} | ${exampleCommand} | ${'/due '} | ${{}}
|
||||
${'reference'} | ${'epic'} | ${'&'} | ${exampleEpic} | ${`gitlab-org&8884`} | ${{}}
|
||||
${'reference'} | ${'label'} | ${'~'} | ${exampleLabel} | ${`~devops::create`} | ${{}}
|
||||
${'reference'} | ${'vulnerability'} | ${'[vulnerability:'} | ${exampleVulnerability} | ${`[vulnerability:60850147]`} | ${{}}
|
||||
${'reference'} | ${'snippet'} | ${'$'} | ${exampleSnippet} | ${`$2420859`} | ${{}}
|
||||
${'emoji'} | ${'emoji'} | ${':'} | ${exampleEmoji} | ${`😃`} | ${insertedEmojiProps}
|
||||
`(
|
||||
'runs a command to insert the selected $referenceType',
|
||||
({ char, nodeType, referenceType, reference, insertedText, insertedProps }) => {
|
||||
|
@ -80,24 +107,21 @@ describe('~/content_editor/components/suggestions_dropdown', () => {
|
|||
|
||||
describe('rendering user references', () => {
|
||||
it('displays avatar labeled component', () => {
|
||||
const testUser = exampleUser;
|
||||
buildWrapper({
|
||||
propsData: {
|
||||
char: '@',
|
||||
command: jest.fn(),
|
||||
nodeType: 'reference',
|
||||
nodeProps: {
|
||||
referenceType: 'user',
|
||||
},
|
||||
items: [testUser],
|
||||
items: [exampleUser],
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper.findComponent(GlAvatarLabeled).attributes()).toEqual(
|
||||
expect.objectContaining({
|
||||
label: testUser.username,
|
||||
label: exampleUser.username,
|
||||
shape: 'circle',
|
||||
src: testUser.avatar_url,
|
||||
src: exampleUser.avatar_url,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
@ -112,7 +136,6 @@ describe('~/content_editor/components/suggestions_dropdown', () => {
|
|||
buildWrapper({
|
||||
propsData: {
|
||||
char,
|
||||
command: jest.fn(),
|
||||
nodeType: 'reference',
|
||||
nodeProps: {
|
||||
referenceType,
|
||||
|
@ -127,13 +150,68 @@ describe('~/content_editor/components/suggestions_dropdown', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe.each`
|
||||
referenceType | char | reference
|
||||
${'snippet'} | ${'$'} | ${exampleSnippet}
|
||||
${'vulnerability'} | ${'[vulnerability:'} | ${exampleVulnerability}
|
||||
`('rendering $referenceType references', ({ referenceType, char, reference }) => {
|
||||
it(`displays ${referenceType} ID and title`, () => {
|
||||
buildWrapper({
|
||||
propsData: {
|
||||
char,
|
||||
nodeProps: {
|
||||
referenceType,
|
||||
},
|
||||
items: [reference],
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper.text()).toContain(`${reference.id}`);
|
||||
expect(wrapper.text()).toContain(`${reference.title}`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('rendering label references', () => {
|
||||
it('displays label title and color', () => {
|
||||
buildWrapper({
|
||||
propsData: {
|
||||
char: '~',
|
||||
nodeProps: {
|
||||
referenceType: 'label',
|
||||
},
|
||||
items: [exampleLabel],
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper.text()).toContain(`${exampleLabel.title}`);
|
||||
expect(wrapper.findByTestId('label-color-box').attributes().style).toEqual(
|
||||
`background-color: rgb(228, 77, 42);`, // #E44D2A
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('rendering epic references', () => {
|
||||
it('displays epic title and reference', () => {
|
||||
buildWrapper({
|
||||
propsData: {
|
||||
char: '&',
|
||||
nodeProps: {
|
||||
referenceType: 'epic',
|
||||
},
|
||||
items: [exampleEpic],
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper.text()).toContain(`${exampleEpic.reference}`);
|
||||
expect(wrapper.text()).toContain(`${exampleEpic.title}`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('rendering a command (quick action)', () => {
|
||||
it('displays command name with a slash', () => {
|
||||
buildWrapper({
|
||||
propsData: {
|
||||
char: '/',
|
||||
command: jest.fn(),
|
||||
nodeType: 'reference',
|
||||
nodeProps: {
|
||||
referenceType: 'command',
|
||||
},
|
||||
|
@ -168,7 +246,6 @@ describe('~/content_editor/components/suggestions_dropdown', () => {
|
|||
buildWrapper({
|
||||
propsData: {
|
||||
char: ':',
|
||||
command: jest.fn(),
|
||||
nodeType: 'emoji',
|
||||
nodeProps: {},
|
||||
items: testEmojis,
|
||||
|
|
|
@ -178,7 +178,7 @@ describe('DiffsStoreActions', () => {
|
|||
});
|
||||
|
||||
describe('fetchDiffFilesMeta', () => {
|
||||
const endpointMetadata = '/fetch/diffs_metadata.json?view=inline';
|
||||
const endpointMetadata = '/fetch/diffs_metadata.json?view=inline&w=0';
|
||||
const noFilesData = { ...diffMetadata };
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -191,7 +191,7 @@ describe('DiffsStoreActions', () => {
|
|||
return testAction(
|
||||
diffActions.fetchDiffFilesMeta,
|
||||
{},
|
||||
{ endpointMetadata, diffViewType: 'inline' },
|
||||
{ endpointMetadata, diffViewType: 'inline', showWhitespace: true },
|
||||
[
|
||||
{ type: types.SET_LOADING, payload: true },
|
||||
{ type: types.SET_LOADING, payload: false },
|
||||
|
|
|
@ -17,7 +17,8 @@ RSpec.describe BulkImports::Common::Pipelines::EntityFinisher do
|
|||
bulk_import_entity_id: entity.id,
|
||||
bulk_import_entity_type: entity.source_type,
|
||||
pipeline_class: described_class.name,
|
||||
message: 'Entity finished'
|
||||
message: 'Entity finished',
|
||||
importer: 'gitlab_migration'
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
@ -60,7 +60,9 @@ RSpec.describe BulkImports::Pipeline::Runner do
|
|||
pipeline_step: :extractor,
|
||||
pipeline_class: 'BulkImports::MyPipeline',
|
||||
exception_class: exception_class,
|
||||
exception_message: exception_message
|
||||
exception_message: exception_message,
|
||||
message: "Pipeline failed",
|
||||
importer: 'gitlab_migration'
|
||||
)
|
||||
)
|
||||
end
|
||||
|
@ -89,7 +91,8 @@ RSpec.describe BulkImports::Pipeline::Runner do
|
|||
log_params(
|
||||
context,
|
||||
message: 'Aborting entity migration due to pipeline failure',
|
||||
pipeline_class: 'BulkImports::MyPipeline'
|
||||
pipeline_class: 'BulkImports::MyPipeline',
|
||||
importer: 'gitlab_migration'
|
||||
)
|
||||
)
|
||||
end
|
||||
|
@ -293,6 +296,7 @@ RSpec.describe BulkImports::Pipeline::Runner do
|
|||
bulk_import_id: context.bulk_import_id,
|
||||
bulk_import_entity_id: context.entity.id,
|
||||
bulk_import_entity_type: context.entity.source_type,
|
||||
importer: 'gitlab_migration',
|
||||
context_extra: context.extra
|
||||
}.merge(extra)
|
||||
end
|
||||
|
|
|
@ -34,7 +34,11 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
|
|||
image: 'image:1.0',
|
||||
default: {},
|
||||
services: ['postgres:9.1', 'mysql:5.5'],
|
||||
variables: { VAR: 'root', VAR2: { value: 'val 2', description: 'this is var 2' } },
|
||||
variables: {
|
||||
VAR: 'root',
|
||||
VAR2: { value: 'val 2', description: 'this is var 2' },
|
||||
VAR3: { value: %w[val3 val3b], description: 'this is var 3' }
|
||||
},
|
||||
after_script: ['make clean'],
|
||||
stages: %w(build pages release),
|
||||
cache: { key: 'k', untracked: true, paths: ['public/'] },
|
||||
|
@ -83,7 +87,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
|
|||
end
|
||||
|
||||
it 'sets correct variables value' do
|
||||
expect(root.variables_value).to eq('VAR' => 'root', 'VAR2' => 'val 2')
|
||||
expect(root.variables_value).to eq('VAR' => 'root', 'VAR2' => 'val 2', 'VAR3' => 'val3')
|
||||
end
|
||||
|
||||
describe '#leaf?' do
|
||||
|
|
|
@ -127,20 +127,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Variable do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when config value is an array' do
|
||||
let(:config) { { value: ['value'], description: 'description' } }
|
||||
|
||||
describe '#valid?' do
|
||||
it { is_expected.not_to be_valid }
|
||||
end
|
||||
|
||||
describe '#errors' do
|
||||
subject(:errors) { entry.errors }
|
||||
|
||||
it { is_expected.to include 'var1 config value must be an alphanumeric string' }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when config description is a symbol' do
|
||||
let(:config) { { value: 'value', description: :description } }
|
||||
|
||||
|
@ -209,4 +195,42 @@ RSpec.describe Gitlab::Ci::Config::Entry::Variable do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'ComplexArrayVariable' do
|
||||
context 'when allow_array_value metadata is false' do
|
||||
let(:config) { { value: %w[value value2], description: 'description' } }
|
||||
let(:metadata) { { allow_array_value: false } }
|
||||
|
||||
describe '#valid?' do
|
||||
it { is_expected.not_to be_valid }
|
||||
end
|
||||
|
||||
describe '#errors' do
|
||||
subject(:errors) { entry.errors }
|
||||
|
||||
it { is_expected.to include 'var1 config value must be an alphanumeric string' }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when allow_array_value metadata is true' do
|
||||
let(:config) { { value: %w[value value2], description: 'description' } }
|
||||
let(:metadata) { { allowed_value_data: %i[value description], allow_array_value: true } }
|
||||
|
||||
describe '#valid?' do
|
||||
it { is_expected.to be_valid }
|
||||
end
|
||||
|
||||
describe '#value' do
|
||||
subject(:value) { entry.value }
|
||||
|
||||
it { is_expected.to eq('value') }
|
||||
end
|
||||
|
||||
describe '#value_with_data' do
|
||||
subject(:value_with_data) { entry.value_with_data }
|
||||
|
||||
it { is_expected.to eq(value: 'value', description: 'description', value_options: %w[value value2]) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -98,6 +98,62 @@ RSpec.describe Gitlab::Ci::Config::Entry::Variables do
|
|||
it_behaves_like 'invalid config', /must be either a string or a hash/
|
||||
end
|
||||
|
||||
context 'when entry config value has unallowed value key-value pair and value is a string' do
|
||||
let(:config) do
|
||||
{ 'VARIABLE_1' => { value: 'value', description: 'variable 1' } }
|
||||
end
|
||||
|
||||
context 'when there is no allowed_value_data metadata' do
|
||||
it_behaves_like 'invalid config', /variable_1 config must be a string/
|
||||
end
|
||||
|
||||
context 'when metadata has allow_array_value and allowed_value_data' do
|
||||
let(:metadata) { { allowed_value_data: %i[value description], allow_array_value: true } }
|
||||
|
||||
let(:result) do
|
||||
{ 'VARIABLE_1' => 'value' }
|
||||
end
|
||||
|
||||
it_behaves_like 'valid config'
|
||||
|
||||
describe '#value_with_data' do
|
||||
it 'returns variable with data' do
|
||||
expect(entry.value_with_data).to eq(
|
||||
'VARIABLE_1' => { value: 'value', description: 'variable 1' }
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when entry config value has key-value pair and value is an array' do
|
||||
let(:config) do
|
||||
{ 'VARIABLE_1' => { value: %w[value1 value2], description: 'variable 1' } }
|
||||
end
|
||||
|
||||
context 'when there is no allowed_value_data metadata' do
|
||||
it_behaves_like 'invalid config', /variable_1 config value must be an alphanumeric string/
|
||||
end
|
||||
|
||||
context 'when metadata has allow_array_value and allowed_value_data' do
|
||||
let(:metadata) { { allowed_value_data: %i[value description], allow_array_value: true } }
|
||||
|
||||
let(:result) do
|
||||
{ 'VARIABLE_1' => 'value1' }
|
||||
end
|
||||
|
||||
it_behaves_like 'valid config'
|
||||
|
||||
describe '#value_with_data' do
|
||||
it 'returns variable with data' do
|
||||
expect(entry.value_with_data).to eq(
|
||||
'VARIABLE_1' => { value: 'value1', value_options: %w[value1 value2], description: 'variable 1' }
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when entry config value has key-value pair and hash' do
|
||||
let(:config) do
|
||||
{ 'VARIABLE_1' => { value: 'value 1', description: 'variable 1' },
|
||||
|
|
|
@ -51,6 +51,7 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do
|
|||
|
||||
before do
|
||||
stub_feature_flags(graphql_keyset_pagination_without_next_page_query: false)
|
||||
allow(GitlabSchema).to receive(:default_max_page_size).and_return(2)
|
||||
end
|
||||
|
||||
it 'invokes an extra query for the next page check' do
|
||||
|
|
|
@ -23,6 +23,7 @@ RSpec.describe 'Query.project(fullPath).ciConfigVariables(sha)' do
|
|||
ciConfigVariables(sha: "#{sha}") {
|
||||
key
|
||||
value
|
||||
valueOptions
|
||||
description
|
||||
}
|
||||
}
|
||||
|
@ -52,14 +53,22 @@ RSpec.describe 'Query.project(fullPath).ciConfigVariables(sha)' do
|
|||
post_graphql(query, current_user: user)
|
||||
|
||||
expect(graphql_data.dig('project', 'ciConfigVariables')).to contain_exactly(
|
||||
{
|
||||
'key' => 'KEY_VALUE_VAR',
|
||||
'value' => 'value x',
|
||||
'valueOptions' => nil,
|
||||
'description' => 'value of KEY_VALUE_VAR'
|
||||
},
|
||||
{
|
||||
'key' => 'DB_NAME',
|
||||
'value' => 'postgres',
|
||||
'valueOptions' => nil,
|
||||
'description' => nil
|
||||
},
|
||||
{
|
||||
'key' => 'ENVIRONMENT_VAR',
|
||||
'value' => 'env var value',
|
||||
'valueOptions' => ['env var value', 'env var value2'],
|
||||
'description' => 'env var description'
|
||||
}
|
||||
)
|
||||
|
|
|
@ -77,6 +77,7 @@ RSpec.describe BulkImports::CreatePipelineTrackersService do
|
|||
message: 'Pipeline skipped as source instance version not compatible with pipeline',
|
||||
bulk_import_entity_id: entity.id,
|
||||
bulk_import_id: entity.bulk_import_id,
|
||||
importer: 'gitlab_migration',
|
||||
pipeline_name: 'PipelineClass4',
|
||||
minimum_source_version: '15.1.0',
|
||||
maximum_source_version: nil,
|
||||
|
@ -87,6 +88,7 @@ RSpec.describe BulkImports::CreatePipelineTrackersService do
|
|||
message: 'Pipeline skipped as source instance version not compatible with pipeline',
|
||||
bulk_import_entity_id: entity.id,
|
||||
bulk_import_id: entity.bulk_import_id,
|
||||
importer: 'gitlab_migration',
|
||||
pipeline_name: 'PipelineClass5',
|
||||
minimum_source_version: '16.0.0',
|
||||
maximum_source_version: nil,
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe IncidentManagement::IssuableEscalationStatuses::PrepareUpdateService do
|
||||
RSpec.describe IncidentManagement::IssuableEscalationStatuses::PrepareUpdateService, factory_default: :keep do
|
||||
let_it_be(:project) { create_default(:project) }
|
||||
let_it_be(:escalation_status) { create(:incident_management_issuable_escalation_status, :triggered) }
|
||||
let_it_be(:user_with_permissions) { create(:user) }
|
||||
|
||||
|
@ -10,7 +11,7 @@ RSpec.describe IncidentManagement::IssuableEscalationStatuses::PrepareUpdateServ
|
|||
let(:issue) { escalation_status.issue }
|
||||
let(:status) { :acknowledged }
|
||||
let(:params) { { status: status } }
|
||||
let(:service) { IncidentManagement::IssuableEscalationStatuses::PrepareUpdateService.new(issue, current_user, params) }
|
||||
let(:service) { described_class.new(issue, current_user, params) }
|
||||
|
||||
subject(:result) { service.execute }
|
||||
|
||||
|
@ -71,9 +72,17 @@ RSpec.describe IncidentManagement::IssuableEscalationStatuses::PrepareUpdateServ
|
|||
end
|
||||
end
|
||||
|
||||
context 'when called without params' do
|
||||
context 'when called nil params' do
|
||||
let(:params) { nil }
|
||||
|
||||
it 'raises an exception' do
|
||||
expect { result }.to raise_error NoMethodError
|
||||
end
|
||||
end
|
||||
|
||||
context 'when called without params' do
|
||||
let(:params) { {} }
|
||||
|
||||
it_behaves_like 'successful response', {}
|
||||
end
|
||||
|
||||
|
|
|
@ -852,6 +852,24 @@ RSpec.describe Issues::UpdateService, :mailer do
|
|||
service.execute(issue)
|
||||
end
|
||||
|
||||
# At the moment of writting old associations are not necessary for update_task
|
||||
# and doing this will prevent fetching associations from the DB and comparing old and new labels
|
||||
it 'does not pass old_associations to the after_update method' do
|
||||
params = {
|
||||
update_task: {
|
||||
index: 1,
|
||||
checked: false,
|
||||
line_source: '- [x] Task 1',
|
||||
line_number: 1
|
||||
}
|
||||
}
|
||||
service = described_class.new(project: project, current_user: user, params: params)
|
||||
|
||||
expect(service).to receive(:after_update).with(issue, {})
|
||||
|
||||
service.execute(issue)
|
||||
end
|
||||
|
||||
it 'creates system note about task status change' do
|
||||
note1 = find_note('marked the checklist item **Task 1** as completed')
|
||||
note2 = find_note('marked the checklist item **Task 2** as completed')
|
||||
|
|
|
@ -108,6 +108,24 @@ RSpec.describe WorkItems::UpdateService do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when labels are updated' do
|
||||
let_it_be(:label_a) { create(:label, project: project) }
|
||||
let_it_be(:label_b) { create(:label, project: project) }
|
||||
let(:issuable) { work_item }
|
||||
|
||||
it_behaves_like 'broadcasting issuable labels updates' do
|
||||
def update_issuable(update_params)
|
||||
described_class.new(
|
||||
project: project,
|
||||
current_user: current_user,
|
||||
params: update_params,
|
||||
spam_params: spam_params,
|
||||
widget_params: widget_params
|
||||
).execute(work_item)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when updating state_event' do
|
||||
context 'when state_event is close' do
|
||||
let(:opts) { { state_event: 'close' } }
|
||||
|
|
|
@ -7,9 +7,12 @@ before_script:
|
|||
- bundle exec rake db:create
|
||||
|
||||
variables:
|
||||
KEY_VALUE_VAR:
|
||||
value: 'value x'
|
||||
description: 'value of KEY_VALUE_VAR'
|
||||
DB_NAME: postgres
|
||||
ENVIRONMENT_VAR:
|
||||
value: 'env var value'
|
||||
value: ['env var value', 'env var value2']
|
||||
description: 'env var description'
|
||||
|
||||
stages:
|
||||
|
|
|
@ -10008,7 +10008,6 @@
|
|||
- './spec/services/incident_management/issuable_escalation_statuses/after_update_service_spec.rb'
|
||||
- './spec/services/incident_management/issuable_escalation_statuses/build_service_spec.rb'
|
||||
- './spec/services/incident_management/issuable_escalation_statuses/create_service_spec.rb'
|
||||
- './spec/services/incident_management/issuable_escalation_statuses/prepare_update_service_spec.rb'
|
||||
- './spec/services/incident_management/pager_duty/create_incident_issue_service_spec.rb'
|
||||
- './spec/services/incident_management/pager_duty/process_webhook_service_spec.rb'
|
||||
- './spec/services/incident_management/timeline_events/create_service_spec.rb'
|
||||
|
|
|
@ -47,7 +47,7 @@ RSpec.shared_examples 'broadcasting issuable labels updates' do
|
|||
it 'triggers the GraphQL subscription' do
|
||||
expect(GraphqlTriggers).to receive(:issuable_labels_updated).with(issuable)
|
||||
|
||||
update_issuable({ add_label_ids: [label_b.id] })
|
||||
update_issuable(add_label_ids: [label_b.id])
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -55,7 +55,7 @@ RSpec.shared_examples 'broadcasting issuable labels updates' do
|
|||
it 'triggers the GraphQL subscription' do
|
||||
expect(GraphqlTriggers).to receive(:issuable_labels_updated).with(issuable)
|
||||
|
||||
update_issuable({ remove_label_ids: [label_a.id] })
|
||||
update_issuable(remove_label_ids: [label_a.id])
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -63,7 +63,7 @@ RSpec.shared_examples 'broadcasting issuable labels updates' do
|
|||
it 'does not trigger the GraphQL subscription' do
|
||||
expect(GraphqlTriggers).not_to receive(:issuable_labels_updated).with(issuable)
|
||||
|
||||
update_issuable({ label_ids: [label_a.id] })
|
||||
update_issuable(label_ids: [label_a.id])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -40,7 +40,8 @@ RSpec.describe BulkImports::EntityWorker do
|
|||
'bulk_import_entity_id' => entity.id,
|
||||
'bulk_import_id' => entity.bulk_import_id,
|
||||
'current_stage' => nil,
|
||||
'message' => 'Stage starting'
|
||||
'message' => 'Stage starting',
|
||||
'importer' => 'gitlab_migration'
|
||||
)
|
||||
)
|
||||
end
|
||||
|
@ -70,7 +71,8 @@ RSpec.describe BulkImports::EntityWorker do
|
|||
hash_including(
|
||||
'bulk_import_entity_id' => entity.id,
|
||||
'bulk_import_id' => entity.bulk_import_id,
|
||||
'current_stage' => nil
|
||||
'current_stage' => nil,
|
||||
'importer' => 'gitlab_migration'
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -81,14 +83,20 @@ RSpec.describe BulkImports::EntityWorker do
|
|||
'bulk_import_entity_id' => entity.id,
|
||||
'bulk_import_id' => entity.bulk_import_id,
|
||||
'current_stage' => nil,
|
||||
'message' => 'Error!'
|
||||
'message' => 'Error!',
|
||||
'importer' => 'gitlab_migration'
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
expect(Gitlab::ErrorTracking)
|
||||
.to receive(:track_exception)
|
||||
.with(exception, bulk_import_entity_id: entity.id, bulk_import_id: entity.bulk_import_id)
|
||||
.with(
|
||||
exception,
|
||||
bulk_import_entity_id: entity.id,
|
||||
bulk_import_id: entity.bulk_import_id,
|
||||
importer: 'gitlab_migration'
|
||||
)
|
||||
|
||||
subject
|
||||
end
|
||||
|
@ -105,7 +113,8 @@ RSpec.describe BulkImports::EntityWorker do
|
|||
'bulk_import_entity_id' => entity.id,
|
||||
'bulk_import_id' => entity.bulk_import_id,
|
||||
'current_stage' => 0,
|
||||
'message' => 'Stage running'
|
||||
'message' => 'Stage running',
|
||||
'importer' => 'gitlab_migration'
|
||||
)
|
||||
)
|
||||
end
|
||||
|
@ -133,7 +142,8 @@ RSpec.describe BulkImports::EntityWorker do
|
|||
hash_including(
|
||||
'bulk_import_entity_id' => entity.id,
|
||||
'bulk_import_id' => entity.bulk_import_id,
|
||||
'current_stage' => 0
|
||||
'current_stage' => 0,
|
||||
'importer' => 'gitlab_migration'
|
||||
)
|
||||
)
|
||||
end
|
||||
|
|
|
@ -45,7 +45,8 @@ RSpec.describe BulkImports::ExportRequestWorker do
|
|||
'exception_message' => 'Export error',
|
||||
'correlation_id_value' => anything,
|
||||
'bulk_import_id' => bulk_import.id,
|
||||
'bulk_import_entity_type' => entity.source_type
|
||||
'bulk_import_entity_type' => entity.source_type,
|
||||
'importer' => 'gitlab_migration'
|
||||
)
|
||||
).twice
|
||||
|
||||
|
@ -104,7 +105,8 @@ RSpec.describe BulkImports::ExportRequestWorker do
|
|||
'exception_message' => "undefined method `model_id' for nil:NilClass",
|
||||
'correlation_id_value' => anything,
|
||||
'bulk_import_id' => bulk_import.id,
|
||||
'bulk_import_entity_type' => entity.source_type
|
||||
'bulk_import_entity_type' => entity.source_type,
|
||||
'importer' => 'gitlab_migration'
|
||||
)
|
||||
).twice
|
||||
|
||||
|
|
|
@ -38,7 +38,8 @@ RSpec.describe BulkImports::PipelineWorker do
|
|||
hash_including(
|
||||
'pipeline_name' => 'FakePipeline',
|
||||
'bulk_import_entity_id' => entity.id,
|
||||
'bulk_import_id' => entity.bulk_import_id
|
||||
'bulk_import_id' => entity.bulk_import_id,
|
||||
'importer' => 'gitlab_migration'
|
||||
)
|
||||
)
|
||||
end
|
||||
|
@ -86,7 +87,8 @@ RSpec.describe BulkImports::PipelineWorker do
|
|||
'pipeline_tracker_id' => pipeline_tracker.id,
|
||||
'bulk_import_entity_id' => entity.id,
|
||||
'bulk_import_id' => entity.bulk_import_id,
|
||||
'message' => 'Unstarted pipeline not found'
|
||||
'message' => 'Unstarted pipeline not found',
|
||||
'importer' => 'gitlab_migration'
|
||||
)
|
||||
)
|
||||
end
|
||||
|
@ -124,7 +126,8 @@ RSpec.describe BulkImports::PipelineWorker do
|
|||
'pipeline_name' => 'FakePipeline',
|
||||
'bulk_import_entity_id' => entity.id,
|
||||
'bulk_import_id' => entity.bulk_import_id,
|
||||
'message' => 'Error!'
|
||||
'message' => 'Error!',
|
||||
'importer' => 'gitlab_migration'
|
||||
)
|
||||
)
|
||||
end
|
||||
|
@ -134,8 +137,9 @@ RSpec.describe BulkImports::PipelineWorker do
|
|||
.with(
|
||||
instance_of(StandardError),
|
||||
bulk_import_entity_id: entity.id,
|
||||
bulk_import_id: entity.bulk_import.id,
|
||||
pipeline_name: pipeline_tracker.pipeline_name
|
||||
bulk_import_id: entity.bulk_import_id,
|
||||
pipeline_name: pipeline_tracker.pipeline_name,
|
||||
importer: 'gitlab_migration'
|
||||
)
|
||||
|
||||
expect(BulkImports::EntityWorker)
|
||||
|
@ -184,7 +188,8 @@ RSpec.describe BulkImports::PipelineWorker do
|
|||
'pipeline_name' => 'FakePipeline',
|
||||
'bulk_import_entity_id' => entity.id,
|
||||
'bulk_import_id' => entity.bulk_import_id,
|
||||
'message' => 'Skipping pipeline due to failed entity'
|
||||
'message' => 'Skipping pipeline due to failed entity',
|
||||
'importer' => 'gitlab_migration'
|
||||
)
|
||||
)
|
||||
end
|
||||
|
@ -231,7 +236,8 @@ RSpec.describe BulkImports::PipelineWorker do
|
|||
hash_including(
|
||||
'pipeline_name' => 'FakePipeline',
|
||||
'bulk_import_entity_id' => entity.id,
|
||||
'bulk_import_id' => entity.bulk_import_id
|
||||
'bulk_import_id' => entity.bulk_import_id,
|
||||
'importer' => 'gitlab_migration'
|
||||
)
|
||||
)
|
||||
end
|
||||
|
@ -356,7 +362,8 @@ RSpec.describe BulkImports::PipelineWorker do
|
|||
'pipeline_name' => 'NdjsonPipeline',
|
||||
'bulk_import_entity_id' => entity.id,
|
||||
'message' => 'Pipeline timeout',
|
||||
'bulk_import_id' => entity.bulk_import_id
|
||||
'bulk_import_id' => entity.bulk_import_id,
|
||||
'importer' => 'gitlab_migration'
|
||||
)
|
||||
)
|
||||
end
|
||||
|
@ -384,7 +391,8 @@ RSpec.describe BulkImports::PipelineWorker do
|
|||
'pipeline_name' => 'NdjsonPipeline',
|
||||
'bulk_import_entity_id' => entity.id,
|
||||
'message' => 'Export from source instance failed: Error!',
|
||||
'bulk_import_id' => entity.bulk_import_id
|
||||
'bulk_import_id' => entity.bulk_import_id,
|
||||
'importer' => 'gitlab_migration'
|
||||
)
|
||||
)
|
||||
end
|
||||
|
|
|
@ -108,7 +108,7 @@ require (
|
|||
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a // indirect
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/text v0.3.8 // indirect
|
||||
golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
google.golang.org/api v0.74.0 // indirect
|
||||
|
|
|
@ -1280,8 +1280,9 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/time v0.0.0-20170424234030-8be79e1e0910/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
|
Loading…
Reference in New Issue