Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
d64d52a860
commit
cd0b43eb25
|
|
@ -13,19 +13,6 @@ Layout/FirstHashElementIndentation:
|
|||
- 'ee/app/services/timebox_report_service.rb'
|
||||
- 'ee/lib/ee/gitlab/ci/parsers.rb'
|
||||
- 'ee/lib/ee/gitlab/usage_data.rb'
|
||||
- 'ee/lib/elastic/latest/issue_class_proxy.rb'
|
||||
- 'ee/lib/gitlab/analytics/type_of_work/tasks_by_type.rb'
|
||||
- 'ee/lib/gitlab/ci/parsers/security/formatters/dependency_list.rb'
|
||||
- 'ee/lib/gitlab/graphql/aggregations/epics/lazy_epic_aggregate.rb'
|
||||
- 'ee/spec/controllers/admin/application_settings_controller_spec.rb'
|
||||
- 'ee/spec/controllers/ee/projects/jobs_controller_spec.rb'
|
||||
- 'ee/spec/controllers/ee/projects/variables_controller_spec.rb'
|
||||
- 'ee/spec/controllers/groups/epic_boards_controller_spec.rb'
|
||||
- 'ee/spec/controllers/groups/issues_controller_spec.rb'
|
||||
- 'ee/spec/controllers/projects/integrations/jira/issues_controller_spec.rb'
|
||||
- 'ee/spec/controllers/projects/repositories_controller_spec.rb'
|
||||
- 'ee/spec/controllers/projects/vulnerability_feedback_controller_spec.rb'
|
||||
- 'ee/spec/controllers/projects_controller_spec.rb'
|
||||
- 'ee/spec/factories/dependencies.rb'
|
||||
- 'ee/spec/finders/epics_finder_spec.rb'
|
||||
- 'ee/spec/finders/namespaces/free_user_cap/users_finder_spec.rb'
|
||||
|
|
|
|||
|
|
@ -49,16 +49,3 @@ Lint/AmbiguousOperatorPrecedence:
|
|||
- 'spec/lib/gitlab/regex_spec.rb'
|
||||
- 'spec/lib/gitlab/search/abuse_validators/no_abusive_term_length_validator_spec.rb'
|
||||
- 'spec/lib/gitlab/slash_commands/deploy_spec.rb'
|
||||
- 'spec/mailers/notify_spec.rb'
|
||||
- 'spec/models/appearance_spec.rb'
|
||||
- 'spec/models/ci/build_spec.rb'
|
||||
- 'spec/models/ci/runner_spec.rb'
|
||||
- 'spec/models/commit_spec.rb'
|
||||
- 'spec/models/concerns/pg_full_text_searchable_spec.rb'
|
||||
- 'spec/models/custom_emoji_spec.rb'
|
||||
- 'spec/models/environment_spec.rb'
|
||||
- 'spec/models/grafana_integration_spec.rb'
|
||||
- 'spec/models/integrations/chat_message/push_message_spec.rb'
|
||||
- 'spec/models/merge_request_diff_spec.rb'
|
||||
- 'spec/models/packages/package_file_spec.rb'
|
||||
- 'spec/models/prometheus_alert_spec.rb'
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ export default {
|
|||
:note-id="note.id"
|
||||
:note-url="note.url"
|
||||
>
|
||||
<span v-if="note.createdAt" class="d-none d-sm-inline">·</span>
|
||||
<span v-if="note.createdAt" class="gl-hidden sm:gl-inline">·</span>
|
||||
</note-header>
|
||||
<div class="gl-display-inline-flex">
|
||||
<abuse-report-note-actions
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ export default {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div :title="title" class="divergence-graph px-2 d-none d-md-block">
|
||||
<div :title="title" class="divergence-graph px-2 gl-hidden md:gl-block">
|
||||
<template v-if="distance">
|
||||
<graph-bar :count="distance" :max-commits="maxCommits" position="full" />
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import { visitUrl } from '~/lib/utils/url_utility';
|
|||
import { s__, __, n__ } from '~/locale';
|
||||
import {
|
||||
CC_VALIDATION_REQUIRED_ERROR,
|
||||
IDENTITY_VERIFICATION_REQUIRED_ERROR,
|
||||
CONFIG_VARIABLES_TIMEOUT,
|
||||
FILE_TYPE,
|
||||
VARIABLE_TYPE,
|
||||
|
|
@ -71,6 +72,8 @@ export default {
|
|||
VariableValuesListbox,
|
||||
CcValidationRequiredAlert: () =>
|
||||
import('ee_component/billings/components/cc_validation_required_alert.vue'),
|
||||
PipelineAccountVerificationAlert: () =>
|
||||
import('ee_component/vue_shared/components/pipeline_account_verification_alert.vue'),
|
||||
},
|
||||
directives: { SafeHtml },
|
||||
props: {
|
||||
|
|
@ -223,6 +226,9 @@ export default {
|
|||
ccRequiredError() {
|
||||
return this.error === CC_VALIDATION_REQUIRED_ERROR && !this.ccAlertDismissed;
|
||||
},
|
||||
identityVerificationRequiredError() {
|
||||
return this.error === IDENTITY_VERIFICATION_REQUIRED_ERROR;
|
||||
},
|
||||
variableTypeListboxItems() {
|
||||
return [
|
||||
{
|
||||
|
|
@ -390,6 +396,10 @@ export default {
|
|||
<template>
|
||||
<gl-form @submit.prevent="createPipeline">
|
||||
<cc-validation-required-alert v-if="ccRequiredError" class="gl-pb-5" @dismiss="dismissError" />
|
||||
<pipeline-account-verification-alert
|
||||
v-else-if="identityVerificationRequiredError"
|
||||
class="gl-mb-4"
|
||||
/>
|
||||
<gl-alert
|
||||
v-else-if="error"
|
||||
:title="errorTitle"
|
||||
|
|
|
|||
|
|
@ -12,3 +12,6 @@ export const TAG_REF_TYPE = 'tag';
|
|||
export const CC_VALIDATION_REQUIRED_ERROR = __(
|
||||
'Credit card required to be on file in order to run CI jobs',
|
||||
);
|
||||
export const IDENTITY_VERIFICATION_REQUIRED_ERROR = __(
|
||||
'Identity verification is required in order to run CI jobs',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ const mountPipelineNewForm = (el) => {
|
|||
const {
|
||||
// provide/inject
|
||||
projectRefsEndpoint,
|
||||
identityVerificationPath,
|
||||
|
||||
// props
|
||||
defaultBranch,
|
||||
|
|
@ -37,6 +38,12 @@ const mountPipelineNewForm = (el) => {
|
|||
apolloProvider,
|
||||
provide: {
|
||||
projectRefsEndpoint,
|
||||
identityVerificationPath,
|
||||
// Normally this will have a value from a helper. In this case, this is
|
||||
// set to true because the alert that uses this field is dynamically
|
||||
// rendered if a specific error is returned from the backend after
|
||||
// the create pipeline XHR request completes
|
||||
identityVerificationRequired: true,
|
||||
},
|
||||
render(createElement) {
|
||||
return createElement(PipelineNewForm, {
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ export default {
|
|||
class="d-block d-sm-flex flex-row-reverse justify-content-between align-items-start flex-lg-row-reverse"
|
||||
>
|
||||
<div
|
||||
class="commit-actions flex-row d-none d-sm-flex gl-align-items-center gl-flex-wrap justify-content-end"
|
||||
class="commit-actions flex-row gl-hidden sm:gl-flex gl-align-items-center gl-flex-wrap justify-content-end"
|
||||
>
|
||||
<div
|
||||
v-if="commit.signature_html"
|
||||
|
|
@ -129,7 +129,7 @@ export default {
|
|||
:img-src="authorAvatar"
|
||||
:img-alt="authorName"
|
||||
:img-size="32"
|
||||
class="avatar-cell d-none d-sm-block gl-my-2 gl-mr-4"
|
||||
class="avatar-cell gl-hidden sm:gl-block gl-my-2 gl-mr-4"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ export default {
|
|||
>
|
||||
{{ __('Show latest version') }}
|
||||
</gl-button>
|
||||
<div v-if="hasChanges" class="inline-parallel-buttons d-none gl-md-display-flex! ml-auto">
|
||||
<div v-if="hasChanges" class="inline-parallel-buttons gl-hidden md:gl-flex ml-auto">
|
||||
<diff-stats
|
||||
:diff-files-count-text="diffFilesCountText"
|
||||
:added-lines="addedLines"
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ export default {
|
|||
:img-src="author.avatar_url"
|
||||
:img-alt="author.name"
|
||||
:img-size="48"
|
||||
class="d-none d-sm-block new-comment"
|
||||
class="!gl-hidden sm:!gl-block new-comment"
|
||||
/>
|
||||
<diff-discussions
|
||||
v-if="imageDiscussions.length"
|
||||
|
|
|
|||
|
|
@ -508,7 +508,7 @@ export default {
|
|||
|
||||
<div
|
||||
v-if="diffFile.submodule_compare"
|
||||
class="file-actions d-none d-sm-flex gl-align-items-center gl-flex-wrap"
|
||||
class="file-actions gl-hidden sm:gl-flex gl-align-items-center gl-flex-wrap"
|
||||
>
|
||||
<gl-button
|
||||
v-gl-tooltip.hover
|
||||
|
|
|
|||
|
|
@ -550,7 +550,7 @@ export default {
|
|||
upcomingDeploymentCellClasses() {
|
||||
return [
|
||||
this.tableData.upcoming.spacing,
|
||||
{ 'gl-display-none gl-md-display-block': !this.upcomingDeployment },
|
||||
{ '!gl-hidden md:!gl-block': !this.upcomingDeployment },
|
||||
];
|
||||
},
|
||||
tableNameSpacingClass() {
|
||||
|
|
@ -643,7 +643,7 @@ export default {
|
|||
|
||||
<div
|
||||
v-if="!isFolder"
|
||||
class="table-section deployment-column d-none d-md-block"
|
||||
class="table-section deployment-column gl-hidden md:gl-block"
|
||||
:class="tableData.deploy.spacing"
|
||||
role="gridcell"
|
||||
data-testid="environment-deployment-id-cell"
|
||||
|
|
@ -678,7 +678,7 @@ export default {
|
|||
|
||||
<div
|
||||
v-if="!isFolder"
|
||||
class="table-section d-none d-md-block"
|
||||
class="table-section gl-hidden md:gl-block"
|
||||
:class="tableData.build.spacing"
|
||||
role="gridcell"
|
||||
data-testid="environment-build-cell"
|
||||
|
|
|
|||
|
|
@ -177,11 +177,11 @@ export default {
|
|||
<gl-loading-icon
|
||||
v-if="group.isChildrenLoading"
|
||||
size="lg"
|
||||
class="d-none d-sm-inline-flex flex-shrink-0 gl-mr-3"
|
||||
class="gl-hidden sm:gl-inline-flex flex-shrink-0 gl-mr-3"
|
||||
/>
|
||||
<a
|
||||
:class="{ 'gl-sm-display-flex': !group.isChildrenLoading }"
|
||||
class="gl-display-none gl-text-decoration-none! gl-mr-3"
|
||||
class="gl-hidden gl-text-decoration-none! gl-mr-3"
|
||||
:href="group.relativePath"
|
||||
:aria-label="group.name"
|
||||
>
|
||||
|
|
@ -270,7 +270,7 @@ export default {
|
|||
>
|
||||
<item-stats
|
||||
:item="group"
|
||||
class="group-stats gl-display-none gl-md-display-flex gl-align-items-center"
|
||||
class="group-stats gl-hidden md:gl-flex gl-align-items-center"
|
||||
/>
|
||||
<item-actions
|
||||
v-if="showActionsMenu"
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ export default {
|
|||
<template>
|
||||
<div class="d-flex-center gl-flex-nowrap text-nowrap js-ide-status-mr">
|
||||
<gl-icon name="merge-request" />
|
||||
<span class="ml-1 d-none d-sm-block">{{ s__('WebIDE|Merge request') }}</span>
|
||||
<span class="ml-1 gl-hidden sm:gl-block">{{ s__('WebIDE|Merge request') }}</span>
|
||||
<gl-link class="ml-1" :href="url">{{ text }}</gl-link>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -427,7 +427,7 @@ export default {
|
|||
<template #pipeline-status="{ issuable = {} }">
|
||||
<li
|
||||
v-if="issuable.headPipeline && issuable.headPipeline.detailedStatus"
|
||||
class="issuable-pipeline-status d-none d-sm-flex"
|
||||
class="issuable-pipeline-status gl-hidden sm:gl-flex"
|
||||
>
|
||||
<ci-icon :status="issuable.headPipeline.detailedStatus" use-link show-tooltip />
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -494,7 +494,7 @@ export default {
|
|||
<slot name="note-header-info"></slot>
|
||||
</template>
|
||||
<span v-if="commit" v-safe-html="actionText"></span>
|
||||
<span v-else-if="note.created_at" class="d-none d-sm-inline">·</span>
|
||||
<span v-else-if="note.created_at" class="gl-hidden sm:gl-inline">·</span>
|
||||
</note-header>
|
||||
<note-actions
|
||||
:author="author"
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import {
|
|||
import { getDraft, clearDraft, updateDraft } from '~/lib/utils/autosave';
|
||||
import csrf from '~/lib/utils/csrf';
|
||||
import { setUrlFragment } from '~/lib/utils/url_utility';
|
||||
import { s__, sprintf } from '~/locale';
|
||||
import { __, s__, sprintf } from '~/locale';
|
||||
import Tracking from '~/tracking';
|
||||
import MarkdownEditor from '~/vue_shared/components/markdown/markdown_editor.vue';
|
||||
import { trackSavedUsingEditor } from '~/vue_shared/components/markdown/tracking';
|
||||
|
|
@ -79,6 +79,9 @@ export default {
|
|||
format: {
|
||||
label: s__('WikiPage|Format'),
|
||||
},
|
||||
template: {
|
||||
label: __('Template'),
|
||||
},
|
||||
content: {
|
||||
label: s__('WikiPage|Content'),
|
||||
placeholder: s__('WikiPage|Write your content or drag files here…'),
|
||||
|
|
@ -335,7 +338,7 @@ export default {
|
|||
<div class="col-12">
|
||||
<gl-form-group :label="$options.i18n.title.label" label-for="wiki_title">
|
||||
<template v-if="!isTemplate" #description>
|
||||
<gl-icon class="-gl-mr-1" name="bulb" />
|
||||
<gl-icon name="bulb" />
|
||||
{{ titleHelpText }}
|
||||
<gl-link :href="helpPath" target="_blank">
|
||||
{{ $options.i18n.title.helpText.learnMore }}
|
||||
|
|
@ -354,15 +357,16 @@ export default {
|
|||
<input v-model="title" type="hidden" name="wiki[title]" />
|
||||
</gl-form-group>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 row-sm-10">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<gl-form-group :label="$options.i18n.format.label" label-for="wiki_format">
|
||||
<gl-form-select
|
||||
id="wiki_format"
|
||||
v-model="format"
|
||||
name="wiki[format]"
|
||||
:disabled="isContentEditorActive"
|
||||
class="form-control"
|
||||
:value="formatOptions.Markdown"
|
||||
>
|
||||
<option v-for="(key, label) of formatOptions" :key="key" :value="key">
|
||||
|
|
@ -371,18 +375,16 @@ export default {
|
|||
</gl-form-select>
|
||||
</gl-form-group>
|
||||
</div>
|
||||
<div v-if="!isTemplate && templates.length" class="col-sm-6">
|
||||
<gl-form-group :label="$options.i18n.template.label" label-for="wiki_template">
|
||||
<wiki-template :format="format" :templates="templates" @input="setTemplate" />
|
||||
</gl-form-group>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-12 row-sm-5">
|
||||
<gl-form-group :label="$options.i18n.content.label" label-for="wiki_content">
|
||||
<wiki-template
|
||||
v-if="!isTemplate && templates.length"
|
||||
:format="format"
|
||||
:templates="templates"
|
||||
class="gl-mb-4"
|
||||
@input="setTemplate"
|
||||
/>
|
||||
<markdown-editor
|
||||
ref="markdownEditor"
|
||||
v-model="content"
|
||||
|
|
@ -402,7 +404,7 @@ export default {
|
|||
@keydown.ctrl.enter="submitFormWithShortcut"
|
||||
@keydown.meta.enter="submitFormWithShortcut"
|
||||
/>
|
||||
<div class="form-text gl-text-gray-600">
|
||||
<template #description>
|
||||
<gl-sprintf
|
||||
v-if="displayWikiSpecificMarkdownHelp && !isTemplate"
|
||||
:message="$options.i18n.linksHelpText"
|
||||
|
|
@ -421,7 +423,7 @@ export default {
|
|||
></template
|
||||
>
|
||||
</gl-sprintf>
|
||||
</div>
|
||||
</template>
|
||||
</gl-form-group>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ export default {
|
|||
v-model="selectedTemplate"
|
||||
:items="templatesList"
|
||||
searchable
|
||||
block
|
||||
:toggle-text="toggleText"
|
||||
:search-placeholder="$options.i18n.searchTemplates"
|
||||
:no-results-text="$options.i18n.noMatchingTemplates"
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ export default {
|
|||
{{ metricDetailsLabel }}
|
||||
</span>
|
||||
</gl-button>
|
||||
<gl-modal :modal-id="modalId" :title="header" size="lg" footer-class="d-none" scrollable>
|
||||
<gl-modal :modal-id="modalId" :title="header" size="lg" footer-class="!gl-hidden" scrollable>
|
||||
<div class="gl-display-flex gl-align-items-center gl-justify-content-space-between">
|
||||
<div class="gl-display-flex gl-align-items-center" data-testid="performance-bar-summary">
|
||||
<div v-for="(value, name) in metricDetailsSummary" :key="name" class="gl-pr-8">
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<th id="name" scope="col">{{ s__('ProjectFileTree|Name') }}</th>
|
||||
<th id="last-commit" scope="col" class="d-none d-sm-table-cell">{{ __('Last commit') }}</th>
|
||||
<th id="last-commit" scope="col" class="gl-hidden sm:gl-table-cell">
|
||||
{{ __('Last commit') }}
|
||||
</th>
|
||||
<th id="last-update" scope="col" class="text-right">{{ __('Last update') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
|
|
|||
|
|
@ -248,7 +248,7 @@ export default {
|
|||
class="ml-1"
|
||||
/>
|
||||
</td>
|
||||
<td class="d-none d-sm-table-cell tree-commit cursor-default">
|
||||
<td class="gl-hidden sm:gl-table-cell tree-commit cursor-default">
|
||||
<gl-link
|
||||
v-if="commitData"
|
||||
v-safe-html:[$options.safeHtmlConfig]="commitData.titleHtml"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
const hide = (el) => el.classList.add('d-none');
|
||||
const show = (el) => el.classList.remove('d-none');
|
||||
const hide = (el) => el.classList.add('!gl-hidden');
|
||||
const show = (el) => el.classList.remove('!gl-hidden');
|
||||
|
||||
const setupCollapsibleInput = (el) => {
|
||||
const collapsedEl = el.querySelector('.js-collapsed');
|
||||
|
|
@ -35,9 +35,9 @@ const setupCollapsibleInput = (el) => {
|
|||
* Usage in HAML
|
||||
*
|
||||
* .js-collapsible-input
|
||||
* .js-collapsed{ class: ('d-none' if is_expanded) }
|
||||
* .js-collapsed{ class: ('!gl-hidden' if is_expanded) }
|
||||
* = input
|
||||
* .js-expanded{ class: ('d-none' if !is_expanded) }
|
||||
* .js-expanded{ class: ('!gl-hidden' if !is_expanded) }
|
||||
* = big_input
|
||||
*/
|
||||
export default () => {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ export default {
|
|||
<div class="form-group js-description-input">
|
||||
<label for="snippet-description">{{ s__('Snippets|Description (optional)') }}</label>
|
||||
<div class="js-collapsible-input">
|
||||
<div class="js-collapsed" :class="{ 'd-none': value }">
|
||||
<div class="js-collapsed" :class="{ '!gl-hidden': value }">
|
||||
<gl-form-textarea
|
||||
class="form-control"
|
||||
rows="2"
|
||||
|
|
@ -43,7 +43,7 @@ export default {
|
|||
</div>
|
||||
<markdown-field
|
||||
class="js-expanded"
|
||||
:class="{ 'd-none': !value }"
|
||||
:class="{ '!gl-hidden': !value }"
|
||||
:add-spacing-classes="false"
|
||||
:markdown-preview-path="markdownPreviewPath"
|
||||
:markdown-docs-path="markdownDocsPath"
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export default {
|
|||
<div class="gl-pl-7">
|
||||
<table class="table m-0">
|
||||
<thead class="thead-white text-nowrap">
|
||||
<tr class="d-none d-sm-table-row">
|
||||
<tr class="gl-hidden sm:gl-table-row">
|
||||
<th>{{ __('Artifact') }}</th>
|
||||
<th>{{ __('Job') }}</th>
|
||||
</tr>
|
||||
|
|
|
|||
|
|
@ -307,7 +307,7 @@ export default {
|
|||
/>
|
||||
</div>
|
||||
|
||||
<h4 class="gl-display-block d-md-none my-3">
|
||||
<h4 class="gl-block md:gl-hidden my-3">
|
||||
<slot name="title"></slot>
|
||||
</h4>
|
||||
|
||||
|
|
|
|||
|
|
@ -343,7 +343,7 @@ export default {
|
|||
:note-url="note.url"
|
||||
:is-internal-note="note.internal"
|
||||
>
|
||||
<span v-if="note.createdAt" class="d-none d-sm-inline">·</span>
|
||||
<span v-if="note.createdAt" class="gl-hidden sm:gl-inline">·</span>
|
||||
</note-header>
|
||||
<div class="gl-display-inline-flex">
|
||||
<note-actions
|
||||
|
|
|
|||
|
|
@ -143,7 +143,9 @@ ul.wiki-pages-list.content-list {
|
|||
}
|
||||
}
|
||||
|
||||
.wiki-form .markdown-area {
|
||||
.wiki-form .markdown-area,
|
||||
.wiki-form .ProseMirror {
|
||||
min-height: min(20vh, 320px);
|
||||
max-height: 55vh;
|
||||
}
|
||||
|
||||
|
|
@ -211,4 +213,4 @@ ul.wiki-pages-list.content-list {
|
|||
.gl-disclosure-dropdown {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,6 +76,23 @@ module Ci
|
|||
current_user.user_preference.visibility_pipeline_id_type
|
||||
end
|
||||
|
||||
def new_pipeline_data(project)
|
||||
{
|
||||
project_id: project.id,
|
||||
pipelines_path: project_pipelines_path(project),
|
||||
default_branch: project.default_branch,
|
||||
pipelines_editor_path: project_ci_pipeline_editor_path(project),
|
||||
can_view_pipeline_editor: can_view_pipeline_editor?(project),
|
||||
ref_param: params[:ref] || project.default_branch,
|
||||
var_param: params[:var].to_json,
|
||||
file_param: params[:file_var].to_json,
|
||||
project_path: project.full_path,
|
||||
project_refs_endpoint: refs_project_path(project, sort: 'updated_desc'),
|
||||
settings_link: project_settings_ci_cd_path(project),
|
||||
max_warnings: ::Gitlab::Ci::Warnings::MAX_LIMIT
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def show_jenkins_ci_prompt(project)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
module Ci
|
||||
class DailyBuildGroupReportResult < Ci::ApplicationRecord
|
||||
include Ci::Partitionable
|
||||
|
||||
PARAM_TYPES = %w[coverage].freeze
|
||||
|
||||
belongs_to :last_pipeline, class_name: 'Ci::Pipeline', foreign_key: :last_pipeline_id,
|
||||
|
|
@ -11,6 +13,8 @@ module Ci
|
|||
|
||||
validates :data, json_schema: { filename: "daily_build_group_report_result_data" }
|
||||
|
||||
partitionable scope: :last_pipeline
|
||||
|
||||
scope :by_ref_path, ->(ref_path) { where(ref_path: ref_path) }
|
||||
scope :by_projects, ->(ids) { where(project_id: ids) }
|
||||
scope :by_group, ->(group_id) { where(group_id: group_id) }
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ module Ci
|
|||
Ci::BuildTraceChunk
|
||||
Ci::BuildTraceMetadata
|
||||
Ci::BuildPendingState
|
||||
Ci::DailyBuildGroupReportResult
|
||||
Ci::JobAnnotation
|
||||
Ci::JobArtifact
|
||||
Ci::JobVariable
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
- only_key_value = local_assigns.fetch(:only_key_value, false)
|
||||
|
||||
%li.ci-variable-row.m-0.d-none.d-sm-block
|
||||
%li.ci-variable-row.m-0.gl-hidden.sm:gl-block
|
||||
.d-flex.gl-w-full.gl-align-items-center.pb-2
|
||||
.bold.table-section.section-15.gl-mr-3
|
||||
= s_('CiVariables|Type')
|
||||
|
|
|
|||
|
|
@ -26,6 +26,6 @@
|
|||
.nav-controls
|
||||
= render 'shared/projects/search_form'
|
||||
= render 'filter'
|
||||
= link_button_to nil, topic_explore_projects_path(@topic.name, rss_url_options), title: s_("Topics|Subscribe to the new projects feed"), class: 'd-none d-sm-inline-flex has-tooltip', icon: 'rss'
|
||||
= link_button_to nil, topic_explore_projects_path(@topic.name, rss_url_options), title: s_("Topics|Subscribe to the new projects feed"), class: 'gl-hidden sm:gl-inline-flex has-tooltip', icon: 'rss'
|
||||
|
||||
= render 'projects', projects: @projects
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
.nav-block.activities
|
||||
= render 'shared/event_filter', show_group_events: @group.supports_events?
|
||||
.controls
|
||||
= render Pajamas::ButtonComponent.new(href: group_path(@group, rss_url_options), icon: 'rss', button_options: { class: 'd-none d-sm-inline-flex has-tooltip', title: _('Subscribe') })
|
||||
= render Pajamas::ButtonComponent.new(href: group_path(@group, rss_url_options), icon: 'rss', button_options: { class: 'gl-hidden sm:gl-inline-flex has-tooltip', title: _('Subscribe') })
|
||||
|
||||
.content_list
|
||||
.loading
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@
|
|||
-# total_pages: total number of pages
|
||||
-# per_page: number of items to fetch per page
|
||||
-# remote: data-remote
|
||||
%li.page-item.disabled.d-none.d-md-block
|
||||
%li.page-item.disabled.gl-hidden.md:gl-block
|
||||
= link_to raw(t('views.pagination.truncate')), '#', class: 'page-link'
|
||||
|
|
|
|||
|
|
@ -10,5 +10,5 @@
|
|||
('sibling' if page.next? || page.prev?),
|
||||
('js-first-button' if page.first?),
|
||||
('js-last-button' if page.last?),
|
||||
('d-none d-md-block' if !page.current?)] }
|
||||
('!gl-hidden md:!gl-block' if !page.current?)] }
|
||||
= link_to page, url, { remote: remote, rel: page.next? ? 'next' : page.prev? ? 'prev' : nil, class: ['page-link', active_when(page.current?)] }
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
- is_project_overview = local_assigns.fetch(:is_project_overview, false)
|
||||
|
||||
.nav-block.d-none.d-sm-flex.activities.gl-static
|
||||
.nav-block.activities.gl-static
|
||||
= render 'shared/event_filter'
|
||||
.controls.gl-display-flex
|
||||
= link_button_to nil, project_path(@project, rss_url_options), title: s_("ProjectActivityRSS|Subscribe"), class: 'd-none d-sm-inline-flex has-tooltip', icon: 'rss'
|
||||
.controls.gl-flex
|
||||
= link_button_to nil, project_path(@project, rss_url_options), title: s_("ProjectActivityRSS|Subscribe"), class: '!gl-hidden sm:!gl-inline-flex has-tooltip', icon: 'rss'
|
||||
- if is_project_overview && can?(current_user, :download_code, @project)
|
||||
.project-code-holder.gl-hidden.md:gl-inline-flex.gl-ml-2
|
||||
= render "projects/buttons/code", dropdown_class: 'dropdown-menu-right', ref: @ref
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
.js-file-title.file-title-flex-parent
|
||||
= render 'projects/blob/header_content', blob: blob
|
||||
|
||||
.file-actions.d-none.d-sm-block
|
||||
.file-actions.gl-hidden.sm:gl-block
|
||||
.btn-group{ role: "group" }<
|
||||
= copy_blob_source_button(blob)
|
||||
= download_blob_button(blob)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
- if blob.rich_viewer && blob.extension != 'geojson'
|
||||
- add_page_startup_api_call local_assigns.fetch(:viewer_url) { url_for(safe_params.merge(viewer: blob.rich_viewer.type, format: :json)) }
|
||||
|
||||
.info-well.d-none.d-sm-block
|
||||
.info-well.gl-hidden.sm:gl-block
|
||||
.well-segment
|
||||
%ul.blob-commit-info
|
||||
= render 'projects/commits/commit', commit: @last_commit, project: @project, ref: @ref
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
- if branch.name != @repository.root_ref
|
||||
.js-branch-divergence-graph
|
||||
|
||||
.pipeline-status.d-none.d-md-block<
|
||||
.pipeline-status.gl-hidden.md:gl-block<
|
||||
- if commit_status
|
||||
= render 'ci/status/icon', status: commit_status
|
||||
- elsif show_commit_status
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#{ s_('CommitBoxTitle|Commit') }
|
||||
%span.commit-sha{ data: { testid: 'commit-sha-content' } }= @commit.short_id
|
||||
= clipboard_button(text: @commit.id, title: _('Copy commit SHA'))
|
||||
%span.d-none.d-sm-inline= _('authored')
|
||||
%span.gl-hidden.sm:gl-inline= _('authored')
|
||||
#{time_ago_with_tooltip(@commit.authored_date)}
|
||||
%span= s_('ByAuthor|by')
|
||||
= author_avatar(@commit, size: 24, has_tooltip: false)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
- add_page_specific_style 'page_bundles/commit_description'
|
||||
|
||||
%li{ class: ["commit flex-row", ("js-toggle-container" if collapsible)], id: "commit-#{commit.short_id}" }
|
||||
.avatar-cell.d-none.d-sm-block
|
||||
.avatar-cell.gl-hidden.sm:gl-block
|
||||
= author_avatar(commit, size: 40, has_tooltip: false)
|
||||
|
||||
.commit-detail.flex-list.gl-display-flex.gl-justify-content-space-between.gl-align-items-center.gl-flex-grow-1.gl-min-w-0
|
||||
|
|
@ -75,7 +75,7 @@
|
|||
|
||||
.js-commit-pipeline-status{ data: { endpoint: pipelines_project_commit_path(project, commit.id, ref: ref) } }
|
||||
|
||||
.commit-sha-group.btn-group.d-none.d-sm-flex
|
||||
.commit-sha-group.btn-group.gl-hidden.sm:gl-flex
|
||||
.label.label-monospace.monospace
|
||||
= commit.short_id
|
||||
= clipboard_button(text: commit.id, category: :primary, size: :medium, title: _("Copy commit SHA"))
|
||||
|
|
|
|||
|
|
@ -19,17 +19,17 @@
|
|||
#js-author-dropdown{ data: { 'commits_path': project_commits_path(@project), 'project_id': @project.id } }
|
||||
.tree-controls
|
||||
- if @merge_request.present?
|
||||
.control.d-none.d-md-block
|
||||
.control.gl-hidden.md:gl-block
|
||||
= link_button_to _("View open merge request"), project_merge_request_path(@project, @merge_request)
|
||||
- elsif create_mr_button?(from: @ref, source_project: @project)
|
||||
.control.d-none.d-md-block
|
||||
.control.gl-hidden.md:gl-block
|
||||
= render Pajamas::ButtonComponent.new(variant: :confirm, href: create_mr_path(from: @ref, source_project: @project)) do
|
||||
= _("Create merge request")
|
||||
|
||||
.control
|
||||
= form_tag(project_commits_path(@project, @id, ref_type: @ref_type), method: :get, class: 'commits-search-form js-signature-container', data: { 'signatures-path' => namespace_project_signatures_path(ref_type: @ref_type)}) do
|
||||
= search_field_tag :search, params[:search], { placeholder: _('Search by message'), id: 'commits-search', class: 'form-control gl-form-input input-short gl-mt-3 gl-sm-mt-0 gl-min-w-full', spellcheck: false }
|
||||
.control.d-none.d-md-block
|
||||
.control.gl-hidden.md:gl-block
|
||||
= link_button_to nil, project_commits_path(@project, @id, rss_url_options), title: _("Commits feed"), icon: 'rss'
|
||||
|
||||
= render_if_exists 'projects/commits/mirror_status'
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@
|
|||
= render "projects/diffs/file_header", diff_file: diff_file, url: "##{file_hash}"
|
||||
|
||||
- if diff_file.submodule?
|
||||
.file-actions.d-none.d-sm-block
|
||||
.file-actions.gl-hidden.sm:gl-block
|
||||
= submodule_diff_compare_link(diff_file)
|
||||
|
||||
- unless diff_file.submodule?
|
||||
.file-actions.gl-display-none.gl-sm-display-flex
|
||||
.file-actions.gl-hidden.sm:gl-flex
|
||||
#js-diff-stats{ data: diff_file_stats_data(diff_file) }
|
||||
- if diff_file.blob&.readable_text?
|
||||
- unless @diff_notes_disabled
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
by
|
||||
%a{ href: user_path(@build.user) }
|
||||
%span.d-none.d-sm-inline
|
||||
%span.gl-hidden.sm:gl-inline
|
||||
= render Pajamas::AvatarComponent.new(@build.user, size: 24, alt: "")
|
||||
%strong{ data: { toggle: 'tooltip', placement: 'top', title: @build.user.to_reference } }
|
||||
= @build.user.name
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
.gl-new-card-empty.gl-px-5.gl-py-4= _('There are currently no mirrored repositories.')
|
||||
- else
|
||||
%table.table.b-table.gl-table.b-table-stacked-md
|
||||
%thead.d-none.d-md-table-header-group
|
||||
%thead.gl-hidden.md:gl-table-header-group
|
||||
%tr
|
||||
%th= _('Repository')
|
||||
%th= _('Direction')
|
||||
|
|
|
|||
|
|
@ -5,15 +5,4 @@
|
|||
%h1.page-title.gl-font-size-h-display
|
||||
= s_('Pipeline|Run pipeline')
|
||||
|
||||
#js-new-pipeline{ data: { project_id: @project.id,
|
||||
pipelines_path: project_pipelines_path(@project),
|
||||
default_branch: @project.default_branch,
|
||||
pipelines_editor_path: project_ci_pipeline_editor_path(@project),
|
||||
can_view_pipeline_editor: can_view_pipeline_editor?(@project),
|
||||
ref_param: params[:ref] || @project.default_branch,
|
||||
var_param: params[:var].to_json,
|
||||
file_param: params[:file_var].to_json,
|
||||
project_path: @project.full_path,
|
||||
project_refs_endpoint: refs_project_path(@project, sort: 'updated_desc'),
|
||||
settings_link: project_settings_ci_cd_path(@project),
|
||||
max_warnings: ::Gitlab::Ci::Warnings::MAX_LIMIT } }
|
||||
#js-new-pipeline{ data: new_pipeline_data(@project) }
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
%col{ width: "50%" }
|
||||
- if can_admin_project
|
||||
%col
|
||||
%thead.d-none.d-md-table-header-group
|
||||
%thead.gl-hidden.md:gl-table-header-group
|
||||
%tr
|
||||
%th
|
||||
= s_('ProtectedBranch|Tag')
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
- @force_desktop_expanded_sidebar = true
|
||||
- add_form_class = 'gl-display-none' if !form_errors(@application)
|
||||
- hide_class = 'gl-display-none' if form_errors(@application)
|
||||
- add_form_class = 'gl-hidden' if !form_errors(@application)
|
||||
- hide_class = 'gl-hidden' if form_errors(@application)
|
||||
|
||||
.settings-section.js-search-settings-section
|
||||
.settings-sticky-header
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
- if @applications.any?
|
||||
.table-holder
|
||||
%table.table.b-table.gl-table.b-table-stacked-sm.-gl-mt-1.gl-mb-n2
|
||||
%thead.d-none.d-md-table-header-group
|
||||
%thead.gl-hidden.md:gl-table-header-group
|
||||
%tr
|
||||
%th= _('Name')
|
||||
%th= _('Callback URL')
|
||||
|
|
@ -78,7 +78,7 @@
|
|||
- if @authorized_tokens.any?
|
||||
.table-holder
|
||||
%table.table.b-table.gl-table.b-table-stacked-sm.-gl-mt-1.gl-mb-n2
|
||||
%thead.d-none.d-md-table-header-group
|
||||
%thead.gl-hidden.md:gl-table-header-group
|
||||
%tr
|
||||
%th= _('Name')
|
||||
%th= _('Authorized At')
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
%thead
|
||||
%tr
|
||||
%th= _('Status')
|
||||
%th.d-none.d-sm-table-cell= _('Trigger')
|
||||
%th.gl-hidden.sm:gl-table-cell= _('Trigger')
|
||||
%th= _('Elapsed time')
|
||||
%th= _('Request time')
|
||||
%th
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
%tr
|
||||
%td
|
||||
= render partial: 'shared/hook_logs/status_label', locals: { hook_log: hook_log }
|
||||
%td.d-none.d-sm-table-cell
|
||||
%td.gl-hidden.sm:gl-table-cell
|
||||
= gl_badge_tag hook_log.trigger.singularize.titleize, { size: :sm }
|
||||
%td
|
||||
#{number_with_precision(hook_log.execution_duration, precision: 2)} sec
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
%a.gitlab-logo-wrapper{ href: url_for(only_path: false, overwrite_params: nil), title: 'View on GitLab', target: '_blank', rel: 'noopener noreferrer' }
|
||||
%img.gitlab-logo{ src: image_url('ext_snippet_icons/logo.svg'), alt: "GitLab logo" }
|
||||
|
||||
.file-actions.d-none.d-sm-block
|
||||
.file-actions.gl-hidden.sm:gl-block
|
||||
.btn-group{ role: "group" }<
|
||||
= embedded_copy_snippet_button(blob)
|
||||
= embedded_raw_snippet_button(@snippet, blob)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
%aside.right-sidebar.right-sidebar-expanded.wiki-sidebar.js-wiki-sidebar.js-right-sidebar{ data: { "offset-top" => "50", "spy" => "affix" }, 'aria-label': _('Wiki') }
|
||||
.sidebar-container
|
||||
.block.gl-mb-3.gl-mx-5.gl-block.sm:gl-hidden{ class: '!gl-pt-0' }
|
||||
%a.gutter-toggle.gl-float-right.d-block.d-md-none.js-sidebar-wiki-toggle{ href: "#" }
|
||||
%a.gutter-toggle.gl-float-right.gl-block.md:gl-hidden.js-sidebar-wiki-toggle{ href: "#" }
|
||||
= sprite_icon('chevron-double-lg-right', css_class: 'gl-icon')
|
||||
|
||||
- if @sidebar_error.present?
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
.page-content-header
|
||||
.header-main-content
|
||||
%strong= markdown_field(commit, :title)
|
||||
%span.d-none.d-sm-inline= _('authored')
|
||||
%span.gl-hidden.sm:gl-inline= _('authored')
|
||||
#{time_ago_with_tooltip(commit.authored_date)}
|
||||
%span= s_('ByAuthor|by')
|
||||
= author_avatar(commit, size: 24, has_tooltip: false)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
%tr.key-list-item
|
||||
%td{ data: { label: s_('Profiles|Key') } }
|
||||
%div{ class: 'gl-display-flex! gl-pl-0!' }
|
||||
= sprite_icon('key', css_class: "settings-list-icon d-none d-sm-inline gl-mr-2")
|
||||
= sprite_icon('key', css_class: "settings-list-icon gl-hidden sm:gl-inline gl-mr-2")
|
||||
.gl-display-flex.gl-flex-direction-column.gl-text-truncate
|
||||
%p.gl-text-truncate.gl-m-0
|
||||
%code= key.fingerprint
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
- if @gpg_keys.any?
|
||||
.table-holder
|
||||
%table.table.b-table.gl-table.b-table-stacked-md.-gl-mt-1.gl-mb-n2.ssh-keys-list
|
||||
%thead.d-none.d-md-table-header-group
|
||||
%thead.gl-hidden.md:gl-table-header-group
|
||||
%tr
|
||||
%th= s_('Profiles|Key')
|
||||
%th= _('Status')
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
- if @keys.any?
|
||||
.table-holder
|
||||
%table.table.b-table.gl-table.b-table-stacked-md.-gl-mt-1.gl-mb-n2.ssh-keys-list{ data: { testid: 'ssh-keys-list' } }
|
||||
%thead.d-none.d-md-table-header-group
|
||||
%thead.gl-hidden.md:gl-table-header-group
|
||||
%tr
|
||||
%th= _('Title')
|
||||
%th= s_('Profiles|Key')
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ property_description: ""
|
|||
value_description: ""
|
||||
extra_properties:
|
||||
identifiers:
|
||||
product_section: dev
|
||||
product_stage: manage
|
||||
product_group: foundations
|
||||
product_section: ci
|
||||
product_stage: package
|
||||
product_group: package_registry
|
||||
milestone: "13.4"
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41668
|
||||
distributions:
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ identifiers:
|
|||
- user
|
||||
product_section: core_platform
|
||||
product_stage: manage
|
||||
product_group: foundations
|
||||
product_group: personal_productivity
|
||||
milestone: '16.11'
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/451458
|
||||
distributions:
|
||||
|
|
|
|||
|
|
@ -5,4 +5,4 @@ rollout_issue_url:
|
|||
milestone: '14.8'
|
||||
type: ops
|
||||
group: group::environments
|
||||
default_enabled: false
|
||||
default_enabled: true
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ key_path: redis_hll_counters.count_distinct_user_id_from_click_expand_panel_on_s
|
|||
description: Monthly count of unique users who expanded a settings panel
|
||||
product_section: core_platform
|
||||
product_stage: manage
|
||||
product_group: foundations
|
||||
product_group: personal_productivity
|
||||
performance_indicator_type: []
|
||||
value_type: number
|
||||
status: active
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ key_path: redis_hll_counters.count_distinct_user_id_from_click_expand_panel_on_s
|
|||
description: Weekly count of unique users who expanded a settings panel
|
||||
product_section: core_platform
|
||||
product_stage: manage
|
||||
product_group: foundations
|
||||
product_group: personal_productivity
|
||||
performance_indicator_type: []
|
||||
value_type: number
|
||||
status: active
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
"engineering_analytics",
|
||||
"engineering_productivity",
|
||||
"environments",
|
||||
"foundations",
|
||||
"fulfillment_platform",
|
||||
"gdk",
|
||||
"geo",
|
||||
|
|
@ -47,6 +46,7 @@
|
|||
"observability",
|
||||
"optimize",
|
||||
"package_registry",
|
||||
"personal_productivity",
|
||||
"pipeline_authoring",
|
||||
"pipeline_execution",
|
||||
"pipeline_security",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
migration_job_name: BackfillPartitionIdCiDailyBuildGroupReportResult
|
||||
description: Fixes incorrect values for ci_daily_build_group_report_results being in the wrong partition
|
||||
feature_category: ci_scaling
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/153236
|
||||
milestone: '17.1'
|
||||
queued_migration_version: 20240516123512
|
||||
finalize_after: '2024-06-01'
|
||||
finalized_by: # version of the migration that finalized this BBM
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddPartitionIdToCiDailyBuildGroupReportResult < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.1'
|
||||
|
||||
def change
|
||||
add_column(:ci_daily_build_group_report_results, :partition_id, :bigint, default: 100, null: false)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class QueueBackfillPartitionIdCiDailyBuildGroupReportResult < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.1'
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_ci
|
||||
|
||||
MIGRATION = 'BackfillPartitionIdCiDailyBuildGroupReportResult'
|
||||
DELAY_INTERVAL = 2.minutes
|
||||
BATCH_SIZE = 5000
|
||||
SUB_BATCH_SIZE = 200
|
||||
|
||||
def up
|
||||
queue_batched_background_migration(
|
||||
MIGRATION,
|
||||
:ci_daily_build_group_report_results,
|
||||
:id,
|
||||
job_interval: DELAY_INTERVAL,
|
||||
batch_size: BATCH_SIZE,
|
||||
sub_batch_size: SUB_BATCH_SIZE
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
delete_batched_background_migration(MIGRATION, :ci_daily_build_group_report_results, :id, [])
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
15c4257ca5b38f5db83f0660ace238a71a6dae0ed4f136ba0874ae3bd613c4ca
|
||||
|
|
@ -0,0 +1 @@
|
|||
3f0a6af062f151c3e0744a0babec4a1a9742d1a3a1a078c9596243b59bdd6419
|
||||
|
|
@ -6531,7 +6531,8 @@ CREATE TABLE ci_daily_build_group_report_results (
|
|||
group_name text NOT NULL,
|
||||
data jsonb NOT NULL,
|
||||
default_branch boolean DEFAULT false NOT NULL,
|
||||
group_id bigint
|
||||
group_id bigint,
|
||||
partition_id bigint DEFAULT 100 NOT NULL
|
||||
);
|
||||
|
||||
CREATE SEQUENCE ci_daily_build_group_report_results_id_seq
|
||||
|
|
|
|||
|
|
@ -8268,7 +8268,7 @@ Input type: `SecurityTrainingUpdateInput`
|
|||
|
||||
### `Mutation.setContainerScanningForRegistry`
|
||||
|
||||
Enable/disable Container Scanning on Container Registry for the given project or group.
|
||||
Enable/disable Container Scanning on Container Registry for the given project.
|
||||
|
||||
Input type: `SetContainerScanningForRegistryInput`
|
||||
|
||||
|
|
@ -8278,7 +8278,7 @@ Input type: `SetContainerScanningForRegistryInput`
|
|||
| ---- | ---- | ----------- |
|
||||
| <a id="mutationsetcontainerscanningforregistryclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationsetcontainerscanningforregistryenable"></a>`enable` | [`Boolean!`](#boolean) | Desired status for Container Scanning on Container Registry feature. |
|
||||
| <a id="mutationsetcontainerscanningforregistrynamespacepath"></a>`namespacePath` | [`ID!`](#id) | Full path of the namespace (project or group). |
|
||||
| <a id="mutationsetcontainerscanningforregistrynamespacepath"></a>`namespacePath` | [`ID!`](#id) | Full path of the namespace (project). |
|
||||
|
||||
#### Fields
|
||||
|
||||
|
|
|
|||
|
|
@ -306,10 +306,10 @@ Resources:
|
|||
|
||||
### Answer questions about GitLab
|
||||
|
||||
In this example, the challenge is exploring the GitLab Duo Chat beta to solve problems.
|
||||
In this example, the challenge is to use GitLab Duo Chat to solve problems.
|
||||
|
||||
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
|
||||
Watch the recording here: [GitLab Duo Coffee Chat: Solve problems with GitLab Duo Chat Beta Challenge](https://www.youtube.com/watch?v=Ypwx4lFnHP0)
|
||||
Watch the recording here: [GitLab Duo Coffee Chat: Solve problems with GitLab Duo Chat Challenge](https://www.youtube.com/watch?v=Ypwx4lFnHP0)
|
||||
<!-- Video published on 2024-02-02 -->
|
||||
|
||||
- You can use GitLab Duo Chat to explain CI/CD errors.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module BackgroundMigration
|
||||
class BackfillPartitionIdCiDailyBuildGroupReportResult < BatchedMigrationJob
|
||||
operation_name :update_all
|
||||
feature_category :ci_scaling
|
||||
|
||||
def perform
|
||||
each_sub_batch do |sub_batch|
|
||||
sub_batch
|
||||
.where('ci_daily_build_group_report_results.last_pipeline_id = ci_pipelines.id')
|
||||
.update_all('partition_id = ci_pipelines.partition_id FROM ci_pipelines')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -86,29 +86,25 @@ module Gitlab
|
|||
end
|
||||
|
||||
def pattern_matches?(paths, pattern_globs, context)
|
||||
return true if (paths.size * pattern_globs.size) > MAX_PATTERN_COMPARISONS
|
||||
|
||||
if ::Feature.disabled?(:ci_rules_exists_pattern_matches_cache, context.project)
|
||||
return legacy_pattern_matches?(paths, pattern_globs)
|
||||
end
|
||||
|
||||
comparisons = 0
|
||||
|
||||
pattern_globs.any? do |glob|
|
||||
Gitlab::SafeRequestStore.fetch("ci_rules_exists_pattern_matches_#{context.project&.id}_#{glob}") do
|
||||
paths.any? do |path|
|
||||
comparisons += 1
|
||||
comparisons > MAX_PATTERN_COMPARISONS || pattern_match?(glob, path)
|
||||
pattern_match?(glob, path)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def legacy_pattern_matches?(paths, pattern_globs)
|
||||
comparisons = 0
|
||||
|
||||
pattern_globs.any? do |glob|
|
||||
paths.any? do |path|
|
||||
comparisons += 1
|
||||
comparisons > MAX_PATTERN_COMPARISONS || pattern_match?(glob, path)
|
||||
pattern_match?(glob, path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -26276,6 +26276,9 @@ msgstr ""
|
|||
msgid "Identity verification exemption has been removed."
|
||||
msgstr ""
|
||||
|
||||
msgid "Identity verification is required in order to run CI jobs"
|
||||
msgstr ""
|
||||
|
||||
msgid "IdentityVerification|%d country found"
|
||||
msgid_plural "IdentityVerification|%d countries found"
|
||||
msgstr[0] ""
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ RSpec.describe 'Database schema', feature_category: :database do
|
|||
chat_names: %w[chat_id team_id user_id],
|
||||
chat_teams: %w[team_id],
|
||||
ci_builds: %w[project_id runner_id user_id erased_by_id trigger_request_id partition_id auto_canceled_by_partition_id execution_config_id],
|
||||
ci_daily_build_group_report_results: %w[partition_id],
|
||||
ci_job_artifacts: %w[partition_id project_id job_id],
|
||||
ci_namespace_monthly_usages: %w[namespace_id],
|
||||
ci_pipeline_artifacts: %w[partition_id],
|
||||
|
|
|
|||
|
|
@ -753,12 +753,14 @@ RSpec.describe 'Pipelines', :js, feature_category: :continuous_integration do
|
|||
stub_ci_pipeline_to_return_yaml_file
|
||||
end
|
||||
|
||||
subject(:run_pipeline) do
|
||||
find_by_testid('run-pipeline-button', text: 'Run pipeline').click
|
||||
|
||||
wait_for_requests
|
||||
end
|
||||
|
||||
it 'creates a new pipeline' do
|
||||
expect do
|
||||
find_by_testid('run-pipeline-button', text: 'Run pipeline').click
|
||||
wait_for_requests
|
||||
end
|
||||
.to change { Ci::Pipeline.count }.by(1)
|
||||
expect { run_pipeline }.to change { Ci::Pipeline.count }.by(1)
|
||||
|
||||
expect(Ci::Pipeline.last).to be_web
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
exports[`Branch divergence graph component renders ahead and behind count 1`] = `
|
||||
<div
|
||||
class="d-md-block d-none divergence-graph px-2"
|
||||
class="divergence-graph gl-hidden md:gl-block px-2"
|
||||
title="10 commits behind main, 10 commits ahead"
|
||||
>
|
||||
<graph-bar-stub
|
||||
|
|
@ -23,7 +23,7 @@ exports[`Branch divergence graph component renders ahead and behind count 1`] =
|
|||
|
||||
exports[`Branch divergence graph component renders distance count 1`] = `
|
||||
<div
|
||||
class="d-md-block d-none divergence-graph px-2"
|
||||
class="divergence-graph gl-hidden md:gl-block px-2"
|
||||
title="More than 900 commits different with main"
|
||||
>
|
||||
<graph-bar-stub
|
||||
|
|
|
|||
|
|
@ -0,0 +1,98 @@
|
|||
import Vue from 'vue';
|
||||
import VueApollo from 'vue-apollo';
|
||||
import { GlForm } from '@gitlab/ui';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import PipelineAccountVerificationAlert from 'ee_component/vue_shared/components/pipeline_account_verification_alert.vue';
|
||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import { HTTP_STATUS_BAD_REQUEST } from '~/lib/utils/http_status';
|
||||
import PipelineNewForm from '~/ci/pipeline_new/components/pipeline_new_form.vue';
|
||||
import ciConfigVariablesQuery from '~/ci/pipeline_new/graphql/queries/ci_config_variables.graphql';
|
||||
import { resolvers } from '~/ci/pipeline_new/graphql/resolvers';
|
||||
import {
|
||||
mockIdentityVerificationRequiredError,
|
||||
mockEmptyCiConfigVariablesResponse,
|
||||
mockProjectId,
|
||||
} from '../mock_data';
|
||||
|
||||
Vue.use(VueApollo);
|
||||
|
||||
const pipelinesPath = '/root/project/-/pipelines';
|
||||
const pipelinesEditorPath = '/root/project/-/ci/editor';
|
||||
const projectPath = '/root/project/-/pipelines/config_variables';
|
||||
const defaultBranch = 'main';
|
||||
|
||||
describe('Pipeline New Form', () => {
|
||||
let wrapper;
|
||||
let mock;
|
||||
let mockApollo;
|
||||
let mockCiConfigVariables;
|
||||
let dummySubmitEvent;
|
||||
|
||||
const findForm = () => wrapper.findComponent(GlForm);
|
||||
const findErrorAlert = () => wrapper.findByTestId('run-pipeline-error-alert');
|
||||
const findIdentityVerificationRequiredAlert = () =>
|
||||
wrapper.findComponent(PipelineAccountVerificationAlert);
|
||||
|
||||
const createComponentWithApollo = ({ props = {} } = {}) => {
|
||||
const handlers = [[ciConfigVariablesQuery, mockCiConfigVariables]];
|
||||
mockApollo = createMockApollo(handlers, resolvers);
|
||||
|
||||
wrapper = shallowMountExtended(PipelineNewForm, {
|
||||
apolloProvider: mockApollo,
|
||||
provide: {
|
||||
identityVerificationRequired: true,
|
||||
identityVerificationPath: '/test',
|
||||
},
|
||||
propsData: {
|
||||
projectId: mockProjectId,
|
||||
pipelinesPath,
|
||||
pipelinesEditorPath,
|
||||
canViewPipelineEditor: true,
|
||||
projectPath,
|
||||
defaultBranch,
|
||||
refParam: defaultBranch,
|
||||
settingsLink: '',
|
||||
maxWarnings: 25,
|
||||
...props,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
mock = new MockAdapter(axios);
|
||||
mockCiConfigVariables = jest.fn();
|
||||
|
||||
dummySubmitEvent = {
|
||||
preventDefault: jest.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mock.restore();
|
||||
});
|
||||
|
||||
describe('Form errors and warnings', () => {
|
||||
describe('when the error response is identity verification required', () => {
|
||||
beforeEach(async () => {
|
||||
mockCiConfigVariables.mockResolvedValue(mockEmptyCiConfigVariablesResponse);
|
||||
createComponentWithApollo();
|
||||
|
||||
mock
|
||||
.onPost(pipelinesPath)
|
||||
.reply(HTTP_STATUS_BAD_REQUEST, mockIdentityVerificationRequiredError);
|
||||
|
||||
findForm().vm.$emit('submit', dummySubmitEvent);
|
||||
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('shows identity verification required alert', () => {
|
||||
expect(findErrorAlert().exists()).toBe(false);
|
||||
expect(findIdentityVerificationRequiredAlert().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -101,6 +101,10 @@ describe('Pipeline New Form', () => {
|
|||
|
||||
wrapper = shallowMountExtended(PipelineNewForm, {
|
||||
apolloProvider: mockApollo,
|
||||
provide: {
|
||||
identityVerificationRequired: true,
|
||||
identityVerificationPath: '/test',
|
||||
},
|
||||
propsData: {
|
||||
projectId: mockProjectId,
|
||||
pipelinesPath,
|
||||
|
|
|
|||
|
|
@ -43,6 +43,12 @@ export const mockCreditCardValidationRequiredError = {
|
|||
total_warnings: 0,
|
||||
};
|
||||
|
||||
export const mockIdentityVerificationRequiredError = {
|
||||
errors: ['Identity verification is required in order to run CI jobs'],
|
||||
warnings: [],
|
||||
total_warnings: 0,
|
||||
};
|
||||
|
||||
export const mockBranchRefs = ['main', 'dev', 'release'];
|
||||
|
||||
export const mockTagRefs = ['1.0.0', '1.1.0', '1.2.0'];
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ const SSL_TOGGLE_CLASS = 'js-enable-ssl-gl-toggle';
|
|||
const SSL_TOGGLE_INPUT_CLASS = 'js-project-feature-toggle-input';
|
||||
const SHOW_IF_AUTO_SSL_CLASS = 'js-shown-if-auto-ssl';
|
||||
const SHOW_UNLESS_AUTO_SSL_CLASS = 'js-shown-unless-auto-ssl';
|
||||
const D_NONE_CLASS = '!gl-hidden';
|
||||
const HIDDEN_CLASS = '!gl-hidden';
|
||||
|
||||
describe('Page domains form', () => {
|
||||
let toggle;
|
||||
|
|
@ -51,8 +51,8 @@ describe('Page domains form', () => {
|
|||
});
|
||||
|
||||
it('sets the correct classes', () => {
|
||||
expect(Array.from(findIfAutoSsl().classList)).not.toContain(D_NONE_CLASS);
|
||||
expect(Array.from(findUnlessAutoSsl().classList)).toContain(D_NONE_CLASS);
|
||||
expect(Array.from(findIfAutoSsl().classList)).not.toContain(HIDDEN_CLASS);
|
||||
expect(Array.from(findUnlessAutoSsl().classList)).toContain(HIDDEN_CLASS);
|
||||
});
|
||||
|
||||
it('sets the correct disabled value', () => {
|
||||
|
|
@ -72,8 +72,8 @@ describe('Page domains form', () => {
|
|||
});
|
||||
|
||||
it('sets the correct classes', () => {
|
||||
expect(Array.from(findIfAutoSsl().classList)).toContain(D_NONE_CLASS);
|
||||
expect(Array.from(findUnlessAutoSsl().classList)).not.toContain(D_NONE_CLASS);
|
||||
expect(Array.from(findIfAutoSsl().classList)).toContain(HIDDEN_CLASS);
|
||||
expect(Array.from(findUnlessAutoSsl().classList)).not.toContain(HIDDEN_CLASS);
|
||||
});
|
||||
|
||||
it('sets the correct disabled value', () => {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ exports[`Repository table row component renders a symlink table row 1`] = `
|
|||
/>
|
||||
</td>
|
||||
<td
|
||||
class="cursor-default d-none d-sm-table-cell tree-commit"
|
||||
class="cursor-default gl-hidden sm:gl-table-cell tree-commit"
|
||||
>
|
||||
<gl-link-stub
|
||||
class="gl-text-gray-600 str-truncated-100 tree-commit-link"
|
||||
|
|
@ -90,7 +90,7 @@ exports[`Repository table row component renders table row 1`] = `
|
|||
/>
|
||||
</td>
|
||||
<td
|
||||
class="cursor-default d-none d-sm-table-cell tree-commit"
|
||||
class="cursor-default gl-hidden sm:gl-table-cell tree-commit"
|
||||
>
|
||||
<gl-link-stub
|
||||
class="gl-text-gray-600 str-truncated-100 tree-commit-link"
|
||||
|
|
@ -146,7 +146,7 @@ exports[`Repository table row component renders table row for path with special
|
|||
/>
|
||||
</td>
|
||||
<td
|
||||
class="cursor-default d-none d-sm-table-cell tree-commit"
|
||||
class="cursor-default gl-hidden sm:gl-table-cell tree-commit"
|
||||
>
|
||||
<gl-link-stub
|
||||
class="gl-text-gray-600 str-truncated-100 tree-commit-link"
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ describe('~/snippet/collapsible_input', () => {
|
|||
setHTMLFixture(`
|
||||
<form>
|
||||
<div class="js-collapsible-input js-title">
|
||||
<div class="js-collapsed d-none">
|
||||
<div class="js-collapsed !gl-hidden">
|
||||
<input type="text" />
|
||||
</div>
|
||||
<div class="js-expanded">
|
||||
|
|
@ -22,7 +22,7 @@ describe('~/snippet/collapsible_input', () => {
|
|||
<div class="js-collapsed">
|
||||
<input type="text" />
|
||||
</div>
|
||||
<div class="js-expanded d-none">
|
||||
<div class="js-expanded !gl-hidden">
|
||||
<textarea></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -49,8 +49,8 @@ describe('~/snippet/collapsible_input', () => {
|
|||
const findExpandedInput = (el) => findInput(findExpanded(el));
|
||||
const focusIn = (target) => target.dispatchEvent(new Event('focusin', { bubbles: true }));
|
||||
const expectIsCollapsed = (el, isCollapsed) => {
|
||||
expect(findCollapsed(el).classList.contains('d-none')).toEqual(!isCollapsed);
|
||||
expect(findExpanded(el).classList.contains('d-none')).toEqual(isCollapsed);
|
||||
expect(findCollapsed(el).classList.contains('!gl-hidden')).toEqual(!isCollapsed);
|
||||
expect(findExpanded(el).classList.contains('!gl-hidden')).toEqual(isCollapsed);
|
||||
};
|
||||
|
||||
describe('when collapsed', () => {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ exports[`Snippet Description Edit component rendering matches the snapshot 1`] =
|
|||
class="js-collapsible-input"
|
||||
>
|
||||
<div
|
||||
class="d-none js-collapsed"
|
||||
class="!gl-hidden js-collapsed"
|
||||
>
|
||||
<gl-form-textarea-stub
|
||||
class="form-control"
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ describe('Snippet Description Edit component', () => {
|
|||
}
|
||||
|
||||
function isHidden(sel) {
|
||||
return wrapper.find(sel).classes('d-none');
|
||||
return wrapper.find(sel).classes('!gl-hidden');
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
@ -36,8 +36,8 @@ describe('Snippet Description Edit component', () => {
|
|||
});
|
||||
|
||||
it('renders the field expanded when description exists', () => {
|
||||
expect(wrapper.find('.js-collapsed').classes('d-none')).toBe(true);
|
||||
expect(wrapper.find('.js-expanded').classes('d-none')).toBe(false);
|
||||
expect(wrapper.find('.js-collapsed').classes('!gl-hidden')).toBe(true);
|
||||
expect(wrapper.find('.js-expanded').classes('!gl-hidden')).toBe(false);
|
||||
|
||||
expect(isHidden('.js-collapsed')).toBe(true);
|
||||
expect(isHidden('.js-expanded')).toBe(false);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ require 'spec_helper'
|
|||
RSpec.describe Ci::PipelinesHelper, feature_category: :continuous_integration do
|
||||
include Devise::Test::ControllerHelpers
|
||||
|
||||
let_it_be(:project) { create(:project) }
|
||||
|
||||
describe 'has_gitlab_ci?' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
|
|
@ -25,8 +27,6 @@ RSpec.describe Ci::PipelinesHelper, feature_category: :continuous_integration do
|
|||
end
|
||||
|
||||
describe '#pipelines_list_data' do
|
||||
let_it_be(:project) { create(:project) }
|
||||
|
||||
subject(:data) { helper.pipelines_list_data(project, 'list_url') }
|
||||
|
||||
before do
|
||||
|
|
@ -111,4 +111,25 @@ RSpec.describe Ci::PipelinesHelper, feature_category: :continuous_integration do
|
|||
it { expect(subject).to eq(result) }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#new_pipeline_data' do
|
||||
subject(:data) { helper.new_pipeline_data(project) }
|
||||
|
||||
it 'has the expected keys' do
|
||||
expect(subject.keys).to include(
|
||||
:project_id,
|
||||
:pipelines_path,
|
||||
:default_branch,
|
||||
:pipelines_editor_path,
|
||||
:can_view_pipeline_editor,
|
||||
:ref_param,
|
||||
:var_param,
|
||||
:file_param,
|
||||
:project_path,
|
||||
:project_refs_endpoint,
|
||||
:settings_link,
|
||||
:max_warnings
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::BackgroundMigration::BackfillPartitionIdCiDailyBuildGroupReportResult, feature_category: :ci_scaling do
|
||||
let(:ci_pipelines_table) { table(:ci_pipelines, database: :ci) }
|
||||
let(:ci_daily_build_group_report_results_table) { table(:ci_daily_build_group_report_results, database: :ci) }
|
||||
let!(:pipeline_1) { ci_pipelines_table.create!(id: 1, partition_id: 100) }
|
||||
let!(:pipeline_2) { ci_pipelines_table.create!(id: 2, partition_id: 101) }
|
||||
let!(:pipeline_3) { ci_pipelines_table.create!(id: 3, partition_id: 101) }
|
||||
let!(:ci_daily_build_group_report_results_100) do
|
||||
ci_daily_build_group_report_results_table.create!(
|
||||
date: Date.yesterday,
|
||||
project_id: 1,
|
||||
ref_path: 'master',
|
||||
group_name: 'rspec',
|
||||
data: { 'coverage' => 77.0 },
|
||||
default_branch: true,
|
||||
last_pipeline_id: pipeline_1.id,
|
||||
partition_id: pipeline_1.partition_id
|
||||
)
|
||||
end
|
||||
|
||||
let!(:ci_daily_build_group_report_results_101) do
|
||||
ci_daily_build_group_report_results_table.create!(
|
||||
date: Date.today,
|
||||
project_id: 1,
|
||||
ref_path: 'master',
|
||||
group_name: 'rspec',
|
||||
data: { 'coverage' => 77.0 },
|
||||
default_branch: true,
|
||||
last_pipeline_id: pipeline_2.id,
|
||||
partition_id: pipeline_2.partition_id
|
||||
)
|
||||
end
|
||||
|
||||
let!(:invalid_ci_daily_build_group_report_results) do
|
||||
ci_daily_build_group_report_results_table.create!(
|
||||
date: Date.tomorrow,
|
||||
project_id: 1,
|
||||
ref_path: 'master',
|
||||
group_name: 'rspec',
|
||||
data: { 'coverage' => 77.0 },
|
||||
default_branch: true,
|
||||
last_pipeline_id: pipeline_3.id,
|
||||
partition_id: pipeline_1.partition_id
|
||||
)
|
||||
end
|
||||
|
||||
let(:migration_attrs) do
|
||||
{
|
||||
start_id: ci_daily_build_group_report_results_table.minimum(:id),
|
||||
end_id: ci_daily_build_group_report_results_table.maximum(:id),
|
||||
batch_table: :ci_daily_build_group_report_results,
|
||||
batch_column: :id,
|
||||
sub_batch_size: 1,
|
||||
pause_ms: 0,
|
||||
connection: Ci::ApplicationRecord.connection
|
||||
}
|
||||
end
|
||||
|
||||
let!(:migration) { described_class.new(**migration_attrs) }
|
||||
|
||||
describe '#perform' do
|
||||
context 'when second partition does not exist' do
|
||||
before do
|
||||
pipeline_3.update!(partition_id: 100)
|
||||
end
|
||||
|
||||
it 'does not execute the migration' do
|
||||
expect { migration.perform }
|
||||
.not_to change { invalid_ci_daily_build_group_report_results.reload.partition_id }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when second partition exists' do
|
||||
it 'fixes invalid records in the wrong the partition' do
|
||||
expect { migration.perform }
|
||||
.to not_change { ci_daily_build_group_report_results_100.reload.partition_id }
|
||||
.and not_change { ci_daily_build_group_report_results_101.reload.partition_id }
|
||||
.and change { invalid_ci_daily_build_group_report_results.reload.partition_id }
|
||||
.from(100)
|
||||
.to(101)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -71,7 +71,7 @@ RSpec.describe Gitlab::Ci::Build::Rules::Rule::Clause::Exists, feature_category:
|
|||
|
||||
before do
|
||||
stub_const('Gitlab::Ci::Build::Rules::Rule::Clause::Exists::MAX_PATTERN_COMPARISONS', 2)
|
||||
expect(File).to receive(:fnmatch?).twice.and_call_original
|
||||
expect(File).not_to receive(:fnmatch?)
|
||||
end
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
|
|
|
|||
|
|
@ -740,7 +740,7 @@ RSpec.describe Notify, feature_category: :code_review_workflow do
|
|||
|
||||
describe 'that have new commits on top of more than two existing ones' do
|
||||
let(:existing_commits) do
|
||||
[merge_request.commits.first] + [double(:commit)] * 3 + [merge_request.commits.second]
|
||||
[merge_request.commits.first] + ([double(:commit)] * 3) + [merge_request.commits.second]
|
||||
end
|
||||
|
||||
subject do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require_migration!
|
||||
|
||||
RSpec.describe QueueBackfillPartitionIdCiDailyBuildGroupReportResult, migration: :gitlab_ci, feature_category: :ci_scaling do
|
||||
let!(:batched_migrations) { table(:batched_background_migrations) }
|
||||
let!(:migration) { described_class::MIGRATION }
|
||||
|
||||
describe '#up' do
|
||||
context 'with migration present' do
|
||||
let!(:ci_backfill_partition_id_ci_daily_build_group_report_results_migration) do
|
||||
batched_migrations.create!(
|
||||
job_class_name: 'QueueBackfillPartitionIdCiDailyBuildGroupReportResult',
|
||||
table_name: :ci_daily_build_group_report_results,
|
||||
column_name: :id,
|
||||
job_arguments: [],
|
||||
interval: 2.minutes,
|
||||
min_value: 1,
|
||||
max_value: 2,
|
||||
batch_size: 1000,
|
||||
sub_batch_size: 100,
|
||||
gitlab_schema: :gitlab_ci,
|
||||
status: 3 # finished
|
||||
)
|
||||
end
|
||||
|
||||
context 'when migration finished successfully' do
|
||||
it 'does not raise exception' do
|
||||
expect { migrate! }.not_to raise_error
|
||||
end
|
||||
|
||||
it 'schedules background jobs for each batch of ci_daily_build_group_report_results' do
|
||||
migrate!
|
||||
|
||||
expect(migration).to have_scheduled_batched_migration(
|
||||
gitlab_schema: :gitlab_ci,
|
||||
table_name: :ci_daily_build_group_report_results,
|
||||
column_name: :id,
|
||||
batch_size: described_class::BATCH_SIZE,
|
||||
sub_batch_size: described_class::SUB_BATCH_SIZE
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#down' do
|
||||
it 'deletes all batched migration records' do
|
||||
migrate!
|
||||
schema_migrate_down!
|
||||
|
||||
expect(migration).not_to have_scheduled_batched_migration
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -125,11 +125,11 @@ RSpec.describe Appearance do
|
|||
context 'valid pwa attributes' do
|
||||
where(:attribute, :value) do
|
||||
:pwa_name | nil
|
||||
:pwa_name | "G" * 255
|
||||
:pwa_name | ("G" * 255)
|
||||
:pwa_short_name | nil
|
||||
:pwa_short_name | "S" * 255
|
||||
:pwa_short_name | ("S" * 255)
|
||||
:pwa_description | nil
|
||||
:pwa_description | "T" * 2048
|
||||
:pwa_description | ("T" * 2048)
|
||||
end
|
||||
|
||||
with_them do
|
||||
|
|
@ -139,9 +139,9 @@ RSpec.describe Appearance do
|
|||
|
||||
context 'invalid pwa attributes' do
|
||||
where(:attribute, :value, :message) do
|
||||
:pwa_name | "G" * 256 | 'is too long (maximum is 255 characters)'
|
||||
:pwa_short_name | "S" * 256 | 'is too long (maximum is 255 characters)'
|
||||
:pwa_description | "T" * 2049 | 'is too long (maximum is 2048 characters)'
|
||||
:pwa_name | ("G" * 256) | 'is too long (maximum is 255 characters)'
|
||||
:pwa_short_name | ("S" * 256) | 'is too long (maximum is 255 characters)'
|
||||
:pwa_description | ("T" * 2049) | 'is too long (maximum is 2048 characters)'
|
||||
end
|
||||
|
||||
with_them do
|
||||
|
|
|
|||
|
|
@ -2298,13 +2298,13 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def
|
|||
'1-foo' | '1-foo'
|
||||
'fix/1-foo' | 'fix-1-foo'
|
||||
'fix-1-foo' | 'fix-1-foo'
|
||||
'a' * 63 | 'a' * 63
|
||||
'a' * 64 | 'a' * 63
|
||||
'FOO' | 'foo'
|
||||
'-' + 'a' * 61 + '-' | 'a' * 61
|
||||
'-' + 'a' * 62 + '-' | 'a' * 62
|
||||
'-' + 'a' * 63 + '-' | 'a' * 62
|
||||
'a' * 62 + ' ' | 'a' * 62
|
||||
('a' * 63) | ('a' * 63)
|
||||
('a' * 64) | ('a' * 63)
|
||||
'FOO' | 'foo'
|
||||
('-' + ('a' * 61) + '-') | ('a' * 61)
|
||||
('-' + ('a' * 62) + '-') | ('a' * 62)
|
||||
('-' + ('a' * 63) + '-') | ('a' * 62)
|
||||
(('a' * 62) + ' ') | ('a' * 62)
|
||||
end
|
||||
|
||||
with_them do
|
||||
|
|
|
|||
|
|
@ -181,4 +181,19 @@ RSpec.describe Ci::DailyBuildGroupReportResult, feature_category: :continuous_in
|
|||
|
||||
let!(:parent) { model.project }
|
||||
end
|
||||
|
||||
describe 'partitioning', :ci_partitionable do
|
||||
include Ci::PartitioningHelpers
|
||||
|
||||
let(:pipeline) { create(:ci_pipeline) }
|
||||
let(:daily_build_group_report_result) { create(:ci_daily_build_group_report_result, last_pipeline: pipeline) }
|
||||
|
||||
before do
|
||||
stub_current_partition_id
|
||||
end
|
||||
|
||||
it 'assigns the same partition id as the one that pipeline has' do
|
||||
expect(daily_build_group_report_result.partition_id).to eq(ci_testing_partition_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -335,7 +335,7 @@ RSpec.describe Commit do
|
|||
'1234567' | true
|
||||
'123456' | false
|
||||
'1' | false
|
||||
'0' * 40 | true
|
||||
('0' * 40) | true
|
||||
'c1acaa58bbcbc3eafe538cb8274ba387047b69f8' | true
|
||||
'H1acaa58bbcbc3eafe538cb8274ba387047b69f8' | false
|
||||
nil | false
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ RSpec.describe PgFullTextSearchable, feature_category: :global_search do
|
|||
end
|
||||
|
||||
it 'strips words containing @ with length >= 500' do
|
||||
model = model_class.create!(project: project, namespace: project.project_namespace, title: 'title', description: 'description ' + '@user1' * 100)
|
||||
model = model_class.create!(project: project, namespace: project.project_namespace, title: 'title', description: 'description ' + ('@user1' * 100))
|
||||
model.update_search_data!
|
||||
|
||||
expect(model.search_data.search_vector).to match(/'titl':1A/)
|
||||
|
|
@ -218,8 +218,8 @@ RSpec.describe PgFullTextSearchable, feature_category: :global_search do
|
|||
end
|
||||
|
||||
context 'with long words' do
|
||||
let(:long_word) { 'long/sequence' * 5 + ' ' }
|
||||
let(:model) { model_class.create!(project: project, namespace: project.project_namespace, title: 'title', description: 'description ' + long_word * 51) }
|
||||
let(:long_word) { ('long/sequence' * 5) + ' ' }
|
||||
let(:model) { model_class.create!(project: project, namespace: project.project_namespace, title: 'title', description: 'description ' + (long_word * 51)) }
|
||||
|
||||
it 'strips words with length >= 50 when there are more than 50 instances' do
|
||||
model.update_search_data!
|
||||
|
|
@ -231,7 +231,7 @@ RSpec.describe PgFullTextSearchable, feature_category: :global_search do
|
|||
end
|
||||
|
||||
it 'does not strip long words when there are less than 51 instances' do
|
||||
model.update!(description: 'description ' + long_word * 50)
|
||||
model.update!(description: 'description ' + (long_word * 50))
|
||||
model.update_search_data!
|
||||
|
||||
expect(model.search_data.search_vector).to match(/'titl':1A/)
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ RSpec.describe CustomEmoji do
|
|||
end
|
||||
|
||||
it 'disallows very long invalid emoji name without regular expression backtracking issues' do
|
||||
new_emoji = build(:custom_emoji, name: 'a' * 10000 + '!', group: group)
|
||||
new_emoji = build(:custom_emoji, name: ('a' * 10000) + '!', group: group)
|
||||
|
||||
Timeout.timeout(1) do
|
||||
expect(new_emoji).not_to be_valid
|
||||
|
|
|
|||
|
|
@ -1848,7 +1848,7 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching, feature_categ
|
|||
where(:value, :expected_result) do
|
||||
'2 days' | 2.days.to_i
|
||||
'1 week' | 1.week.to_i
|
||||
'2h20min' | 2.hours.to_i + 20.minutes.to_i
|
||||
'2h20min' | (2.hours.to_i + 20.minutes.to_i)
|
||||
'abcdef' | ChronicDuration::DurationParseError
|
||||
'' | nil
|
||||
nil | nil
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ RSpec.describe GrafanaIntegration do
|
|||
unsafe_url = %{https://replaceme.com/'><script>alert(document.cookie)</script>}
|
||||
non_ascii_url = 'http://gitlab.com/api/0/projects/project1/something€'
|
||||
blank_url = ''
|
||||
excessively_long_url = 'https://grafan' + 'a' * 1024 + '.com'
|
||||
excessively_long_url = 'https://grafan' + ('a' * 1024) + '.com'
|
||||
|
||||
is_expected.not_to allow_values(
|
||||
unsafe_url,
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ RSpec.describe Integrations::ChatMessage::PushMessage do
|
|||
args[:commits] = [
|
||||
{ message: 'message1', title: 'message1', url: 'http://url1.com', id: 'abcdefghijkl', author: { name: 'author1' } },
|
||||
{
|
||||
message: 'message2' + ' w' * 100 + "\nsecondline",
|
||||
message: 'message2' + (' w' * 100) + "\nsecondline",
|
||||
title: 'message2 w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w ...',
|
||||
url: 'http://url2.com',
|
||||
id: '123456789012',
|
||||
|
|
|
|||
|
|
@ -944,7 +944,7 @@ RSpec.describe MergeRequestDiff, feature_category: :code_review_workflow do
|
|||
|
||||
context 'with diffs that contain a null byte' do
|
||||
let(:filename) { 'test-null.txt' }
|
||||
let(:content) { "a" * 10000 + "\x00" }
|
||||
let(:content) { ("a" * 10000) + "\x00" }
|
||||
let(:project) { create(:project, :repository) }
|
||||
let(:branch) { 'null-data' }
|
||||
let(:target_branch) { 'master' }
|
||||
|
|
|
|||
|
|
@ -55,12 +55,12 @@ RSpec.describe Packages::PackageFile, type: :model, feature_category: :package_r
|
|||
|
||||
context 'file_sha256' do
|
||||
where(:sha256_value, :expected_success) do
|
||||
'a' * 64 | true
|
||||
nil | true
|
||||
'a' * 63 | false
|
||||
'a' * 65 | false
|
||||
'a' * 63 + '%' | false
|
||||
'' | false
|
||||
('a' * 64) | true
|
||||
nil | true
|
||||
('a' * 63) | false
|
||||
('a' * 65) | false
|
||||
(('a' * 63) + '%') | false
|
||||
'' | false
|
||||
end
|
||||
|
||||
with_them do
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ RSpec.describe PrometheusAlert do
|
|||
it 'disallow invalid urls' do
|
||||
unsafe_url = %{https://replaceme.com/'><script>alert(document.cookie)</script>}
|
||||
non_ascii_url = 'http://gitlab.com/user/project1/wiki/something€'
|
||||
excessively_long_url = 'https://gitla' + 'b' * 1024 + '.com'
|
||||
excessively_long_url = 'https://gitla' + ('b' * 1024) + '.com'
|
||||
|
||||
is_expected.not_to allow_values(
|
||||
unsafe_url,
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue