Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-07-12 21:09:09 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-07-12 21:09:09 +0300
commitdd1c093e289dab5b2142e8e7f02883f2281e7910 (patch)
treee16d1733ecd3b693c205816102f42b78bd65394b /app
parentd9b3f39acad88d81eb7a75627c4325651fb7ff13 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue23
-rw-r--r--app/assets/javascripts/jobs/components/log/collapsible_section.vue33
-rw-r--r--app/assets/javascripts/jobs/components/log/line_number.vue6
-rw-r--r--app/assets/javascripts/jobs/constants.js2
-rw-r--r--app/assets/javascripts/jobs/store/mutations.js28
-rw-r--r--app/assets/javascripts/jobs/store/state.js3
-rw-r--r--app/assets/javascripts/jobs/store/utils.js75
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/create/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/edit/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/new/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/update/index.js2
-rw-r--r--app/assets/javascripts/runner/components/runner_filtered_search_bar.vue39
-rw-r--r--app/assets/javascripts/runner/components/runner_list.vue15
-rw-r--r--app/assets/javascripts/runner/runner_list/index.js3
-rw-r--r--app/assets/javascripts/runner/runner_list/runner_list_app.vue12
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss12
-rw-r--r--app/controllers/projects/jobs_controller.rb4
-rw-r--r--app/workers/repository_check/single_repository_worker.rb2
18 files changed, 189 insertions, 76 deletions
diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue b/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue
index 7b169b68d20..1137951ccfc 100644
--- a/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue
+++ b/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue
@@ -5,14 +5,14 @@ import highlight from '~/lib/utils/highlight';
import { truncateNamespace } from '~/lib/utils/text_utility';
import { mapVuexModuleState } from '~/lib/utils/vuex_module_mappers';
import Tracking from '~/tracking';
-import Identicon from '~/vue_shared/components/identicon.vue';
+import ProjectAvatar from '~/vue_shared/components/project_avatar.vue';
const trackingMixin = Tracking.mixin();
export default {
components: {
- Identicon,
GlButton,
+ ProjectAvatar,
},
mixins: [trackingMixin],
inject: ['vuexModule'],
@@ -64,19 +64,12 @@ export default {
class="gl-text-left gl-justify-content-start!"
@click="track('click_link', { label: `${dropdownType}_dropdown_frequent_items_list_item` })"
>
- <div
- ref="frequentItemsItemAvatarContainer"
- class="frequent-items-item-avatar-container avatar-container rect-avatar s32"
- >
- <img v-if="avatarUrl" ref="frequentItemsItemAvatar" :src="avatarUrl" class="avatar s32" />
- <identicon
- v-else
- :entity-id="itemId"
- :entity-name="itemName"
- size-class="s32"
- class="rect-avatar"
- />
- </div>
+ <project-avatar
+ class="gl-float-left gl-mr-3"
+ :project-avatar-url="avatarUrl"
+ :project-name="itemName"
+ aria-hidden="true"
+ />
<div ref="frequentItemsItemMetadataContainer" class="frequent-items-item-metadata-container">
<div
ref="frequentItemsItemTitle"
diff --git a/app/assets/javascripts/jobs/components/log/collapsible_section.vue b/app/assets/javascripts/jobs/components/log/collapsible_section.vue
index 55cdfb691f4..c0d5fac0e8d 100644
--- a/app/assets/javascripts/jobs/components/log/collapsible_section.vue
+++ b/app/assets/javascripts/jobs/components/log/collapsible_section.vue
@@ -1,4 +1,6 @@
<script>
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { INFINITELY_NESTED_COLLAPSIBLE_SECTIONS_FF } from '../../constants';
import LogLine from './line.vue';
import LogLineHeader from './line_header.vue';
@@ -7,7 +9,9 @@ export default {
components: {
LogLine,
LogLineHeader,
+ CollapsibleLogSection: () => import('./collapsible_section.vue'),
},
+ mixins: [glFeatureFlagsMixin()],
props: {
section: {
type: Object,
@@ -22,6 +26,9 @@ export default {
badgeDuration() {
return this.section.line && this.section.line.section_duration;
},
+ infinitelyCollapsibleSectionsFlag() {
+ return this.glFeatures?.[INFINITELY_NESTED_COLLAPSIBLE_SECTIONS_FF];
+ },
},
methods: {
handleOnClickCollapsibleLine(section) {
@@ -40,12 +47,26 @@ export default {
@toggleLine="handleOnClickCollapsibleLine(section)"
/>
<template v-if="!section.isClosed">
- <log-line
- v-for="line in section.lines"
- :key="line.offset"
- :line="line"
- :path="traceEndpoint"
- />
+ <template v-if="infinitelyCollapsibleSectionsFlag">
+ <template v-for="line in section.lines">
+ <collapsible-log-section
+ v-if="line.isHeader"
+ :key="line.line.offset"
+ :section="line"
+ :trace-endpoint="traceEndpoint"
+ @onClickCollapsibleLine="handleOnClickCollapsibleLine"
+ />
+ <log-line v-else :key="line.offset" :line="line" :path="traceEndpoint" />
+ </template>
+ </template>
+ <template v-else>
+ <log-line
+ v-for="line in section.lines"
+ :key="line.offset"
+ :line="line"
+ :path="traceEndpoint"
+ />
+ </template>
</template>
</div>
</template>
diff --git a/app/assets/javascripts/jobs/components/log/line_number.vue b/app/assets/javascripts/jobs/components/log/line_number.vue
index 7ca9154d2fe..c8ceac2c7ff 100644
--- a/app/assets/javascripts/jobs/components/log/line_number.vue
+++ b/app/assets/javascripts/jobs/components/log/line_number.vue
@@ -1,4 +1,6 @@
<script>
+import { INFINITELY_NESTED_COLLAPSIBLE_SECTIONS_FF } from '../../constants';
+
export default {
functional: true,
props: {
@@ -14,7 +16,9 @@ export default {
render(h, { props }) {
const { lineNumber, path } = props;
- const parsedLineNumber = lineNumber + 1;
+ const parsedLineNumber = gon.features?.[INFINITELY_NESTED_COLLAPSIBLE_SECTIONS_FF]
+ ? lineNumber
+ : lineNumber + 1;
const lineId = `L${parsedLineNumber}`;
const lineHref = `${path}#${lineId}`;
diff --git a/app/assets/javascripts/jobs/constants.js b/app/assets/javascripts/jobs/constants.js
index 3040d4e2379..97f31eee57c 100644
--- a/app/assets/javascripts/jobs/constants.js
+++ b/app/assets/javascripts/jobs/constants.js
@@ -24,3 +24,5 @@ export const JOB_RETRY_FORWARD_DEPLOYMENT_MODAL = {
};
export const SUCCESS_STATUS = 'SUCCESS';
+
+export const INFINITELY_NESTED_COLLAPSIBLE_SECTIONS_FF = 'infinitelyCollapsibleSections';
diff --git a/app/assets/javascripts/jobs/store/mutations.js b/app/assets/javascripts/jobs/store/mutations.js
index 924b811d0d6..4045d8a0c16 100644
--- a/app/assets/javascripts/jobs/store/mutations.js
+++ b/app/assets/javascripts/jobs/store/mutations.js
@@ -1,6 +1,7 @@
import Vue from 'vue';
+import { INFINITELY_NESTED_COLLAPSIBLE_SECTIONS_FF } from '../constants';
import * as types from './mutation_types';
-import { logLinesParser, updateIncrementalTrace } from './utils';
+import { logLinesParser, logLinesParserLegacy, updateIncrementalTrace } from './utils';
export default {
[types.SET_JOB_ENDPOINT](state, endpoint) {
@@ -20,12 +21,26 @@ export default {
},
[types.RECEIVE_TRACE_SUCCESS](state, log = {}) {
+ const infinitelyCollapsibleSectionsFlag =
+ gon.features?.[INFINITELY_NESTED_COLLAPSIBLE_SECTIONS_FF];
if (log.state) {
state.traceState = log.state;
}
if (log.append) {
- state.trace = log.lines ? updateIncrementalTrace(log.lines, state.trace) : state.trace;
+ if (infinitelyCollapsibleSectionsFlag) {
+ if (log.lines) {
+ const parsedResult = logLinesParser(
+ log.lines,
+ state.auxiliaryPartialTraceHelpers,
+ state.trace,
+ );
+ state.trace = parsedResult.parsedLines;
+ state.auxiliaryPartialTraceHelpers = parsedResult.auxiliaryPartialTraceHelpers;
+ }
+ } else {
+ state.trace = log.lines ? updateIncrementalTrace(log.lines, state.trace) : state.trace;
+ }
state.traceSize += log.size;
} else {
@@ -33,7 +48,14 @@ export default {
// the trace response will not have a defined
// html or size. We keep the old value otherwise these
// will be set to `null`
- state.trace = log.lines ? logLinesParser(log.lines) : state.trace;
+
+ if (infinitelyCollapsibleSectionsFlag) {
+ const parsedResult = logLinesParser(log.lines);
+ state.trace = parsedResult.parsedLines;
+ state.auxiliaryPartialTraceHelpers = parsedResult.auxiliaryPartialTraceHelpers;
+ } else {
+ state.trace = log.lines ? logLinesParserLegacy(log.lines) : state.trace;
+ }
state.traceSize = log.size || state.traceSize;
}
diff --git a/app/assets/javascripts/jobs/store/state.js b/app/assets/javascripts/jobs/store/state.js
index 2fe945b2985..718324c8bad 100644
--- a/app/assets/javascripts/jobs/store/state.js
+++ b/app/assets/javascripts/jobs/store/state.js
@@ -30,4 +30,7 @@ export default () => ({
selectedStage: '',
stages: [],
jobs: [],
+
+ // to parse partial logs
+ auxiliaryPartialTraceHelpers: {},
});
diff --git a/app/assets/javascripts/jobs/store/utils.js b/app/assets/javascripts/jobs/store/utils.js
index a0e0a0fb8bd..36391a4d433 100644
--- a/app/assets/javascripts/jobs/store/utils.js
+++ b/app/assets/javascripts/jobs/store/utils.js
@@ -104,7 +104,7 @@ export const getIncrementalLineNumber = (acc) => {
* @param Array accumulator
* @returns Array parsed log lines
*/
-export const logLinesParser = (lines = [], accumulator = []) =>
+export const logLinesParserLegacy = (lines = [], accumulator = []) =>
lines.reduce(
(acc, line, index) => {
const lineNumber = accumulator.length > 0 ? getIncrementalLineNumber(acc) : index;
@@ -131,6 +131,77 @@ export const logLinesParser = (lines = [], accumulator = []) =>
[...accumulator],
);
+export const logLinesParser = (lines = [], previousTraceState = {}, prevParsedLines = []) => {
+ let currentLine = previousTraceState?.prevLineCount ?? 0;
+ let currentHeader = previousTraceState?.currentHeader;
+ let isPreviousLineHeader = previousTraceState?.isPreviousLineHeader ?? false;
+ const parsedLines = prevParsedLines.length > 0 ? prevParsedLines : [];
+ const sectionsQueue = previousTraceState?.sectionsQueue ?? [];
+
+ for (let i = 0; i < lines.length; i += 1) {
+ const line = lines[i];
+ // First run we can use the current index, later runs we have to retrieve the last number of lines
+ currentLine = previousTraceState?.prevLineCount ? currentLine + 1 : i + 1;
+
+ if (line.section_header && !isPreviousLineHeader) {
+ // If there's no previous line header that means we're at the root of the log
+
+ isPreviousLineHeader = true;
+ parsedLines.push(parseHeaderLine(line, currentLine));
+ currentHeader = { index: parsedLines.length - 1 };
+ } else if (line.section_header && isPreviousLineHeader) {
+ // If there's a current section, we can't push to the parsedLines array
+ sectionsQueue.push(currentHeader);
+ currentHeader = parseHeaderLine(line, currentLine); // Let's parse the incoming header line
+ } else if (line.section && !line.section_duration) {
+ // We're inside a collapsible section and want to parse a standard line
+ if (currentHeader?.index) {
+ // If the current section header is only an index, add the line as part of the lines
+ // array of the current collapsible section
+ parsedLines[currentHeader.index].lines.push(parseLine(line, currentLine));
+ } else {
+ // Otherwise add it to the innermost collapsible section lines array
+ currentHeader.lines.push(parseLine(line, currentLine));
+ }
+ } else if (line.section && line.section_duration) {
+ // NOTE: This marks the end of a section_header
+ const previousSection = sectionsQueue.pop();
+
+ // Add the duration to section header
+ // If at the root, just push the end to the current parsedLine,
+ // otherwise, push it to the previous sections queue
+ if (currentHeader?.index) {
+ parsedLines[currentHeader.index].line.section_duration = line.section_duration;
+ isPreviousLineHeader = false;
+ currentHeader = null;
+ } else {
+ currentHeader.line.section_duration = line.section_duration;
+
+ if (previousSection && previousSection?.index) {
+ // Is the previous section on root?
+ parsedLines[previousSection.index].lines.push(currentHeader);
+ } else if (previousSection && !previousSection?.index) {
+ previousSection.lines.push(currentHeader);
+ }
+
+ currentHeader = previousSection;
+ }
+ } else {
+ parsedLines.push(parseLine(line, currentLine));
+ }
+ }
+
+ return {
+ parsedLines,
+ auxiliaryPartialTraceHelpers: {
+ isPreviousLineHeader,
+ currentHeader,
+ sectionsQueue,
+ prevLineCount: lines.length,
+ },
+ };
+};
+
/**
* Finds the repeated offset, removes the old one
*
@@ -177,5 +248,5 @@ export const findOffsetAndRemove = (newLog = [], oldParsed = []) => {
export const updateIncrementalTrace = (newLog = [], oldParsed = []) => {
const parsedLog = findOffsetAndRemove(newLog, oldParsed);
- return logLinesParser(newLog, parsedLog);
+ return logLinesParserLegacy(newLog, parsedLog);
};
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/create/index.js b/app/assets/javascripts/pages/projects/pipeline_schedules/create/index.js
index d65be6bc69e..6dd21380bec 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/create/index.js
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/create/index.js
@@ -1,3 +1,3 @@
import initForm from '../shared/init_form';
-document.addEventListener('DOMContentLoaded', initForm);
+initForm();
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/edit/index.js b/app/assets/javascripts/pages/projects/pipeline_schedules/edit/index.js
index d65be6bc69e..6dd21380bec 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/edit/index.js
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/edit/index.js
@@ -1,3 +1,3 @@
import initForm from '../shared/init_form';
-document.addEventListener('DOMContentLoaded', initForm);
+initForm();
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/new/index.js b/app/assets/javascripts/pages/projects/pipeline_schedules/new/index.js
index d65be6bc69e..6dd21380bec 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/new/index.js
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/new/index.js
@@ -1,3 +1,3 @@
import initForm from '../shared/init_form';
-document.addEventListener('DOMContentLoaded', initForm);
+initForm();
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/update/index.js b/app/assets/javascripts/pages/projects/pipeline_schedules/update/index.js
index d65be6bc69e..6dd21380bec 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/update/index.js
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/update/index.js
@@ -1,3 +1,3 @@
import initForm from '../shared/init_form';
-document.addEventListener('DOMContentLoaded', initForm);
+initForm();
diff --git a/app/assets/javascripts/runner/components/runner_filtered_search_bar.vue b/app/assets/javascripts/runner/components/runner_filtered_search_bar.vue
index 06b6d91a216..e14b3b17fa8 100644
--- a/app/assets/javascripts/runner/components/runner_filtered_search_bar.vue
+++ b/app/assets/javascripts/runner/components/runner_filtered_search_bar.vue
@@ -1,6 +1,6 @@
<script>
import { cloneDeep } from 'lodash';
-import { __, s__ } from '~/locale';
+import { formatNumber, sprintf, __, s__ } from '~/locale';
import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
@@ -58,6 +58,10 @@ export default {
type: String,
required: true,
},
+ activeRunnersCount: {
+ type: Number,
+ required: true,
+ },
},
data() {
// filtered_search_bar_root.vue may mutate the inital
@@ -119,6 +123,11 @@ export default {
},
];
},
+ activeRunnersMessage() {
+ return sprintf(__('Runners currently online: %{active_runners_count}'), {
+ active_runners_count: formatNumber(this.activeRunnersCount),
+ });
+ },
},
methods: {
onFilter(filters) {
@@ -144,16 +153,20 @@ export default {
};
</script>
<template>
- <filtered-search
- v-bind="$attrs"
- :namespace="namespace"
- recent-searches-storage-key="runners-search"
- :sort-options="$options.sortOptions"
- :initial-filter-value="initialFilterValue"
- :initial-sort-by="initialSortBy"
- :tokens="searchTokens"
- :search-input-placeholder="__('Search or filter results...')"
- @onFilter="onFilter"
- @onSort="onSort"
- />
+ <div>
+ <filtered-search
+ v-bind="$attrs"
+ :namespace="namespace"
+ recent-searches-storage-key="runners-search"
+ :sort-options="$options.sortOptions"
+ :initial-filter-value="initialFilterValue"
+ :initial-sort-by="initialSortBy"
+ :tokens="searchTokens"
+ :search-input-placeholder="__('Search or filter results...')"
+ data-testid="runners-filtered-search"
+ @onFilter="onFilter"
+ @onSort="onSort"
+ />
+ <div class="gl-text-right" data-testid="active-runners-message">{{ activeRunnersMessage }}</div>
+ </div>
</template>
diff --git a/app/assets/javascripts/runner/components/runner_list.vue b/app/assets/javascripts/runner/components/runner_list.vue
index a3efd51cab5..69a1f106ca8 100644
--- a/app/assets/javascripts/runner/components/runner_list.vue
+++ b/app/assets/javascripts/runner/components/runner_list.vue
@@ -1,7 +1,7 @@
<script>
import { GlTable, GlTooltipDirective, GlSkeletonLoader } from '@gitlab/ui';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { formatNumber, sprintf, __, s__ } from '~/locale';
+import { formatNumber, __, s__ } from '~/locale';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
import { RUNNER_JOB_COUNT_LIMIT } from '../constants';
import RunnerActionsCell from './cells/runner_actions_cell.vue';
@@ -52,17 +52,6 @@ export default {
type: Array,
required: true,
},
- activeRunnersCount: {
- type: Number,
- required: true,
- },
- },
- computed: {
- activeRunnersMessage() {
- return sprintf(__('Runners currently online: %{active_runners_count}'), {
- active_runners_count: formatNumber(this.activeRunnersCount),
- });
- },
},
methods: {
formatProjectCount(projectCount) {
@@ -101,12 +90,12 @@ export default {
</script>
<template>
<div>
- <div class="gl-text-right" data-testid="active-runners-message">{{ activeRunnersMessage }}</div>
<gl-table
:busy="loading"
:items="runners"
:fields="$options.fields"
:tbody-tr-attr="runnerTrAttr"
+ data-testid="runner-list"
stacked="md"
fixed
>
diff --git a/app/assets/javascripts/runner/runner_list/index.js b/app/assets/javascripts/runner/runner_list/index.js
index 5eba14a7948..16616f00d1e 100644
--- a/app/assets/javascripts/runner/runner_list/index.js
+++ b/app/assets/javascripts/runner/runner_list/index.js
@@ -12,7 +12,8 @@ export const initRunnerList = (selector = '#js-runner-list') => {
return null;
}
- // TODO `activeRunnersCount` should be implemented using a GraphQL API.
+ // TODO `activeRunnersCount` should be implemented using a GraphQL API
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/333806
const { activeRunnersCount, registrationToken, runnerInstallHelpPage } = el.dataset;
const apolloProvider = new VueApollo({
diff --git a/app/assets/javascripts/runner/runner_list/runner_list_app.vue b/app/assets/javascripts/runner/runner_list/runner_list_app.vue
index 8977d2a2a3d..8d39243d609 100644
--- a/app/assets/javascripts/runner/runner_list/runner_list_app.vue
+++ b/app/assets/javascripts/runner/runner_list/runner_list_app.vue
@@ -116,17 +116,17 @@ export default {
</div>
</div>
- <runner-filtered-search-bar v-model="search" namespace="admin_runners" />
+ <runner-filtered-search-bar
+ v-model="search"
+ namespace="admin_runners"
+ :active-runners-count="activeRunnersCount"
+ />
<div v-if="noRunnersFound" class="gl-text-center gl-p-5">
{{ __('No runners found') }}
</div>
<template v-else>
- <runner-list
- :runners="runners.items"
- :loading="runnersLoading"
- :active-runners-count="activeRunnersCount"
- />
+ <runner-list :runners="runners.items" :loading="runnersLoading" />
<runner-pagination v-model="search.pagination" :page-info="runners.pageInfo" />
</template>
</div>
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index 20d8d7d9469..144a396ea65 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -933,13 +933,9 @@ header.header-content .dropdown-menu.frequent-items-dropdown-menu {
}
.frequent-items-list-item-container {
- .frequent-items-item-avatar-container,
- .frequent-items-item-metadata-container {
- flex-shrink: 0;
- }
-
.frequent-items-item-metadata-container {
display: flex;
+ flex-shrink: 0;
flex-direction: column;
justify-content: center;
}
@@ -951,12 +947,6 @@ header.header-content .dropdown-menu.frequent-items-dropdown-menu {
white-space: nowrap;
}
- &:hover {
- .frequent-items-item-avatar-container .avatar {
- border-color: $gray-50;
- }
- }
-
.frequent-items-item-title {
font-size: $gl-font-size;
font-weight: 400;
diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb
index 92442fd4e28..49687a50ff6 100644
--- a/app/controllers/projects/jobs_controller.rb
+++ b/app/controllers/projects/jobs_controller.rb
@@ -17,6 +17,10 @@ class Projects::JobsController < Projects::ApplicationController
before_action :verify_proxy_request!, only: :proxy_websocket_authorize
before_action :push_jobs_table_vue, only: [:index]
+ before_action do
+ push_frontend_feature_flag(:infinitely_collapsible_sections, @project, default_enabled: :yaml)
+ end
+
layout 'project'
feature_category :continuous_integration
diff --git a/app/workers/repository_check/single_repository_worker.rb b/app/workers/repository_check/single_repository_worker.rb
index a9a8201205e..31d68e65b23 100644
--- a/app/workers/repository_check/single_repository_worker.rb
+++ b/app/workers/repository_check/single_repository_worker.rb
@@ -46,7 +46,7 @@ module RepositoryCheck
true
rescue Gitlab::Git::Repository::GitError => e
- Gitlab::RepositoryCheckLogger.error(e.message)
+ Gitlab::RepositoryCheckLogger.error("#{repository.full_path}: #{e.message}")
false
end