Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-02-03 21:09:17 +00:00
parent 1743439667
commit a1ed241c82
195 changed files with 1574 additions and 1159 deletions

View File

@ -2647,113 +2647,6 @@ Style/FrozenStringLiteralComment:
- 'app/views/projects/tags/index.atom.builder'
- 'app/views/users/show.atom.builder'
- 'bin/secpick'
- 'config.ru'
- 'config/boot.rb'
- 'config/environment.rb'
- 'config/environments/development.rb'
- 'config/environments/production.rb'
- 'config/environments/test.rb'
- 'config/initializers/01_secret_token.rb'
- 'config/initializers/0_acts_as_taggable.rb'
- 'config/initializers/0_inject_feature_flags.rb'
- 'config/initializers/0_post_deployment_migrations.rb'
- 'config/initializers/1_settings.rb'
- 'config/initializers/2_gitlab.rb'
- 'config/initializers/5_backend.rb'
- 'config/initializers/6_validations.rb'
- 'config/initializers/7_prometheus_metrics.rb'
- 'config/initializers/7_redis.rb'
- 'config/initializers/8_devise.rb'
- 'config/initializers/8_gitaly.rb'
- 'config/initializers/9_fast_gettext.rb'
- 'config/initializers/action_dispatch_http_mime_negotiation.rb'
- 'config/initializers/action_mailer_hooks.rb'
- 'config/initializers/active_record_data_types.rb'
- 'config/initializers/active_record_ping.rb'
- 'config/initializers/active_record_preloader.rb'
- 'config/initializers/active_record_schema_ignore_tables.rb'
- 'config/initializers/active_record_table_definition.rb'
- 'config/initializers/ar_speed_up_migration_checking.rb'
- 'config/initializers/asset_proxy_settings.rb'
- 'config/initializers/attr_encrypted_no_db_connection.rb'
- 'config/initializers/backtrace_silencers.rb'
- 'config/initializers/batch_loader.rb'
- 'config/initializers/bootstrap_form.rb'
- 'config/initializers/bullet.rb'
- 'config/initializers/cluster_events_before_phased_restart.rb'
- 'config/initializers/console_message.rb'
- 'config/initializers/cookies_serializer.rb'
- 'config/initializers/date_time_formats.rb'
- 'config/initializers/default_url_options.rb'
- 'config/initializers/deprecations.rb'
- 'config/initializers/direct_upload_support.rb'
- 'config/initializers/doorkeeper.rb'
- 'config/initializers/doorkeeper_openid_connect.rb'
- 'config/initializers/etag_caching.rb'
- 'config/initializers/fill_shards.rb'
- 'config/initializers/fix_local_cache_middleware.rb'
- 'config/initializers/fog_google_https_private_urls.rb'
- 'config/initializers/forbid_sidekiq_in_transactions.rb'
- 'config/initializers/gettext_rails_i18n_patch.rb'
- 'config/initializers/gitlab_kas_secret.rb'
- 'config/initializers/gitlab_shell_secret_token.rb'
- 'config/initializers/gitlab_workhorse_secret.rb'
- 'config/initializers/go_get.rb'
- 'config/initializers/grpc.rb'
- 'config/initializers/hamlit.rb'
- 'config/initializers/health_check.rb'
- 'config/initializers/http_hostname_override.rb'
- 'config/initializers/kaminari_active_record_relation_methods_with_limit.rb'
- 'config/initializers/kaminari_config.rb'
- 'config/initializers/lograge.rb'
- 'config/initializers/mail_encoding_patch.rb'
- 'config/initializers/mime_types.rb'
- 'config/initializers/mini_magick.rb'
- 'config/initializers/new_framework_defaults.rb'
- 'config/initializers/octokit.rb'
- 'config/initializers/omniauth.rb'
- 'config/initializers/peek.rb'
- 'config/initializers/postgresql_cte.rb'
- 'config/initializers/premailer.rb'
- 'config/initializers/query_limiting.rb'
- 'config/initializers/rack_lineprof.rb'
- 'config/initializers/relative_naming_ci_namespace.rb'
- 'config/initializers/request_context.rb'
- 'config/initializers/request_profiler.rb'
- 'config/initializers/routing_draw.rb'
- 'config/initializers/sentry.rb'
- 'config/initializers/server_uptime.rb'
- 'config/initializers/session_store.rb'
- 'config/initializers/sherlock.rb'
- 'config/initializers/sprockets.rb'
- 'config/initializers/static_files.rb'
- 'config/initializers/time_zone.rb'
- 'config/initializers/trusted_proxies.rb'
- 'config/initializers/warden.rb'
- 'config/initializers/workhorse_multipart.rb'
- 'config/initializers/wrap_parameters.rb'
- 'config/initializers/zz_metrics.rb'
- 'config/initializers_before_autoloader/000_inflections.rb'
- 'config/object_store_settings.rb'
- 'config/routes.rb'
- 'config/routes/admin.rb'
- 'config/routes/api.rb'
- 'config/routes/dashboard.rb'
- 'config/routes/development.rb'
- 'config/routes/explore.rb'
- 'config/routes/git_http.rb'
- 'config/routes/google_api.rb'
- 'config/routes/help.rb'
- 'config/routes/import.rb'
- 'config/routes/legacy_builds.rb'
- 'config/routes/repository.rb'
- 'config/routes/sherlock.rb'
- 'config/routes/sidekiq.rb'
- 'config/routes/snippets.rb'
- 'config/routes/uploads.rb'
- 'config/routes/wiki.rb'
- 'config/smime_signature_settings.rb'
- 'config/spring.rb'
- 'danger/changes_size/Dangerfile'
- 'danger/metadata/Dangerfile'
- 'db/migrate/20190325080727_truncate_user_fullname.rb'

View File

@ -86,16 +86,16 @@ export default {
return !this.disabled && this.listType !== ListType.closed;
},
showMilestoneListDetails() {
return (
this.listType === ListType.milestone &&
this.list.milestone &&
(!this.list.collapsed || !this.isSwimlanesHeader)
);
return this.listType === ListType.milestone && this.list.milestone && this.showListDetails;
},
showAssigneeListDetails() {
return (
this.listType === ListType.assignee && (!this.list.collapsed || !this.isSwimlanesHeader)
);
return this.listType === ListType.assignee && this.showListDetails;
},
showIterationListDetails() {
return this.listType === ListType.iteration && this.showListDetails;
},
showListDetails() {
return !this.list.collapsed || !this.isSwimlanesHeader;
},
issuesCount() {
return this.list.issuesCount;
@ -218,6 +218,17 @@ export default {
<gl-icon name="timer" />
</span>
<span
v-if="showIterationListDetails"
aria-hidden="true"
:class="{
'gl-mt-3 gl-rotate-90': list.collapsed,
'gl-mr-2': !list.collapsed,
}"
>
<gl-icon name="iteration" />
</span>
<a
v-if="showAssigneeListDetails"
:href="list.assignee.webUrl"

View File

@ -78,14 +78,16 @@ export default {
return !this.disabled && this.listType !== ListType.closed;
},
showMilestoneListDetails() {
return (
this.list.type === 'milestone' &&
this.list.milestone &&
(this.list.isExpanded || !this.isSwimlanesHeader)
);
return this.list.type === 'milestone' && this.list.milestone && this.showListDetails;
},
showAssigneeListDetails() {
return this.list.type === 'assignee' && (this.list.isExpanded || !this.isSwimlanesHeader);
return this.list.type === 'assignee' && this.showListDetails;
},
showIterationListDetails() {
return this.listType === ListType.iteration && this.showListDetails;
},
showListDetails() {
return this.list.isExpanded || !this.isSwimlanesHeader;
},
issuesCount() {
return this.list.issuesSize;
@ -203,6 +205,17 @@ export default {
<gl-icon name="timer" />
</span>
<span
v-if="showIterationListDetails"
aria-hidden="true"
:class="{
'gl-mt-3 gl-rotate-90': !list.isExpanded,
'gl-mr-2': list.isExpanded,
}"
>
<gl-icon name="iteration" />
</span>
<a
v-if="showAssigneeListDetails"
:href="list.assignee.path"

View File

@ -5,17 +5,13 @@ import { __ } from '~/locale';
import boardsStore from '~/boards/stores/boards_store';
import eventHub from '~/sidebar/event_hub';
import { isScopedLabel } from '~/lib/utils/common_utils';
import { LIST } from '~/boards/constants';
import { LIST, ListType, ListTypeTitles } from '~/boards/constants';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
// NOTE: need to revisit how we handle headerHeight, because we have so many different header and footer options.
export default {
headerHeight: process.env.NODE_ENV === 'development' ? '75px' : '40px',
listSettingsText: __('List settings'),
assignee: 'assignee',
milestone: 'milestone',
label: 'label',
labelListText: __('Label'),
components: {
GlButton,
GlDrawer,
@ -33,6 +29,11 @@ export default {
default: false,
},
},
data() {
return {
ListType,
};
},
computed: {
...mapGetters(['isSidebarOpen', 'shouldUseGraphQL']),
...mapState(['activeId', 'sidebarType', 'boardLists']),
@ -56,7 +57,7 @@ export default {
return this.activeList.type || this.activeList.listType || null;
},
listTypeTitle() {
return this.$options.labelListText;
return ListTypeTitles[ListType.label];
},
showSidebar() {
return this.sidebarType === LIST;
@ -98,7 +99,7 @@ export default {
>
<template #header>{{ $options.listSettingsText }}</template>
<template v-if="isSidebarOpen">
<div v-if="boardListType === $options.label">
<div v-if="boardListType === ListType.label">
<label class="js-list-label gl-display-block">{{ listTypeTitle }}</label>
<gl-label
:title="activeListLabel.title"

View File

@ -1,3 +1,5 @@
import { __ } from '~/locale';
export const BoardType = {
project: 'project',
group: 'group',
@ -6,11 +8,19 @@ export const BoardType = {
export const ListType = {
assignee: 'assignee',
milestone: 'milestone',
iteration: 'iteration',
backlog: 'backlog',
closed: 'closed',
label: 'label',
};
export const ListTypeTitles = {
assignee: __('Assignee'),
milestone: __('Milestone'),
iteration: __('Iteration'),
label: __('Label'),
};
export const inactiveId = 0;
export const ISSUABLE = 'issuable';

View File

@ -0,0 +1,9 @@
export default class ListIteration {
constructor(obj) {
this.id = obj.id;
this.title = obj.title;
this.state = obj.state;
this.webUrl = obj.web_url || obj.webUrl;
this.description = obj.description;
}
}

View File

@ -5,6 +5,7 @@ import boardsStore from '../stores/boards_store';
import ListLabel from './label';
import ListAssignee from './assignee';
import ListMilestone from './milestone';
import ListIteration from './iteration';
import 'ee_else_ce/boards/models/issue';
const TYPES = {
@ -57,6 +58,9 @@ class List {
} else if (IS_EE && obj.milestone) {
this.milestone = new ListMilestone(obj.milestone);
this.title = this.milestone.title;
} else if (IS_EE && obj.iteration) {
this.iteration = new ListIteration(obj.iteration);
this.title = this.iteration.title;
}
// doNotFetchIssues is a temporary workaround until issues are fetched using GraphQL on issue boards

View File

@ -1,7 +1,6 @@
<script>
/* eslint-disable vue/no-v-html */
import { GlLoadingIcon, GlBadge, GlTooltipDirective } from '@gitlab/ui';
import { showLearnGitLabGroupItemPopover } from '~/onboarding_issues';
import { visitUrl } from '../../lib/utils/url_utility';
import identicon from '../../vue_shared/components/identicon.vue';
import eventHub from '../event_hub';
@ -77,11 +76,6 @@ export default {
return this.group.microdata || {};
},
},
mounted() {
if (this.group.name === 'Learn GitLab') {
showLearnGitLabGroupItemPopover(this.group.id);
}
},
methods: {
onClickRowGroup(e) {
const NO_EXPAND_CLS = 'no-expand';

View File

@ -1,128 +0,0 @@
import $ from 'jquery';
import { parseBoolean, getCookie, setCookie, removeCookie } from '~/lib/utils/common_utils';
import { __, sprintf } from '~/locale';
import Tracking from '~/tracking';
const COOKIE_NAME = 'onboarding_issues_settings';
const POPOVER_LOCATIONS = {
GROUPS_SHOW: 'groups#show',
PROJECTS_SHOW: 'projects#show',
ISSUES_INDEX: 'issues#index',
};
const removeLearnGitLabCookie = () => {
removeCookie(COOKIE_NAME);
};
function disposePopover(event) {
event.preventDefault();
this.popover('dispose');
removeLearnGitLabCookie();
Tracking.event('Growth::Conversion::Experiment::OnboardingIssues', 'dismiss_popover');
}
const showPopover = (el, path, footer, options) => {
// Cookie value looks like `{ 'groups#show': true, 'projects#show': true, 'issues#index': true }`. When it doesn't exist, don't show the popover.
const cookie = getCookie(COOKIE_NAME);
if (!cookie) return;
// When the popover action has already been taken, don't show the popover.
const settings = JSON.parse(cookie);
if (!parseBoolean(settings[path])) return;
const defaultOptions = {
boundary: 'window',
html: true,
placement: 'top',
template: `<div class="gl-popover popover blue learn-gitlab d-none d-xl-block" role="tooltip">
<div class="arrow"></div>
<div class="js-close-learn-gitlab gl-font-weight-bold gl-line-height-normal float-right gl-cursor-pointer gl-font-base gl-text-white gl-opacity-10 gl-p-3">&#10005</div>
<div class="popover-body gl-font-base"></div>
<div class="gl-font-weight-bold gl-text-right gl-text-white gl-p-3 gl-pt-0">${footer}</div>
</div>`,
};
// When one of the popovers is dismissed, remove the cookie.
const closeButton = () => document.querySelector('.js-close-learn-gitlab');
// We still have to use jQuery, since Bootstrap's Popover is based on jQuery.
const jQueryEl = $(el);
const clickCloseButton = disposePopover.bind(jQueryEl);
jQueryEl
.popover({ ...defaultOptions, ...options })
.on('inserted.bs.popover', () => closeButton().addEventListener('click', clickCloseButton))
.on('hide.bs.dropdown', () => closeButton().removeEventListener('click', clickCloseButton))
.popover('show');
// The previous popover actions have been taken, don't show those popovers anymore.
Object.keys(settings).forEach((pathSetting) => {
if (path !== pathSetting) {
settings[pathSetting] = false;
} else {
setCookie(COOKIE_NAME, settings);
}
});
// The final popover action will be taken on click, we then no longer need the cookie.
if (path === POPOVER_LOCATIONS.ISSUES_INDEX) {
el.addEventListener('click', removeLearnGitLabCookie);
}
};
export const showLearnGitLabGroupItemPopover = (id) => {
const el = document.querySelector(`#group-${id} .group-text a`);
if (!el) return;
const options = {
content: __(
'Here are all your projects in your group, including the one you just created. To start, lets take a look at your personalized learning project which will help you learn about GitLab at your own pace.',
),
};
showPopover(el, POPOVER_LOCATIONS.GROUPS_SHOW, '1 / 2', options);
};
export const showLearnGitLabProjectPopover = () => {
// Do not show a popover if we are not viewing the 'Learn GitLab' project.
if (!window.location.pathname.includes('learn-gitlab')) return;
const el = document.querySelector('a.shortcuts-issues');
if (!el) return;
const options = {
content: sprintf(
__(
'Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board.',
),
{ strongStart: '<strong>', strongEnd: '</strong>' },
false,
),
};
showPopover(el, POPOVER_LOCATIONS.PROJECTS_SHOW, '2 / 2', options);
};
export const showLearnGitLabIssuesPopover = () => {
// Do not show a popover if we are not viewing the 'Learn GitLab' project.
if (!window.location.pathname.includes('learn-gitlab')) return;
const el = document.querySelector('a[data-qa-selector="issue_boards_link"]');
if (!el) return;
const options = {
content: sprintf(
__(
'Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board.',
),
{ strongStart: '<strong>', strongEnd: '</strong>' },
false,
),
};
showPopover(el, POPOVER_LOCATIONS.ISSUES_INDEX, '2 / 2', options);
};

View File

@ -9,7 +9,6 @@ import { FILTERED_SEARCH } from '~/pages/constants';
import { ISSUABLE_INDEX } from '~/pages/projects/constants';
import initIssuablesList from '~/issues_list';
import initManualOrdering from '~/manual_ordering';
import { showLearnGitLabIssuesPopover } from '~/onboarding_issues';
IssuableFilteredSearchTokenKeys.addExtraTokensForIssues();
@ -25,4 +24,3 @@ new UsersSelect();
initManualOrdering();
initIssuablesList();
showLearnGitLabIssuesPopover();

View File

@ -7,7 +7,6 @@ import BlobViewer from '~/blob/viewer/index';
import Activities from '~/activities';
import initReadMore from '~/read_more';
import leaveByUrl from '~/namespaces/leave_by_url';
import { showLearnGitLabProjectPopover } from '~/onboarding_issues';
import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
import initVueNotificationsDropdown from '~/notifications';
@ -41,8 +40,6 @@ if (document.querySelector('.project-show-activity')) {
leaveByUrl('project');
showLearnGitLabProjectPopover();
if (gon.features?.vueNotificationDropdown) {
initVueNotificationsDropdown();
} else {

View File

@ -0,0 +1,114 @@
<script>
import CommitForm from './commit_form.vue';
import commitCIFile from '../../graphql/mutations/commit_ci_file.mutation.graphql';
import getCommitSha from '../../graphql/queries/client/commit_sha.graphql';
import { COMMIT_FAILURE, COMMIT_SUCCESS } from '../../constants';
import { mergeUrlParams, redirectTo } from '~/lib/utils/url_utility';
import { __, s__, sprintf } from '~/locale';
const MR_SOURCE_BRANCH = 'merge_request[source_branch]';
const MR_TARGET_BRANCH = 'merge_request[target_branch]';
export default {
alertTexts: {
[COMMIT_FAILURE]: s__('Pipelines|The GitLab CI configuration could not be updated.'),
[COMMIT_SUCCESS]: __('Your changes have been successfully committed.'),
},
i18n: {
defaultCommitMessage: __('Update %{sourcePath} file'),
},
components: {
CommitForm,
},
inject: ['projectFullPath', 'ciConfigPath', 'defaultBranch', 'newMergeRequestPath'],
props: {
ciFileContent: {
type: String,
required: true,
},
},
data() {
return {
commit: {},
isSaving: false,
};
},
apollo: {
commitSha: {
query: getCommitSha,
},
},
computed: {
defaultCommitMessage() {
return sprintf(this.$options.i18n.defaultCommitMessage, { sourcePath: this.ciConfigPath });
},
},
methods: {
redirectToNewMergeRequest(sourceBranch) {
const url = mergeUrlParams(
{
[MR_SOURCE_BRANCH]: sourceBranch,
[MR_TARGET_BRANCH]: this.defaultBranch,
},
this.newMergeRequestPath,
);
redirectTo(url);
},
async onCommitSubmit({ message, branch, openMergeRequest }) {
this.isSaving = true;
try {
const {
data: {
commitCreate: { errors },
},
} = await this.$apollo.mutate({
mutation: commitCIFile,
variables: {
projectPath: this.projectFullPath,
branch,
startBranch: this.defaultBranch,
message,
filePath: this.ciConfigPath,
content: this.ciFileContent,
lastCommitId: this.commitSha,
},
update(store, { data }) {
const commitSha = data?.commitCreate?.commit?.sha;
if (commitSha) {
store.writeQuery({ query: getCommitSha, data: { commitSha } });
}
},
});
if (errors?.length) {
this.$emit('showError', { type: COMMIT_FAILURE, reasons: errors });
} else if (openMergeRequest) {
this.redirectToNewMergeRequest(branch);
} else {
this.$emit('commit', { type: COMMIT_SUCCESS });
}
} catch (error) {
this.$emit('showError', { type: COMMIT_FAILURE, reasons: [error?.message] });
} finally {
this.isSaving = false;
}
},
onCommitCancel() {
this.$emit('resetContent');
},
},
};
</script>
<template>
<commit-form
:default-branch="defaultBranch"
:default-message="defaultCommitMessage"
:is-saving="isSaving"
@cancel="onCommitCancel"
@submit="onCommitSubmit"
/>
</template>

View File

@ -0,0 +1,30 @@
<script>
import ValidationSegment from './validation_segment.vue';
export default {
validationSegmentClasses:
'gl-p-5 gl-bg-gray-10 gl-border-solid gl-border-1 gl-border-gray-100 gl-rounded-base',
components: {
ValidationSegment,
},
props: {
ciConfigData: {
type: Object,
required: true,
},
isCiConfigDataLoading: {
type: Boolean,
required: true,
},
},
};
</script>
<template>
<div class="gl-mb-5">
<validation-segment
:class="$options.validationSegmentClasses"
:loading="isCiConfigDataLoading"
:ci-config="ciConfigData"
/>
</div>
</template>

View File

@ -0,0 +1,62 @@
<script>
import { GlLoadingIcon, GlTabs, GlTab } from '@gitlab/ui';
import { s__ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import CiLint from './lint/ci_lint.vue';
import EditorTab from './ui/editor_tab.vue';
import TextEditor from './text_editor.vue';
import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue';
export default {
i18n: {
tabEdit: s__('Pipelines|Write pipeline configuration'),
tabGraph: s__('Pipelines|Visualize'),
tabLint: s__('Pipelines|Lint'),
},
components: {
CiLint,
EditorTab,
GlLoadingIcon,
GlTab,
GlTabs,
PipelineGraph,
TextEditor,
},
mixins: [glFeatureFlagsMixin()],
props: {
ciConfigData: {
type: Object,
required: true,
},
ciFileContent: {
type: String,
required: true,
},
isCiConfigDataLoading: {
type: Boolean,
required: false,
default: false,
},
},
};
</script>
<template>
<gl-tabs class="file-editor gl-mb-3">
<editor-tab :title="$options.i18n.tabEdit" lazy data-testid="editor-tab">
<text-editor :value="ciFileContent" v-on="$listeners" />
</editor-tab>
<gl-tab
v-if="glFeatures.ciConfigVisualizationTab"
:title="$options.i18n.tabGraph"
lazy
data-testid="visualization-tab"
>
<gl-loading-icon v-if="isCiConfigDataLoading" size="lg" class="gl-m-3" />
<pipeline-graph v-else :pipeline-data="ciConfigData" />
</gl-tab>
<editor-tab :title="$options.i18n.tabLint" data-testid="lint-tab">
<gl-loading-icon v-if="isCiConfigDataLoading" size="lg" class="gl-m-3" />
<ci-lint v-else :ci-config="ciConfigData" />
</editor-tab>
</gl-tabs>
</template>

View File

@ -2,26 +2,29 @@
import EditorLite from '~/vue_shared/components/editor_lite.vue';
import { CiSchemaExtension } from '~/editor/extensions/editor_ci_schema_ext';
import { EDITOR_READY_EVENT } from '~/editor/constants';
import getCommitSha from '../graphql/queries/client/commit_sha.graphql';
export default {
components: {
EditorLite,
},
inject: ['projectPath', 'projectNamespace'],
inject: ['ciConfigPath', 'projectPath', 'projectNamespace'],
inheritAttrs: false,
props: {
ciConfigPath: {
type: String,
required: true,
},
data() {
return {
commitSha: '',
};
},
apollo: {
commitSha: {
type: String,
required: false,
default: null,
query: getCommitSha,
},
},
methods: {
onEditorReady() {
onCiConfigUpdate(content) {
this.$emit('updateCiConfig', content);
},
registerCiSchema() {
const editorInstance = this.$refs.editor.getEditor();
editorInstance.use(new CiSchemaExtension());
@ -41,7 +44,8 @@ export default {
ref="editor"
:file-name="ciConfigPath"
v-bind="$attrs"
@[$options.readyEvent]="onEditorReady"
@[$options.readyEvent]="registerCiSchema"
@input="onCiConfigUpdate"
v-on="$listeners"
/>
</div>

View File

@ -1,2 +1,9 @@
export const CI_CONFIG_STATUS_VALID = 'VALID';
export const CI_CONFIG_STATUS_INVALID = 'INVALID';
export const COMMIT_FAILURE = 'COMMIT_FAILURE';
export const COMMIT_SUCCESS = 'COMMIT_SUCCESS';
export const DEFAULT_FAILURE = 'DEFAULT_FAILURE';
export const LOAD_FAILURE_NO_FILE = 'LOAD_FAILURE_NO_FILE';
export const LOAD_FAILURE_UNKNOWN = 'LOAD_FAILURE_UNKNOWN';

View File

@ -1,4 +1,4 @@
mutation commitCIFileMutation(
mutation commitCIFile(
$projectPath: ID!
$branch: String!
$startBranch: String

View File

@ -0,0 +1,3 @@
query getCommitSha {
commitSha @client
}

View File

@ -15,14 +15,13 @@ export const initPipelineEditor = (selector = '#js-pipeline-editor') => {
}
const {
// props
ciConfigPath,
// Add to apollo cache as it can be updated by future queries
commitSha,
// Add to provide/inject API for static values
ciConfigPath,
defaultBranch,
newMergeRequestPath,
// `provide/inject` data
lintHelpPagePath,
newMergeRequestPath,
projectFullPath,
projectPath,
projectNamespace,
@ -35,25 +34,27 @@ export const initPipelineEditor = (selector = '#js-pipeline-editor') => {
defaultClient: createDefaultClient(resolvers, { typeDefs }),
});
apolloProvider.clients.defaultClient.cache.writeData({
data: {
commitSha,
},
});
return new Vue({
el,
apolloProvider,
provide: {
ciConfigPath,
defaultBranch,
lintHelpPagePath,
newMergeRequestPath,
projectFullPath,
projectPath,
projectNamespace,
ymlHelpPagePath,
},
render(h) {
return h(PipelineEditorApp, {
props: {
ciConfigPath,
commitSha,
defaultBranch,
newMergeRequestPath,
},
});
return h(PipelineEditorApp);
},
});
};

View File

@ -1,87 +1,55 @@
<script>
import { GlAlert, GlLoadingIcon, GlTabs, GlTab } from '@gitlab/ui';
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
import { __, s__, sprintf } from '~/locale';
import { mergeUrlParams, redirectTo } from '~/lib/utils/url_utility';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import httpStatusCodes from '~/lib/utils/http_status';
import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue';
import { unwrapStagesWithNeeds } from '~/pipelines/components/unwrapping_utils';
import CiLint from './components/lint/ci_lint.vue';
import CommitForm from './components/commit/commit_form.vue';
import ConfirmUnsavedChangesDialog from './components/ui/confirm_unsaved_changes_dialog.vue';
import EditorTab from './components/ui/editor_tab.vue';
import TextEditor from './components/text_editor.vue';
import ValidationSegment from './components/info/validation_segment.vue';
import commitCiFileMutation from './graphql/mutations/commit_ci_file.mutation.graphql';
import {
COMMIT_FAILURE,
COMMIT_SUCCESS,
DEFAULT_FAILURE,
LOAD_FAILURE_NO_FILE,
LOAD_FAILURE_UNKNOWN,
} from './constants';
import getBlobContent from './graphql/queries/blob_content.graphql';
import getCiConfigData from './graphql/queries/ci_config.graphql';
const MR_SOURCE_BRANCH = 'merge_request[source_branch]';
const MR_TARGET_BRANCH = 'merge_request[target_branch]';
const COMMIT_FAILURE = 'COMMIT_FAILURE';
const COMMIT_SUCCESS = 'COMMIT_SUCCESS';
const DEFAULT_FAILURE = 'DEFAULT_FAILURE';
const LOAD_FAILURE_NO_FILE = 'LOAD_FAILURE_NO_FILE';
const LOAD_FAILURE_UNKNOWN = 'LOAD_FAILURE_UNKNOWN';
import PipelineEditorHome from './pipeline_editor_home.vue';
export default {
components: {
CiLint,
CommitForm,
ConfirmUnsavedChangesDialog,
EditorTab,
GlAlert,
GlLoadingIcon,
GlTabs,
GlTab,
PipelineGraph,
TextEditor,
ValidationSegment,
PipelineEditorHome,
},
mixins: [glFeatureFlagsMixin()],
inject: ['projectFullPath'],
props: {
defaultBranch: {
type: String,
required: false,
default: null,
},
commitSha: {
type: String,
required: false,
default: null,
},
inject: {
ciConfigPath: {
type: String,
required: true,
default: '',
},
newMergeRequestPath: {
type: String,
required: true,
defaultBranch: {
default: null,
},
projectFullPath: {
default: '',
},
},
data() {
return {
ciConfigData: {},
content: '',
contentModel: '',
lastCommittedContent: '',
lastCommitSha: this.commitSha,
isSaving: false,
// Success and failure state
failureType: null,
showFailureAlert: false,
failureReasons: [],
successType: null,
initialCiFileContent: '',
lastCommittedContent: '',
currentCiFileContent: '',
showFailureAlert: false,
showSuccessAlert: false,
successType: null,
};
},
apollo: {
content: {
initialCiFileContent: {
query: getBlobContent,
variables() {
return {
@ -91,12 +59,13 @@ export default {
};
},
update(data) {
const content = data?.blobContent?.rawData;
this.lastCommittedContent = content;
return content;
return data?.blobContent?.rawData;
},
result({ data }) {
this.contentModel = data?.blobContent?.rawData ?? '';
const fileContent = data?.blobContent?.rawData ?? '';
this.lastCommittedContent = fileContent;
this.currentCiFileContent = fileContent;
},
error(error) {
this.handleBlobContentError(error);
@ -105,13 +74,13 @@ export default {
ciConfigData: {
query: getCiConfigData,
// If content is not loaded, we can't lint the data
skip: ({ contentModel }) => {
return !contentModel;
skip: ({ currentCiFileContent }) => {
return !currentCiFileContent;
},
variables() {
return {
projectPath: this.projectFullPath,
content: this.contentModel,
content: this.currentCiFileContent,
};
},
update(data) {
@ -128,10 +97,10 @@ export default {
},
computed: {
hasUnsavedChanges() {
return this.lastCommittedContent !== this.contentModel;
return this.lastCommittedContent !== this.currentCiFileContent;
},
isBlobContentLoading() {
return this.$apollo.queries.content.loading;
return this.$apollo.queries.initialCiFileContent.loading;
},
isBlobContentError() {
return this.failureType === LOAD_FAILURE_NO_FILE;
@ -139,62 +108,60 @@ export default {
isCiConfigDataLoading() {
return this.$apollo.queries.ciConfigData.loading;
},
defaultCommitMessage() {
return sprintf(this.$options.i18n.defaultCommitMessage, { sourcePath: this.ciConfigPath });
},
success() {
switch (this.successType) {
case COMMIT_SUCCESS:
return {
text: this.$options.alertTexts[COMMIT_SUCCESS],
variant: 'info',
};
default:
return null;
}
},
failure() {
switch (this.failureType) {
case LOAD_FAILURE_NO_FILE:
return {
text: sprintf(this.$options.alertTexts[LOAD_FAILURE_NO_FILE], {
text: sprintf(this.$options.errorTexts[LOAD_FAILURE_NO_FILE], {
filePath: this.ciConfigPath,
}),
variant: 'danger',
};
case LOAD_FAILURE_UNKNOWN:
return {
text: this.$options.alertTexts[LOAD_FAILURE_UNKNOWN],
text: this.$options.errorTexts[LOAD_FAILURE_UNKNOWN],
variant: 'danger',
};
case COMMIT_FAILURE:
return {
text: this.$options.alertTexts[COMMIT_FAILURE],
text: this.$options.errorTexts[COMMIT_FAILURE],
variant: 'danger',
};
default:
return {
text: this.$options.alertTexts[DEFAULT_FAILURE],
text: this.$options.errorTexts[DEFAULT_FAILURE],
variant: 'danger',
};
}
},
success() {
switch (this.successType) {
case COMMIT_SUCCESS:
return {
text: this.$options.successTexts[COMMIT_SUCCESS],
variant: 'info',
};
default:
return null;
}
},
},
i18n: {
defaultCommitMessage: __('Update %{sourcePath} file'),
tabEdit: s__('Pipelines|Write pipeline configuration'),
tabGraph: s__('Pipelines|Visualize'),
tabLint: s__('Pipelines|Lint'),
},
alertTexts: {
errorTexts: {
[COMMIT_FAILURE]: s__('Pipelines|The GitLab CI configuration could not be updated.'),
[COMMIT_SUCCESS]: __('Your changes have been successfully committed.'),
[DEFAULT_FAILURE]: __('Something went wrong on our end.'),
[LOAD_FAILURE_NO_FILE]: s__(
'Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again.',
),
[LOAD_FAILURE_UNKNOWN]: s__('Pipelines|The CI configuration was not loaded, please try again.'),
},
successTexts: {
[COMMIT_SUCCESS]: __('Your changes have been successfully committed.'),
},
methods: {
handleBlobContentError(error = {}) {
const { networkError } = error;
@ -215,73 +182,32 @@ export default {
dismissFailure() {
this.showFailureAlert = false;
},
dismissSuccess() {
this.showSuccessAlert = false;
},
reportFailure(type, reasons = []) {
this.showFailureAlert = true;
this.failureType = type;
this.failureReasons = reasons;
},
dismissSuccess() {
this.showSuccessAlert = false;
},
reportSuccess(type) {
this.showSuccessAlert = true;
this.successType = type;
},
redirectToNewMergeRequest(sourceBranch) {
const url = mergeUrlParams(
{
[MR_SOURCE_BRANCH]: sourceBranch,
[MR_TARGET_BRANCH]: this.defaultBranch,
},
this.newMergeRequestPath,
);
redirectTo(url);
resetContent() {
this.currentCiFileContent = this.lastCommittedContent;
},
async onCommitSubmit(event) {
this.isSaving = true;
const { message, branch, openMergeRequest } = event;
try {
const {
data: {
commitCreate: { errors, commit },
},
} = await this.$apollo.mutate({
mutation: commitCiFileMutation,
variables: {
projectPath: this.projectFullPath,
branch,
startBranch: this.defaultBranch,
message,
filePath: this.ciConfigPath,
content: this.contentModel,
lastCommitId: this.lastCommitSha,
},
});
if (errors?.length) {
this.reportFailure(COMMIT_FAILURE, errors);
return;
}
if (openMergeRequest) {
this.redirectToNewMergeRequest(branch);
} else {
this.reportSuccess(COMMIT_SUCCESS);
// Update latest commit
this.lastCommitSha = commit.sha;
this.lastCommittedContent = this.contentModel;
}
} catch (error) {
this.reportFailure(COMMIT_FAILURE, [error?.message]);
} finally {
this.isSaving = false;
}
showErrorAlert({ type, reasons = [] }) {
this.reportFailure(type, reasons);
},
onCommitCancel() {
this.contentModel = this.content;
updateCiConfig(ciFileContent) {
this.currentCiFileContent = ciFileContent;
},
updateOnCommit({ type }) {
this.reportSuccess(type);
// Keep track of the latest commited content to know
// if the user has made changes to the file that are unsaved.
this.lastCommittedContent = this.currentCiFileContent;
},
},
};
@ -289,20 +215,10 @@ export default {
<template>
<div class="gl-mt-4">
<gl-alert
v-if="showSuccessAlert"
:variant="success.variant"
:dismissible="true"
@dismiss="dismissSuccess"
>
<gl-alert v-if="showSuccessAlert" :variant="success.variant" @dismiss="dismissSuccess">
{{ success.text }}
</gl-alert>
<gl-alert
v-if="showFailureAlert"
:variant="failure.variant"
:dismissible="true"
@dismiss="dismissFailure"
>
<gl-alert v-if="showFailureAlert" :variant="failure.variant" @dismiss="dismissFailure">
{{ failure.text }}
<ul v-if="failureReasons.length" class="gl-mb-0">
<li v-for="reason in failureReasons" :key="reason">{{ reason }}</li>
@ -310,45 +226,14 @@ export default {
</gl-alert>
<gl-loading-icon v-if="isBlobContentLoading" size="lg" class="gl-m-3" />
<div v-else-if="!isBlobContentError" class="gl-mt-4">
<div class="file-editor gl-mb-3">
<div class="info-well gl-display-none gl-sm-display-block">
<validation-segment
class="well-segment"
:loading="isCiConfigDataLoading"
:ci-config="ciConfigData"
/>
</div>
<gl-tabs>
<editor-tab :lazy="true" :title="$options.i18n.tabEdit">
<text-editor
v-model="contentModel"
:ci-config-path="ciConfigPath"
:commit-sha="lastCommitSha"
/>
</editor-tab>
<gl-tab
v-if="glFeatures.ciConfigVisualizationTab"
:lazy="true"
:title="$options.i18n.tabGraph"
data-testid="visualization-tab"
>
<gl-loading-icon v-if="isCiConfigDataLoading" size="lg" class="gl-m-3" />
<pipeline-graph v-else :pipeline-data="ciConfigData" />
</gl-tab>
<editor-tab :title="$options.i18n.tabLint">
<gl-loading-icon v-if="isCiConfigDataLoading" size="lg" class="gl-m-3" />
<ci-lint v-else :ci-config="ciConfigData" />
</editor-tab>
</gl-tabs>
</div>
<commit-form
:default-branch="defaultBranch"
:default-message="defaultCommitMessage"
:is-saving="isSaving"
@cancel="onCommitCancel"
@submit="onCommitSubmit"
<pipeline-editor-home
:is-ci-config-data-loading="isCiConfigDataLoading"
:ci-config-data="ciConfigData"
:ci-file-content="currentCiFileContent"
@commit="updateOnCommit"
@resetContent="resetContent"
@showError="showErrorAlert"
@updateCiConfig="updateCiConfig"
/>
</div>
<confirm-unsaved-changes-dialog :has-unsaved-changes="hasUnsavedChanges" />

View File

@ -0,0 +1,43 @@
<script>
import CommitSection from './components/commit/commit_section.vue';
import PipelineEditorTabs from './components/pipeline_editor_tabs.vue';
import PipelineEditorHeader from './components/header/pipeline_editor_header.vue';
export default {
components: {
CommitSection,
PipelineEditorHeader,
PipelineEditorTabs,
},
props: {
ciConfigData: {
type: Object,
required: true,
},
ciFileContent: {
type: String,
required: true,
},
isCiConfigDataLoading: {
type: Boolean,
required: true,
},
},
};
</script>
<template>
<div>
<pipeline-editor-header
:ci-config-data="ciConfigData"
:is-ci-config-data-loading="isCiConfigDataLoading"
/>
<pipeline-editor-tabs
:ci-config-data="ciConfigData"
:ci-file-content="ciFileContent"
:is-ci-config-data-loading="isCiConfigDataLoading"
v-on="$listeners"
/>
<commit-section :ci-file-content="ciFileContent" v-on="$listeners" />
</div>
</template>

View File

@ -28,7 +28,6 @@ export default {
return {
currentPipeline: null,
loadingPipelineId: null,
minWidth: 0,
pipelineExpanded: false,
};
},
@ -40,6 +39,7 @@ export default {
'gl-pl-3',
'gl-mb-5',
],
minWidth: `${ONE_COL_WIDTH}px`,
computed: {
columnClass() {
const positionValues = {
@ -48,12 +48,6 @@ export default {
};
return `graph-position-${this.graphPosition} ${positionValues[this.graphPosition]}`;
},
graphPosition() {
return this.isUpstream ? 'left' : 'right';
},
isUpstream() {
return this.type === UPSTREAM;
},
computedTitleClasses() {
const positionalClasses = this.isUpstream
? ['gl-w-full', 'gl-text-right', 'gl-linked-pipeline-padding']
@ -61,6 +55,12 @@ export default {
return [...this.$options.titleClasses, ...positionalClasses];
},
graphPosition() {
return this.isUpstream ? 'left' : 'right';
},
isUpstream() {
return this.type === UPSTREAM;
},
},
methods: {
getPipelineData(pipeline) {
@ -105,7 +105,6 @@ export default {
if (this.currentPipeline?.id === pipeline.id) {
this.pipelineExpanded = false;
this.currentPipeline = null;
this.minWidth = 0;
return;
}
@ -120,11 +119,6 @@ export default {
*/
this.pipelineExpanded = true;
/*
Min-width is set manually for timing reasons.
*/
this.minWidth = `${ONE_COL_WIDTH}px`;
this.getPipelineData(pipeline);
},
onDownstreamHovered(jobName) {
@ -138,6 +132,9 @@ export default {
this.$emit('pipelineExpandToggle', jobName, expanded);
},
showDownstreamContainer(id) {
return !this.isUpstream && (this.isExpanded(id) || this.isLoadingPipeline(id));
},
},
};
</script>
@ -167,12 +164,12 @@ export default {
@pipelineExpandToggle="onPipelineExpandToggle"
/>
<div
v-if="isExpanded(pipeline.id) && !isUpstream"
:style="{ minWidth }"
v-if="showDownstreamContainer(pipeline.id)"
:style="{ minWidth: $options.minWidth }"
class="gl-display-inline-block"
>
<pipeline-graph
v-if="currentPipeline"
v-if="isExpanded(pipeline.id)"
:type="type"
class="d-inline-block gl-mt-n2"
:pipeline="currentPipeline"

View File

@ -74,13 +74,15 @@ export default {
<div v-else>
<gl-alert
v-if="showAlert"
class="gl-w-max-content gl-ml-4"
class="gl-ml-4 gl-mb-4"
:primary-button-text="$options.i18n.showLinksAnyways"
@primaryAction="overrideShowLinks"
@dismiss="dismissAlert"
>
{{ $options.i18n.tooManyJobs }}
</gl-alert>
<slot></slot>
<div class="gl-display-flex gl-relative">
<slot></slot>
</div>
</div>
</template>

View File

@ -203,6 +203,17 @@ module DiffHelper
set_secure_cookie(:diff_view, params.delete(:view), type: CookiesHelper::COOKIE_TYPE_PERMANENT) if params[:view].present?
end
def collapsed_diff_url(diff_file)
url_for(
safe_params.merge(
action: :diff_for_path,
old_path: diff_file.old_path,
new_path: diff_file.new_path,
file_identifier: diff_file.file_identifier
)
)
end
private
def diff_btn(title, name, selected)

View File

@ -76,6 +76,22 @@ module Ci
end
end
##
# Sometime we need to ensure that the first read goes to a primary
# database, what is especially important in EE. This method does not
# change the behavior in CE.
#
def with_read_consistency(build, &block)
return yield unless consistent_reads_enabled?(build)
::Gitlab::Database::Consistency
.with_read_consistency(&block)
end
def consistent_reads_enabled?(build)
Feature.enabled?(:gitlab_ci_trace_read_consistency, build.project, type: :development, default_enabled: false)
end
##
# Sometimes we do not want to read raw data. This method makes it easier
# to find attributes that are just metadata excluding raw data.
@ -154,8 +170,8 @@ module Ci
in_lock(lock_key, **lock_params) do # exclusive Redis lock is acquired first
raise FailedToPersistDataError, 'Modifed build trace chunk detected' if has_changes_to_save?
self.reset.then do |chunk| # we ensure having latest lock_version
chunk.unsafe_persist_data! # we migrate the data and update data store
self.class.with_read_consistency(build) do
self.reset.then { |chunk| chunk.unsafe_persist_data! }
end
end
rescue FailedToObtainLockError

View File

@ -24,9 +24,7 @@ module Pages
@queue.close
@logger.info("Waiting for threads to finish...")
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
threads.each(&:join)
end
threads.each(&:join)
{ migrated: @migrated, errored: @errored }
end
@ -34,8 +32,8 @@ module Pages
def start_migration_threads
Array.new(@migration_threads) do
Thread.new do
Rails.application.executor.wrap do
while batch = @queue.pop
while batch = @queue.pop
Rails.application.executor.wrap do
process_batch(batch)
end
end
@ -51,6 +49,11 @@ module Pages
end
@logger.info("#{@migrated} projects are migrated successfully, #{@errored} projects failed to be migrated")
rescue => e
# This method should never raise exception otherwise all threads might be killed
# and this will result in queue starving (and deadlock)
Gitlab::ErrorTracking.track_exception(e)
@logger.error("failed processing a batch: #{e.message}")
end
def migrate_project(project)

View File

@ -1,5 +1,3 @@
- diff_file = viewer.diff_file
- url = url_for(safe_params.merge(action: :diff_for_path, old_path: diff_file.old_path, new_path: diff_file.new_path, file_identifier: diff_file.file_identifier))
.nothing-here-block.diff-collapsed{ data: { diff_for_path: url } }
.nothing-here-block.diff-collapsed{ data: { diff_for_path: collapsed_diff_url(viewer.diff_file) } }
= _("This diff is collapsed.")
%button.click-to-expand.btn.btn-link= _("Click to expand it.")

View File

@ -15,5 +15,5 @@
= render 'shared/notes/hints'
.error-alert
.gl-mt-3
= f.submit 'Save changes', class: 'btn btn-success'
= link_to "Cancel", project_tag_path(@project, @tag.name), class: "btn btn-default btn-cancel"
= f.submit 'Save changes', class: 'btn gl-button btn-success'
= link_to "Cancel", project_tag_path(@project, @tag.name), class: "btn gl-button btn-default btn-cancel"

View File

@ -42,13 +42,13 @@
- if @tag.has_signature?
= render partial: 'projects/commit/signature', object: @tag.signature
- if can?(current_user, :admin_tag, @project)
= link_to edit_project_tag_release_path(@project, @tag.name), class: 'btn btn-icon btn-edit gl-button controls-item has-tooltip', title: s_('TagsPage|Edit release notes') do
= link_to edit_project_tag_release_path(@project, @tag.name), class: 'btn btn-icon btn-edit gl-button btn-default controls-item has-tooltip', title: s_('TagsPage|Edit release notes') do
= sprite_icon("pencil", css_class: 'gl-icon')
= link_to project_tree_path(@project, @tag.name), class: 'btn btn-icon gl-button controls-item has-tooltip', title: s_('TagsPage|Browse files') do
= link_to project_tree_path(@project, @tag.name), class: 'btn btn-icon gl-button btn-default controls-item has-tooltip', title: s_('TagsPage|Browse files') do
= sprite_icon('folder-open', css_class: 'gl-icon')
= link_to project_commits_path(@project, @tag.name), class: 'btn btn-icon gl-button controls-item has-tooltip', title: s_('TagsPage|Browse commits') do
= link_to project_commits_path(@project, @tag.name), class: 'btn btn-icon gl-button btn-default controls-item has-tooltip', title: s_('TagsPage|Browse commits') do
= sprite_icon('history', css_class: 'gl-icon')
.btn-container.controls-item
.controls-item
= render 'projects/buttons/download', project: @project, ref: @tag.name
- if can?(current_user, :admin_tag, @project)
.btn-container.controls-item-full

View File

@ -0,0 +1,5 @@
---
title: Lower allocations in _collapsed partial
merge_request: 53233
author:
type: performance

View File

@ -0,0 +1,5 @@
---
title: Add btn-default to buttons in tag action on the single tag page
merge_request: 52866
author: Yogi (@yo)
type: other

View File

@ -0,0 +1,5 @@
---
title: Apply new GitLab UI for buttons in the tag edit page
merge_request: 52863
author: Yogi (@yo)
type: other

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
# This file is used by Rack-based servers to start the application.
if defined?(Unicorn)

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
# Set up gems listed in the Gemfile.

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
# Load the Rails application.
require_relative 'application'

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
require 'gitlab/testing/request_blocker_middleware'
require 'gitlab/testing/robots_blocker_middleware'
require 'gitlab/testing/request_inspector_middleware'

View File

@ -0,0 +1,8 @@
---
name: gitlab_ci_trace_read_consistency
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46976
rollout_issue_url:
milestone: '13.9'
type: development
group: group::continuous integration
default_enabled: false

View File

@ -0,0 +1,8 @@
---
name: usage_data_i_testing_load_performance_widget_total
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52688
rollout_issue_url:
milestone: '13.9'
type: development
group: group::testing
default_enabled: true

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
# WARNING: Before you make a change to secrets.yml, read the development guide for GitLab secrets
# doc/development/application_secrets.md.
#

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
ActsAsTaggableOn.strict_case_match = true
# tags_counter enables caching count of tags which results in an update whenever a tag is added or removed

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
# This needs to be loaded after
# config/initializers/0_inject_enterprise_edition_module.rb

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
# Post deployment migrations are included by default. This file must be loaded
# before other initializers as Rails may otherwise memoize a list of migrations
# excluding the post deployment migrations.

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
require_relative '../settings'
require_relative '../object_store_settings'
require_relative '../smime_signature_settings'

View File

@ -1 +1,3 @@
# frozen_string_literal: true
require_dependency 'gitlab'

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
unless Rails.env.test?
required_version = Gitlab::VersionInfo.parse(Gitlab::Shell.version_required)
current_version = Gitlab::VersionInfo.parse(Gitlab::Shell.version)

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
def storage_validation_error(message)
raise "#{message}. Please fix this in your gitlab.yml before starting GitLab."
end

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
require 'prometheus/client'
# Keep separate directories for separate processes

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
# Make sure we initialize a Redis connection pool before multi-threaded
# execution starts by
# 1. Sidekiq

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
# Use this hook to configure devise mailer, warden hooks and so forth. The first
# four configuration values can also be set straight in your models.
Devise.setup do |config|

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
require 'uri'
Gitlab.config.repositories.storages.keys.each do |storage|

View File

@ -1,2 +1,4 @@
# frozen_string_literal: true
FastGettext.default_available_locales = Gitlab::I18n.available_locales
I18n.available_locales = Gitlab::I18n.available_locales

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
# Starting with Rails 5, Rails tries to determine the request format based on
# the extension of the full URL path if no explicit `format` param or `Accept`
# header is provided, like when simply browsing to a page in your browser.

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
unless Gitlab.config.gitlab.email_enabled
ActionMailer::Base.register_interceptor(::Gitlab::Email::Hook::DisableEmailInterceptor)
ActionMailer::Base.logger = nil

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
# ActiveRecord custom data type for storing datetimes with timezone information.
# See https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/11229

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
# # frozen_string_literal: true
if Gitlab::Utils.to_boolean(ENV['ENABLE_ACTIVERECORD_EMPTY_PING'], default: false)

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
module ActiveRecord
module Associations
class Preloader

View File

@ -1,2 +1,4 @@
# frozen_string_literal: true
# Ignore dynamically managed partitions in static application schema
ActiveRecord::SchemaDumper.ignore_tables += ["#{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}.*"]

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
# ActiveRecord custom method definitions with timezone information.
# See https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/11229

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
if Rails.env.test?
require 'active_record/migration'

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
#
# Asset proxy settings
#

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
module AttrEncrypted
module Adapters
module ActiveRecord

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
Rails.backtrace_cleaner.remove_silencers!
# This allows us to see the proper caller of SQL calls in {development,test}.log

View File

@ -1 +1,3 @@
# frozen_string_literal: true
Rails.application.config.middleware.use(BatchLoader::Middleware)

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
module BootstrapFormBuilderCustomization
def label_class
"label-bold"

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
def bullet_enabled?
Gitlab::Utils.to_boolean(ENV['ENABLE_BULLET'].to_s)
end

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
# Technical debt, this should be ideally upstreamed.
#
# However, there's currently no way to hook before doing

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
# rubocop:disable Rails/Output
if Gitlab::Runtime.console?
# note that this will not print out when using `spring`

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file.
Rails.application.config.action_dispatch.use_cookies_with_metadata = true

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
# :short - 10 Nov
# :medium - Nov 10, 2007
# :long - November 10, 2007

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
default_url_options = {
host: Gitlab.config.gitlab.host,
protocol: Gitlab.config.gitlab.protocol,

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
if Rails.env.development? || ENV['GITLAB_LEGACY_PATH_LOG_MESSAGE']
deprecator = ActiveSupport::Deprecation.new('11.0', 'GitLab')

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
class DirectUploadsValidator
SUPPORTED_DIRECT_UPLOAD_PROVIDERS = [ObjectStorage::Config::GOOGLE_PROVIDER,
ObjectStorage::Config::AWS_PROVIDER,

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
Doorkeeper.configure do
# Change the ORM that doorkeeper will use.
# Currently supported options are :active_record, :mongoid2, :mongoid3, :mongo_mapper

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
Doorkeeper::OpenidConnect.configure do
issuer Gitlab.config.gitlab.url

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
# This middleware has to come after Gitlab::Metrics::RackMiddleware
# in the middleware stack, because it tracks events with
# GitLab Performance Monitoring

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
# The explicit schema version check is needed because during our migration rollback testing,
# `Shard.connected?` could be cached and return true even though the table doesn't exist
return unless Shard.connected?

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
module LocalCacheRegistryCleanupWithEnsure
LocalCacheRegistry =
ActiveSupport::Cache::Strategy::LocalCache::LocalCacheRegistry

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
#
# Monkey patching the https support for private urls
# See https://gitlab.com/gitlab-org/gitlab/issues/4879

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
module Sidekiq
module Worker
EnqueueFromTransactionError = Class.new(StandardError)

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
require 'gettext_i18n_rails/haml_parser'
require 'gettext_i18n_rails_js/parser/javascript'
require 'json'

View File

@ -1 +1,3 @@
# frozen_string_literal: true
Gitlab::Kas.ensure_secret!

View File

@ -1 +1,3 @@
# frozen_string_literal: true
Gitlab::Shell.ensure_secret_token!

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
begin
Gitlab::Workhorse.secret
rescue

View File

@ -1 +1,3 @@
# frozen_string_literal: true
Rails.application.config.middleware.use(Gitlab::Middleware::Go)

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
require 'logger'
GRPC_LOGGER = Logger.new(Rails.root.join('log/grpc.log'))

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
Hamlit::RailsTemplate.set_options(attr_quote: '"')
Hamlit::Filters.remove_filter('coffee')

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
HealthCheck.setup do |config|
config.standard_checks = %w(database migrations cache)
config.full_checks = %w(database migrations cache)

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
# This override allows passing `@hostname_override` to the SNI protocol,
# which is used to lookup the correct SSL certificate in the
# request handshake process.

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
module Kaminari
# Active Record specific page scope methods implementations
module ActiveRecordRelationMethodsWithLimit

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
Kaminari.configure do |config|
config.default_per_page = 20
config.max_per_page = 100

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
# Only use Lograge for Rails
unless Gitlab::Runtime.sidekiq?
Rails.application.reloader.to_prepare do

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
# Monkey patch mail 2.7.1 to fix quoted-printable issues with newlines
# The issues upstream invalidate SMIME signatures under some conditions
# This was working properly in 2.6.6

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file.
# Add new mime types for use in respond_to blocks:

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
MiniMagick.configure do |config|
config.cli = :graphicsmagick
end

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
# Remove this `if` condition when upgraded to rails 5.0.
# The body must be kept.
# Be sure to restart your server when you modify this file.

View File

@ -1 +1,3 @@
# frozen_string_literal: true
Octokit.middleware.insert_after Octokit::Middleware::FollowRedirects, Gitlab::Octokit::Middleware

View File

@ -1,3 +1,5 @@
# frozen_string_literal: true
if Gitlab::Auth::Ldap::Config.enabled?
module OmniAuth::Strategies
Gitlab::Auth::Ldap::Config.available_servers.each do |server|

Some files were not shown because too many files have changed in this diff Show More