diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-01-26 18:09:30 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-01-26 18:09:30 +0000 |
commit | 25eb713a7fdb787a67d74a88a89433839aab5642 (patch) | |
tree | 43cfe6c45530aedfd7f96d6c6d0e5857ce1d5ee3 /app | |
parent | ff89c3c372cd3b317915fb21940f9c8c065d94c0 (diff) | |
download | gitlab-ce-25eb713a7fdb787a67d74a88a89433839aab5642.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
47 files changed, 492 insertions, 328 deletions
diff --git a/app/assets/javascripts/pages/admin/runners/index.js b/app/assets/javascripts/pages/admin/runners/index.js index e60c6133c7c..1b373226664 100644 --- a/app/assets/javascripts/pages/admin/runners/index.js +++ b/app/assets/javascripts/pages/admin/runners/index.js @@ -1,6 +1,7 @@ import initFilteredSearch from '~/pages/search/init_filtered_search'; import AdminRunnersFilteredSearchTokenKeys from '~/filtered_search/admin_runners_filtered_search_token_keys'; import { FILTERED_SEARCH } from '~/pages/constants'; +import { initInstallRunner } from '~/pages/shared/mount_runner_instructions'; document.addEventListener('DOMContentLoaded', () => { initFilteredSearch({ @@ -8,4 +9,8 @@ document.addEventListener('DOMContentLoaded', () => { filteredSearchTokenKeys: AdminRunnersFilteredSearchTokenKeys, useDefaultState: true, }); + + if (gon?.features?.runnerInstructions) { + initInstallRunner(); + } }); diff --git a/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js b/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js index e8d8c985ade..3ce779975f7 100644 --- a/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js +++ b/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js @@ -4,6 +4,7 @@ import initFilteredSearch from '~/pages/search/init_filtered_search'; import GroupRunnersFilteredSearchTokenKeys from '~/filtered_search/group_runners_filtered_search_token_keys'; import { FILTERED_SEARCH } from '~/pages/constants'; import initSharedRunnersForm from '~/group_settings/mount_shared_runners'; +import { initInstallRunner } from '~/pages/shared/mount_runner_instructions'; document.addEventListener('DOMContentLoaded', () => { // Initialize expandable settings panels @@ -18,4 +19,8 @@ document.addEventListener('DOMContentLoaded', () => { initSharedRunnersForm(); initVariableList(); + + if (gon?.features?.runnerInstructions) { + initInstallRunner(); + } }); diff --git a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js index 1321155b7ec..0eb40ff30f9 100644 --- a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js +++ b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js @@ -6,6 +6,7 @@ import initDeployFreeze from '~/deploy_freeze'; import initSettingsPipelinesTriggers from '~/ci_settings_pipeline_triggers'; import initSharedRunnersToggle from '~/projects/settings/mount_shared_runners_toggle'; import initArtifactsSettings from '~/artifacts_settings'; +import { initInstallRunner } from '~/pages/shared/mount_runner_instructions'; document.addEventListener('DOMContentLoaded', () => { // Initialize expandable settings panels @@ -39,4 +40,8 @@ document.addEventListener('DOMContentLoaded', () => { if (gon?.features?.vueifySharedRunnersToggle) { initSharedRunnersToggle(); } + + if (gon?.features?.runnerInstructions) { + initInstallRunner(); + } }); diff --git a/app/assets/javascripts/pages/shared/mount_runner_instructions.js b/app/assets/javascripts/pages/shared/mount_runner_instructions.js new file mode 100644 index 00000000000..51028e585b8 --- /dev/null +++ b/app/assets/javascripts/pages/shared/mount_runner_instructions.js @@ -0,0 +1,32 @@ +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createDefaultClient from '~/lib/graphql'; +import InstallRunnerInstructions from '~/vue_shared/components/runner_instructions/runner_instructions.vue'; + +Vue.use(VueApollo); + +export function initInstallRunner(componentId = 'js-install-runner') { + const installRunnerEl = document.getElementById(componentId); + + if (installRunnerEl) { + const defaultClient = createDefaultClient(); + const { projectPath, groupPath } = installRunnerEl.dataset; + + const apolloProvider = new VueApollo({ + defaultClient, + }); + + // eslint-disable-next-line no-new + new Vue({ + el: installRunnerEl, + apolloProvider, + provide: { + projectPath, + groupPath, + }, + render(createElement) { + return createElement(InstallRunnerInstructions); + }, + }); + } +} diff --git a/app/assets/javascripts/pipelines/components/legacy_header_component.vue b/app/assets/javascripts/pipelines/components/legacy_header_component.vue deleted file mode 100644 index c7b72be36ad..00000000000 --- a/app/assets/javascripts/pipelines/components/legacy_header_component.vue +++ /dev/null @@ -1,132 +0,0 @@ -<script> -import { GlLoadingIcon, GlModal, GlModalDirective, GlButton } from '@gitlab/ui'; -import ciHeader from '~/vue_shared/components/header_ci_component.vue'; -import eventHub from '../event_hub'; -import { __ } from '~/locale'; - -const DELETE_MODAL_ID = 'pipeline-delete-modal'; - -export default { - name: 'PipelineHeaderSection', - components: { - ciHeader, - GlLoadingIcon, - GlModal, - GlButton, - }, - directives: { - GlModal: GlModalDirective, - }, - props: { - pipeline: { - type: Object, - required: true, - }, - isLoading: { - type: Boolean, - required: true, - }, - }, - data() { - return { - isCanceling: false, - isRetrying: false, - isDeleting: false, - }; - }, - - computed: { - status() { - return this.pipeline.details && this.pipeline.details.status; - }, - shouldRenderContent() { - return !this.isLoading && Object.keys(this.pipeline).length; - }, - deleteModalConfirmationText() { - return __( - 'Are you sure you want to delete this pipeline? Doing so will expire all pipeline caches and delete all related objects, such as builds, logs, artifacts, and triggers. This action cannot be undone.', - ); - }, - }, - - methods: { - cancelPipeline() { - this.isCanceling = true; - eventHub.$emit('headerPostAction', this.pipeline.cancel_path); - }, - retryPipeline() { - this.isRetrying = true; - eventHub.$emit('headerPostAction', this.pipeline.retry_path); - }, - deletePipeline() { - this.isDeleting = true; - eventHub.$emit('headerDeleteAction', this.pipeline.delete_path); - }, - }, - DELETE_MODAL_ID, -}; -</script> -<template> - <div class="pipeline-header-container"> - <ci-header - v-if="shouldRenderContent" - :status="status" - :item-id="pipeline.id" - :time="pipeline.created_at" - :user="pipeline.user" - item-name="Pipeline" - > - <gl-button - v-if="pipeline.retry_path" - :loading="isRetrying" - :disabled="isRetrying" - data-testid="retryButton" - category="secondary" - variant="info" - @click="retryPipeline()" - > - {{ __('Retry') }} - </gl-button> - - <gl-button - v-if="pipeline.cancel_path" - :loading="isCanceling" - :disabled="isCanceling" - data-testid="cancelPipeline" - class="gl-ml-3" - category="primary" - variant="danger" - @click="cancelPipeline()" - > - {{ __('Cancel running') }} - </gl-button> - - <gl-button - v-if="pipeline.delete_path" - v-gl-modal="$options.DELETE_MODAL_ID" - :loading="isDeleting" - :disabled="isDeleting" - data-testid="deletePipeline" - class="gl-ml-3" - category="secondary" - variant="danger" - > - {{ __('Delete') }} - </gl-button> - </ci-header> - - <gl-loading-icon v-if="isLoading" size="lg" class="gl-mt-3 gl-mb-3" /> - - <gl-modal - :modal-id="$options.DELETE_MODAL_ID" - :title="__('Delete pipeline')" - :ok-title="__('Delete pipeline')" - ok-variant="danger" - @ok="deletePipeline()" - > - <p> - {{ deleteModalConfirmationText }} - </p> - </gl-modal> - </div> -</template> diff --git a/app/assets/javascripts/pipelines/pipeline_details_bundle.js b/app/assets/javascripts/pipelines/pipeline_details_bundle.js index 1c6f0b3f036..5ee5b45aac9 100644 --- a/app/assets/javascripts/pipelines/pipeline_details_bundle.js +++ b/app/assets/javascripts/pipelines/pipeline_details_bundle.js @@ -2,12 +2,9 @@ import Vue from 'vue'; import { deprecatedCreateFlash as Flash } from '~/flash'; import Translate from '~/vue_shared/translate'; import { __ } from '~/locale'; -import { setUrlFragment, redirectTo } from '~/lib/utils/url_utility'; import PipelineGraphLegacy from './components/graph/graph_component_legacy.vue'; import createDagApp from './pipeline_details_dag'; import GraphBundleMixin from './mixins/graph_pipeline_bundle_mixin'; -import legacyPipelineHeader from './components/legacy_header_component.vue'; -import eventHub from './event_hub'; import TestReports from './components/test_reports/test_reports.vue'; import createTestReportsStore from './stores/test_reports'; import { reportToSentry } from './components/graph/utils'; @@ -59,58 +56,6 @@ const createLegacyPipelinesDetailApp = (mediator) => { }); }; -const createLegacyPipelineHeaderApp = (mediator) => { - if (!document.querySelector(SELECTORS.PIPELINE_HEADER)) { - return; - } - // eslint-disable-next-line no-new - new Vue({ - el: SELECTORS.PIPELINE_HEADER, - components: { - legacyPipelineHeader, - }, - data() { - return { - mediator, - }; - }, - created() { - eventHub.$on('headerPostAction', this.postAction); - eventHub.$on('headerDeleteAction', this.deleteAction); - }, - beforeDestroy() { - eventHub.$off('headerPostAction', this.postAction); - eventHub.$off('headerDeleteAction', this.deleteAction); - }, - errorCaptured(err, _vm, info) { - reportToSentry('pipeline_details_bundle_legacy', `error: ${err}, info: ${info}`); - }, - methods: { - postAction(path) { - this.mediator.service - .postAction(path) - .then(() => this.mediator.refreshPipeline()) - .catch(() => Flash(__('An error occurred while making the request.'))); - }, - deleteAction(path) { - this.mediator.stopPipelinePoll(); - this.mediator.service - .deleteAction(path) - .then(({ request }) => redirectTo(setUrlFragment(request.responseURL, 'delete_success'))) - .catch(() => Flash(__('An error occurred while deleting the pipeline.'))); - }, - }, - render(createElement) { - return createElement('legacy-pipeline-header', { - props: { - isLoading: this.mediator.state.isLoading, - pipeline: this.mediator.store.state.pipeline, - }, - }); - }, - }); -}; - const createTestDetails = () => { const el = document.querySelector(SELECTORS.PIPELINE_TESTS); const { summaryEndpoint, suiteEndpoint } = el?.dataset || {}; @@ -140,19 +85,6 @@ export default async function () { gon.features.graphqlPipelineDetails || gon.features.graphqlPipelineDetailsUsers; const { dataset } = document.querySelector(SELECTORS.PIPELINE_DETAILS); - let mediator; - - if (!gon.features.graphqlPipelineHeader || !canShowNewPipelineDetails) { - try { - const { default: PipelinesMediator } = await import( - /* webpackChunkName: 'PipelinesMediator' */ './pipeline_details_mediator' - ); - mediator = new PipelinesMediator({ endpoint: dataset.endpoint }); - mediator.fetchPipeline(); - } catch { - Flash(__('An error occurred while loading the pipeline.')); - } - } if (canShowNewPipelineDetails) { try { @@ -166,19 +98,21 @@ export default async function () { Flash(__('An error occurred while loading the pipeline.')); } } else { + const { default: PipelinesMediator } = await import( + /* webpackChunkName: 'PipelinesMediator' */ './pipeline_details_mediator' + ); + const mediator = new PipelinesMediator({ endpoint: dataset.endpoint }); + mediator.fetchPipeline(); + createLegacyPipelinesDetailApp(mediator); } - if (gon.features.graphqlPipelineHeader) { - try { - const { createPipelineHeaderApp } = await import( - /* webpackChunkName: 'createPipelineHeaderApp' */ './pipeline_details_header' - ); - createPipelineHeaderApp(SELECTORS.PIPELINE_HEADER); - } catch { - Flash(__('An error occurred while loading a section of this page.')); - } - } else { - createLegacyPipelineHeaderApp(mediator); + try { + const { createPipelineHeaderApp } = await import( + /* webpackChunkName: 'createPipelineHeaderApp' */ './pipeline_details_header' + ); + createPipelineHeaderApp(SELECTORS.PIPELINE_HEADER); + } catch { + Flash(__('An error occurred while loading a section of this page.')); } } diff --git a/app/assets/javascripts/registry/explorer/index.js b/app/assets/javascripts/registry/explorer/index.js index a3890ab5c42..0ddbe50441b 100644 --- a/app/assets/javascripts/registry/explorer/index.js +++ b/app/assets/javascripts/registry/explorer/index.js @@ -29,7 +29,14 @@ export default () => { return null; } - const { endpoint, expirationPolicy, isGroupPage, isAdmin, ...config } = el.dataset; + const { + endpoint, + expirationPolicy, + isGroupPage, + isAdmin, + showUnfinishedTagCleanupCallout, + ...config + } = el.dataset; // This is a mini state to help the breadcrumb have the correct name in the details page const breadCrumbState = Vue.observable({ @@ -57,6 +64,7 @@ export default () => { expirationPolicy: expirationPolicy ? JSON.parse(expirationPolicy) : undefined, isGroupPage: parseBoolean(isGroupPage), isAdmin: parseBoolean(isAdmin), + showUnfinishedTagCleanupCallout: parseBoolean(showUnfinishedTagCleanupCallout), }, /* eslint-disable @gitlab/require-i18n-strings */ dockerBuildCommand: `docker build -t ${config.repositoryUrl} .`, diff --git a/app/assets/javascripts/registry/explorer/pages/details.vue b/app/assets/javascripts/registry/explorer/pages/details.vue index 0894fd6fcfa..71c610b6003 100644 --- a/app/assets/javascripts/registry/explorer/pages/details.vue +++ b/app/assets/javascripts/registry/explorer/pages/details.vue @@ -3,6 +3,7 @@ import { GlKeysetPagination, GlResizeObserverDirective } from '@gitlab/ui'; import { GlBreakpointInstance } from '@gitlab/ui/dist/utils'; import createFlash from '~/flash'; import Tracking from '~/tracking'; +import axios from '~/lib/utils/axios_utils'; import { joinPaths } from '~/lib/utils/url_utility'; import DeleteAlert from '../components/details_page/delete_alert.vue'; import PartialCleanupAlert from '../components/details_page/partial_cleanup_alert.vue'; @@ -68,7 +69,7 @@ export default { isMobile: false, mutationLoading: false, deleteAlertType: null, - dismissPartialCleanupWarning: false, + hidePartialCleanupWarning: false, }; }, computed: { @@ -86,8 +87,9 @@ export default { }, showPartialCleanupWarning() { return ( + this.config.showUnfinishedTagCleanupCallout && this.image?.expirationPolicyCleanupStatus === UNFINISHED_STATUS && - !this.dismissPartialCleanupWarning + !this.hidePartialCleanupWarning ); }, tracking() { @@ -168,6 +170,12 @@ export default { }); } }, + dismissPartialCleanupWarning() { + this.hidePartialCleanupWarning = true; + axios.post(this.config.userCalloutsPath, { + feature_name: this.config.userCalloutId, + }); + }, }, }; </script> @@ -185,7 +193,7 @@ export default { v-if="showPartialCleanupWarning" :run-cleanup-policies-help-page-path="config.runCleanupPoliciesHelpPagePath" :cleanup-policies-help-page-path="config.cleanupPoliciesHelpPagePath" - @dismiss="dismissPartialCleanupWarning = true" + @dismiss="dismissPartialCleanupWarning" /> <details-header :image="image" :metadata-loading="isLoading" /> diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/constants.js b/app/assets/javascripts/vue_shared/components/runner_instructions/constants.js new file mode 100644 index 00000000000..facace0d809 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/runner_instructions/constants.js @@ -0,0 +1,18 @@ +import { s__ } from '~/locale'; + +export const PLATFORMS_WITHOUT_ARCHITECTURES = ['docker', 'kubernetes']; + +export const INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES = { + docker: { + instructions: s__( + 'Runners|To install Runner in a container follow the instructions described in the GitLab documentation', + ), + link: 'https://docs.gitlab.com/runner/install/docker.html', + }, + kubernetes: { + instructions: s__( + 'Runners|To install Runner in Kubernetes follow the instructions described in the GitLab documentation.', + ), + link: 'https://docs.gitlab.com/runner/install/kubernetes.html', + }, +}; diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql b/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql new file mode 100644 index 00000000000..ff0626167a9 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql @@ -0,0 +1,20 @@ +query getRunnerPlatforms($projectPath: ID!, $groupPath: ID!) { + runnerPlatforms { + nodes { + name + humanReadableName + architectures { + nodes { + name + downloadLocation + } + } + } + } + project(fullPath: $projectPath) { + id + } + group(fullPath: $groupPath) { + id + } +} diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql b/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql new file mode 100644 index 00000000000..643c1991807 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql @@ -0,0 +1,16 @@ +query runnerSetupInstructions( + $platform: String! + $architecture: String! + $projectId: ID! + $groupId: ID! +) { + runnerSetup( + platform: $platform + architecture: $architecture + projectId: $projectId + groupId: $groupId + ) { + installInstructions + registerInstructions + } +} diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue new file mode 100644 index 00000000000..1d6db576942 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue @@ -0,0 +1,261 @@ +<script> +import { + GlAlert, + GlButton, + GlModal, + GlModalDirective, + GlButtonGroup, + GlDropdown, + GlDropdownItem, + GlIcon, +} from '@gitlab/ui'; +import { __, s__ } from '~/locale'; +import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue'; +import { + PLATFORMS_WITHOUT_ARCHITECTURES, + INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES, +} from './constants'; +import getRunnerPlatforms from './graphql/queries/get_runner_platforms.query.graphql'; +import getRunnerSetupInstructions from './graphql/queries/get_runner_setup.query.graphql'; + +export default { + components: { + GlAlert, + GlButton, + GlButtonGroup, + GlDropdown, + GlDropdownItem, + GlModal, + GlIcon, + ModalCopyButton, + }, + directives: { + GlModalDirective, + }, + inject: { + projectPath: { + default: '', + }, + groupPath: { + default: '', + }, + }, + apollo: { + runnerPlatforms: { + query: getRunnerPlatforms, + variables() { + return { + projectPath: this.projectPath, + groupPath: this.groupPath, + }; + }, + error() { + this.showAlert = true; + }, + result({ data }) { + this.project = data?.project; + this.group = data?.group; + + this.selectPlatform(this.platforms[0].name); + }, + }, + }, + data() { + return { + showAlert: false, + selectedPlatformArchitectures: [], + selectedPlatform: { + name: '', + }, + selectedArchitecture: {}, + runnerPlatforms: {}, + instructions: {}, + project: {}, + group: {}, + }; + }, + computed: { + isPlatformSelected() { + return Object.keys(this.selectedPlatform).length > 0; + }, + instructionsEmpty() { + return Object.keys(this.instructions).length === 0; + }, + groupId() { + return this.group?.id ?? ''; + }, + projectId() { + return this.project?.id ?? ''; + }, + platforms() { + return this.runnerPlatforms?.nodes; + }, + hasArchitecureList() { + return !PLATFORMS_WITHOUT_ARCHITECTURES.includes(this.selectedPlatform?.name); + }, + instructionsWithoutArchitecture() { + return INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES[this.selectedPlatform.name]?.instructions; + }, + runnerInstallationLink() { + return INSTRUCTIONS_PLATFORMS_WITHOUT_ARCHITECTURES[this.selectedPlatform.name]?.link; + }, + }, + methods: { + selectPlatform(name) { + this.selectedPlatform = this.platforms.find((platform) => platform.name === name); + if (this.hasArchitecureList) { + this.selectedPlatformArchitectures = this.selectedPlatform?.architectures?.nodes; + [this.selectedArchitecture] = this.selectedPlatformArchitectures; + this.selectArchitecture(this.selectedArchitecture); + } + }, + selectArchitecture(architecture) { + this.selectedArchitecture = architecture; + + this.$apollo.addSmartQuery('instructions', { + variables() { + return { + platform: this.selectedPlatform.name, + architecture: this.selectedArchitecture.name, + projectId: this.projectId, + groupId: this.groupId, + }; + }, + query: getRunnerSetupInstructions, + update(data) { + return data?.runnerSetup; + }, + error() { + this.showAlert = true; + }, + }); + }, + toggleAlert(state) { + this.showAlert = state; + }, + }, + modalId: 'installation-instructions-modal', + i18n: { + installARunner: s__('Runners|Install a Runner'), + architecture: s__('Runners|Architecture'), + downloadInstallBinary: s__('Runners|Download and Install Binary'), + downloadLatestBinary: s__('Runners|Download Latest Binary'), + registerRunner: s__('Runners|Register Runner'), + method: __('Method'), + fetchError: s__('Runners|An error has occurred fetching instructions'), + instructions: s__('Runners|Show Runner installation instructions'), + copyInstructions: s__('Runners|Copy instructions'), + }, + closeButton: { + text: __('Close'), + attributes: [{ variant: 'default' }], + }, +}; +</script> +<template> + <div> + <gl-button + v-gl-modal-directive="$options.modalId" + class="gl-mt-4" + data-testid="show-modal-button" + > + {{ $options.i18n.instructions }} + </gl-button> + <gl-modal + :modal-id="$options.modalId" + :title="$options.i18n.installARunner" + :action-secondary="$options.closeButton" + > + <gl-alert v-if="showAlert" variant="danger" @dismiss="toggleAlert(false)"> + {{ $options.i18n.fetchError }} + </gl-alert> + <h5>{{ __('Environment') }}</h5> + <gl-button-group class="gl-mb-5"> + <gl-button + v-for="platform in platforms" + :key="platform.name" + data-testid="platform-button" + @click="selectPlatform(platform.name)" + > + {{ platform.humanReadableName }} + </gl-button> + </gl-button-group> + <template v-if="hasArchitecureList"> + <template v-if="isPlatformSelected"> + <h5> + {{ $options.i18n.architecture }} + </h5> + <gl-dropdown class="gl-mb-5" :text="selectedArchitecture.name"> + <gl-dropdown-item + v-for="architecture in selectedPlatformArchitectures" + :key="architecture.name" + data-testid="architecture-dropdown-item" + @click="selectArchitecture(architecture)" + > + {{ architecture.name }} + </gl-dropdown-item> + </gl-dropdown> + <div class="gl-display-flex gl-align-items-center gl-mb-5"> + <h5>{{ $options.i18n.downloadInstallBinary }}</h5> + <gl-button + class="gl-ml-auto" + :href="selectedArchitecture.downloadLocation" + download + data-testid="binary-download-button" + > + {{ $options.i18n.downloadLatestBinary }} + </gl-button> + </div> + </template> + <template v-if="!instructionsEmpty"> + <div class="gl-display-flex"> + <pre + class="gl-bg-gray gl-flex-fill-1 gl-white-space-pre-line" + data-testid="binary-instructions" + > + + {{ instructions.installInstructions }} + </pre + > + <modal-copy-button + :title="$options.i18n.copyInstructions" + :text="instructions.installInstructions" + :modal-id="$options.modalId" + css-classes="gl-align-self-start gl-ml-2 gl-mt-2" + category="tertiary" + /> + </div> + + <hr /> + <h5 class="gl-mb-5">{{ $options.i18n.registerRunner }}</h5> + <h5 class="gl-mb-5">{{ $options.i18n.method }}</h5> + <div class="gl-display-flex"> + <pre + class="gl-bg-gray gl-flex-fill-1 gl-white-space-pre-line" + data-testid="runner-instructions" + > + {{ instructions.registerInstructions }} + </pre + > + <modal-copy-button + :title="$options.i18n.copyInstructions" + :text="instructions.registerInstructions" + :modal-id="$options.modalId" + css-classes="gl-align-self-start gl-ml-2 gl-mt-2" + category="tertiary" + /> + </div> + </template> + </template> + <template v-else> + <div> + <p>{{ instructionsWithoutArchitecture }}</p> + <gl-button :href="runnerInstallationLink"> + <gl-icon name="external-link" /> + {{ s__('Runners|View installation instructions') }} + </gl-button> + </div> + </template> + </gl-modal> + </div> +</template> diff --git a/app/assets/stylesheets/_page_specific_files.scss b/app/assets/stylesheets/_page_specific_files.scss index 42d15635566..20ff78d32d3 100644 --- a/app/assets/stylesheets/_page_specific_files.scss +++ b/app/assets/stylesheets/_page_specific_files.scss @@ -1,4 +1,3 @@ -@import './pages/admin'; @import './pages/branches'; @import './pages/ci_projects'; @import './pages/clusters'; diff --git a/app/assets/stylesheets/page_bundles/admin/application_settings_metrics_and_profiling.scss b/app/assets/stylesheets/page_bundles/admin/application_settings_metrics_and_profiling.scss new file mode 100644 index 00000000000..41bb6d107f1 --- /dev/null +++ b/app/assets/stylesheets/page_bundles/admin/application_settings_metrics_and_profiling.scss @@ -0,0 +1,3 @@ +.usage-data { + max-height: 400px; +} diff --git a/app/assets/stylesheets/page_bundles/admin/jobs_index.scss b/app/assets/stylesheets/page_bundles/admin/jobs_index.scss new file mode 100644 index 00000000000..7844cae5f87 --- /dev/null +++ b/app/assets/stylesheets/page_bundles/admin/jobs_index.scss @@ -0,0 +1,5 @@ +.admin-builds-table { + td:last-child { + min-width: 120px; + } +} diff --git a/app/assets/stylesheets/pages/admin.scss b/app/assets/stylesheets/pages/admin.scss deleted file mode 100644 index 34834b9a4a9..00000000000 --- a/app/assets/stylesheets/pages/admin.scss +++ /dev/null @@ -1,11 +0,0 @@ -.usage-data { - max-height: 400px; -} - -[data-page='admin:jobs:index'] { - .admin-builds-table { - td:last-child { - min-width: 120px; - } - } -} diff --git a/app/controllers/admin/runners_controller.rb b/app/controllers/admin/runners_controller.rb index 576b148fbff..91cb33dd4c6 100644 --- a/app/controllers/admin/runners_controller.rb +++ b/app/controllers/admin/runners_controller.rb @@ -4,6 +4,9 @@ class Admin::RunnersController < Admin::ApplicationController include RunnerSetupScripts before_action :runner, except: [:index, :tag_list, :runner_setup_scripts] + before_action do + push_frontend_feature_flag(:runner_instructions, default_enabled: :yaml) + end feature_category :continuous_integration diff --git a/app/controllers/groups/settings/ci_cd_controller.rb b/app/controllers/groups/settings/ci_cd_controller.rb index 723edc4b7e9..a45f3f18976 100644 --- a/app/controllers/groups/settings/ci_cd_controller.rb +++ b/app/controllers/groups/settings/ci_cd_controller.rb @@ -9,6 +9,9 @@ module Groups before_action :authorize_admin_group! before_action :authorize_update_max_artifacts_size!, only: [:update] before_action :define_variables, only: [:show] + before_action do + push_frontend_feature_flag(:runner_instructions, @group, default_enabled: :yaml) + end feature_category :continuous_integration diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index 21ff23c6440..052a7aca069 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -14,7 +14,6 @@ class Projects::PipelinesController < Projects::ApplicationController before_action do push_frontend_feature_flag(:pipelines_security_report_summary, project) push_frontend_feature_flag(:new_pipeline_form, project, default_enabled: true) - push_frontend_feature_flag(:graphql_pipeline_header, project, type: :development, default_enabled: false) push_frontend_feature_flag(:graphql_pipeline_details, project, type: :development, default_enabled: :yaml) push_frontend_feature_flag(:graphql_pipeline_details_users, current_user, type: :development, default_enabled: :yaml) push_frontend_feature_flag(:new_pipeline_form_prefilled_vars, project, type: :development, default_enabled: true) diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb index 31533dfeea0..7586c74431a 100644 --- a/app/controllers/projects/settings/ci_cd_controller.rb +++ b/app/controllers/projects/settings/ci_cd_controller.rb @@ -12,6 +12,7 @@ module Projects before_action do push_frontend_feature_flag(:ajax_new_deploy_token, @project) push_frontend_feature_flag(:vueify_shared_runners_toggle, @project) + push_frontend_feature_flag(:runner_instructions, @project, default_enabled: :yaml) end helper_method :highlight_badge diff --git a/app/graphql/mutations/alert_management/http_integration/create.rb b/app/graphql/mutations/alert_management/http_integration/create.rb index e1531148a76..2d7bffb4333 100644 --- a/app/graphql/mutations/alert_management/http_integration/create.rb +++ b/app/graphql/mutations/alert_management/http_integration/create.rb @@ -4,7 +4,7 @@ module Mutations module AlertManagement module HttpIntegration class Create < HttpIntegrationBase - include ResolvesProject + include FindsProject graphql_name 'HttpIntegrationCreate' @@ -21,7 +21,7 @@ module Mutations description: 'Whether the integration is receiving alerts.' def resolve(args) - project = authorized_find!(full_path: args[:project_path]) + project = authorized_find!(args[:project_path]) response ::AlertManagement::HttpIntegrations::CreateService.new( project, @@ -29,12 +29,6 @@ module Mutations http_integration_params(project, args) ).execute end - - private - - def find_object(full_path:) - resolve_project(full_path: full_path) - end end end end diff --git a/app/graphql/mutations/alert_management/prometheus_integration/create.rb b/app/graphql/mutations/alert_management/prometheus_integration/create.rb index c676cde90b4..87e6bc46937 100644 --- a/app/graphql/mutations/alert_management/prometheus_integration/create.rb +++ b/app/graphql/mutations/alert_management/prometheus_integration/create.rb @@ -4,7 +4,7 @@ module Mutations module AlertManagement module PrometheusIntegration class Create < PrometheusIntegrationBase - include ResolvesProject + include FindsProject graphql_name 'PrometheusIntegrationCreate' @@ -21,7 +21,7 @@ module Mutations description: 'Endpoint at which prometheus can be queried.' def resolve(args) - project = authorized_find!(full_path: args[:project_path]) + project = authorized_find!(args[:project_path]) return integration_exists if project.prometheus_service @@ -37,10 +37,6 @@ module Mutations private - def find_object(full_path:) - resolve_project(full_path: full_path) - end - def integration_exists response(nil, message: _('Multiple Prometheus integrations are not supported')) end diff --git a/app/graphql/mutations/branches/create.rb b/app/graphql/mutations/branches/create.rb index 9fe9bef5403..6354976f1ea 100644 --- a/app/graphql/mutations/branches/create.rb +++ b/app/graphql/mutations/branches/create.rb @@ -3,7 +3,7 @@ module Mutations module Branches class Create < BaseMutation - include ResolvesProject + include FindsProject graphql_name 'CreateBranch' @@ -28,7 +28,7 @@ module Mutations authorize :push_code def resolve(project_path:, name:, ref:) - project = authorized_find!(full_path: project_path) + project = authorized_find!(project_path) context.scoped_set!(:branch_project, project) @@ -40,12 +40,6 @@ module Mutations errors: Array.wrap(result[:message]) } end - - private - - def find_object(full_path:) - resolve_project(full_path: full_path) - end end end end diff --git a/app/graphql/mutations/commits/create.rb b/app/graphql/mutations/commits/create.rb index ae14401558b..84933fee5d2 100644 --- a/app/graphql/mutations/commits/create.rb +++ b/app/graphql/mutations/commits/create.rb @@ -3,7 +3,7 @@ module Mutations module Commits class Create < BaseMutation - include ResolvesProject + include FindsProject graphql_name 'CommitCreate' @@ -37,7 +37,7 @@ module Mutations authorize :push_code def resolve(project_path:, branch:, message:, actions:, **args) - project = authorized_find!(full_path: project_path) + project = authorized_find!(project_path) attributes = { commit_message: message, @@ -53,12 +53,6 @@ module Mutations errors: Array.wrap(result[:message]) } end - - private - - def find_object(full_path:) - resolve_project(full_path: full_path) - end end end end diff --git a/app/graphql/mutations/container_expiration_policies/update.rb b/app/graphql/mutations/container_expiration_policies/update.rb index 37cf2fa6bf3..f61d852bb6c 100644 --- a/app/graphql/mutations/container_expiration_policies/update.rb +++ b/app/graphql/mutations/container_expiration_policies/update.rb @@ -3,7 +3,7 @@ module Mutations module ContainerExpirationPolicies class Update < Mutations::BaseMutation - include ResolvesProject + include FindsProject graphql_name 'UpdateContainerExpirationPolicy' @@ -50,7 +50,7 @@ module Mutations description: 'The container expiration policy after mutation.' def resolve(project_path:, **args) - project = authorized_find!(full_path: project_path) + project = authorized_find!(project_path) result = ::ContainerExpirationPolicies::UpdateService .new(container: project, current_user: current_user, params: args) @@ -61,12 +61,6 @@ module Mutations errors: result.errors } end - - private - - def find_object(full_path:) - resolve_project(full_path: full_path) - end end end end diff --git a/app/graphql/mutations/issues/create.rb b/app/graphql/mutations/issues/create.rb index 18b80ff1736..37fddd92832 100644 --- a/app/graphql/mutations/issues/create.rb +++ b/app/graphql/mutations/issues/create.rb @@ -3,7 +3,7 @@ module Mutations module Issues class Create < BaseMutation - include ResolvesProject + include FindsProject graphql_name 'CreateIssue' authorize :create_issue @@ -70,7 +70,7 @@ module Mutations end def resolve(project_path:, **attributes) - project = authorized_find!(full_path: project_path) + project = authorized_find!(project_path) params = build_create_issue_params(attributes.merge(author_id: current_user.id)) issue = ::Issues::CreateService.new(project, current_user, params).execute @@ -98,10 +98,6 @@ module Mutations def mutually_exclusive_label_args [:labels, :label_ids] end - - def find_object(full_path:) - resolve_project(full_path: full_path) - end end end end diff --git a/app/graphql/mutations/jira_import/import_users.rb b/app/graphql/mutations/jira_import/import_users.rb index 616ef390657..af2bb18161f 100644 --- a/app/graphql/mutations/jira_import/import_users.rb +++ b/app/graphql/mutations/jira_import/import_users.rb @@ -3,10 +3,12 @@ module Mutations module JiraImport class ImportUsers < BaseMutation - include ResolvesProject + include FindsProject graphql_name 'JiraImportUsers' + authorize :admin_project + field :jira_users, [Types::JiraUserType], null: true, @@ -20,7 +22,7 @@ module Mutations description: 'The index of the record the import should started at, default 0 (50 records returned).' def resolve(project_path:, start_at: 0) - project = authorized_find!(full_path: project_path) + project = authorized_find!(project_path) service_response = ::JiraImport::UsersImporter.new(context[:current_user], project, start_at.to_i).execute @@ -29,16 +31,6 @@ module Mutations errors: service_response.errors } end - - private - - def find_object(full_path:) - resolve_project(full_path: full_path) - end - - def authorized_resource?(project) - Ability.allowed?(context[:current_user], :admin_project, project) - end end end end diff --git a/app/graphql/mutations/jira_import/start.rb b/app/graphql/mutations/jira_import/start.rb index 3d50ebde13a..e31aaf53a09 100644 --- a/app/graphql/mutations/jira_import/start.rb +++ b/app/graphql/mutations/jira_import/start.rb @@ -3,10 +3,12 @@ module Mutations module JiraImport class Start < BaseMutation - include ResolvesProject + include FindsProject graphql_name 'JiraImportStart' + authorize :admin_project + field :jira_import, Types::JiraImportType, null: true, @@ -27,7 +29,7 @@ module Mutations description: 'The mapping of Jira to GitLab users.' def resolve(project_path:, jira_project_key:, users_mapping:) - project = authorized_find!(full_path: project_path) + project = authorized_find!(project_path) mapping = users_mapping.to_ary.map { |map| map.to_hash } service_response = ::JiraImport::StartImportService @@ -40,16 +42,6 @@ module Mutations errors: service_response.errors } end - - private - - def find_object(full_path:) - resolve_project(full_path: full_path) - end - - def authorized_resource?(project) - Ability.allowed?(context[:current_user], :admin_project, project) - end end end end diff --git a/app/graphql/mutations/merge_requests/create.rb b/app/graphql/mutations/merge_requests/create.rb index 64fa8417e50..9ac8f70be95 100644 --- a/app/graphql/mutations/merge_requests/create.rb +++ b/app/graphql/mutations/merge_requests/create.rb @@ -3,7 +3,7 @@ module Mutations module MergeRequests class Create < BaseMutation - include ResolvesProject + include FindsProject graphql_name 'MergeRequestCreate' @@ -39,7 +39,7 @@ module Mutations authorize :create_merge_request_from def resolve(project_path:, **attributes) - project = authorized_find!(full_path: project_path) + project = authorized_find!(project_path) params = attributes.merge(author_id: current_user.id) merge_request = ::MergeRequests::CreateService.new(project, current_user, params).execute @@ -49,12 +49,6 @@ module Mutations errors: errors_on_object(merge_request) } end - - private - - def find_object(full_path:) - resolve_project(full_path: full_path) - end end end end diff --git a/app/graphql/mutations/releases/base.rb b/app/graphql/mutations/releases/base.rb index dd1724fe320..610e9cd9cde 100644 --- a/app/graphql/mutations/releases/base.rb +++ b/app/graphql/mutations/releases/base.rb @@ -3,17 +3,11 @@ module Mutations module Releases class Base < BaseMutation - include ResolvesProject + include FindsProject argument :project_path, GraphQL::ID_TYPE, required: true, description: 'Full path of the project the release is associated with.' - - private - - def find_object(full_path:) - resolve_project(full_path: full_path) - end end end end diff --git a/app/graphql/mutations/releases/create.rb b/app/graphql/mutations/releases/create.rb index 91ac256033e..914c1302094 100644 --- a/app/graphql/mutations/releases/create.rb +++ b/app/graphql/mutations/releases/create.rb @@ -41,7 +41,7 @@ module Mutations authorize :create_release def resolve(project_path:, assets: nil, **scalars) - project = authorized_find!(full_path: project_path) + project = authorized_find!(project_path) params = { **scalars, diff --git a/app/graphql/mutations/releases/delete.rb b/app/graphql/mutations/releases/delete.rb index e887b702cce..020c9133b58 100644 --- a/app/graphql/mutations/releases/delete.rb +++ b/app/graphql/mutations/releases/delete.rb @@ -17,7 +17,7 @@ module Mutations authorize :destroy_release def resolve(project_path:, tag:) - project = authorized_find!(full_path: project_path) + project = authorized_find!(project_path) params = { tag: tag }.with_indifferent_access diff --git a/app/graphql/mutations/releases/update.rb b/app/graphql/mutations/releases/update.rb index dff743254bd..35f2a7b3d4b 100644 --- a/app/graphql/mutations/releases/update.rb +++ b/app/graphql/mutations/releases/update.rb @@ -47,7 +47,7 @@ module Mutations end def resolve(project_path:, **scalars) - project = authorized_find!(full_path: project_path) + project = authorized_find!(project_path) params = scalars.with_indifferent_access diff --git a/app/graphql/mutations/security/ci_configuration/configure_sast.rb b/app/graphql/mutations/security/ci_configuration/configure_sast.rb index 6cb3704a19b..e4a3f815396 100644 --- a/app/graphql/mutations/security/ci_configuration/configure_sast.rb +++ b/app/graphql/mutations/security/ci_configuration/configure_sast.rb @@ -4,7 +4,7 @@ module Mutations module Security module CiConfiguration class ConfigureSast < BaseMutation - include ResolvesProject + include FindsProject graphql_name 'ConfigureSast' @@ -25,7 +25,7 @@ module Mutations authorize :push_code def resolve(project_path:, configuration:) - project = authorized_find!(full_path: project_path) + project = authorized_find!(project_path) result = ::Security::CiConfiguration::SastCreateService.new(project, current_user, configuration).execute prepare_response(result) @@ -33,10 +33,6 @@ module Mutations private - def find_object(full_path:) - resolve_project(full_path: full_path) - end - def prepare_response(result) { status: result[:status], diff --git a/app/helpers/user_callouts_helper.rb b/app/helpers/user_callouts_helper.rb index a06a31ddf32..f55a6c3c9e5 100644 --- a/app/helpers/user_callouts_helper.rb +++ b/app/helpers/user_callouts_helper.rb @@ -11,6 +11,7 @@ module UserCalloutsHelper CUSTOMIZE_HOMEPAGE = 'customize_homepage' FEATURE_FLAGS_NEW_VERSION = 'feature_flags_new_version' REGISTRATION_ENABLED_CALLOUT = 'registration_enabled_callout' + UNFINISHED_TAG_CLEANUP_CALLOUT = 'unfinished_tag_cleanup_callout' def show_admin_integrations_moved? !user_dismissed?(ADMIN_INTEGRATIONS_MOVED) @@ -56,6 +57,10 @@ module UserCalloutsHelper !user_dismissed?(FEATURE_FLAGS_NEW_VERSION) end + def show_unfinished_tag_cleanup_callout? + !user_dismissed?(UNFINISHED_TAG_CLEANUP_CALLOUT) + end + def show_registration_enabled_user_callout? !Gitlab.com? && current_user&.admin? && diff --git a/app/models/pages/lookup_path.rb b/app/models/pages/lookup_path.rb index b7e27f460a8..fa2d7bb316c 100644 --- a/app/models/pages/lookup_path.rb +++ b/app/models/pages/lookup_path.rb @@ -5,6 +5,7 @@ module Pages include Gitlab::Utils::StrongMemoize LegacyStorageDisabledError = Class.new(::StandardError) + MIGRATED_FILE_NAME = "_migrated.zip" def initialize(project, trim_prefix: nil, domain: nil) @project = project @@ -54,6 +55,8 @@ module Pages return if deployment.file.file_storage? && !Feature.enabled?(:pages_serve_with_zip_file_protocol, project) + return if deployment.file.filename == MIGRATED_FILE_NAME && !Feature.enabled?(:pages_serve_from_migrated_zip, project) + global_id = ::Gitlab::GlobalId.build(deployment, id: deployment.id).to_s { diff --git a/app/models/user_callout.rb b/app/models/user_callout.rb index ad5651f9439..6e57673bafc 100644 --- a/app/models/user_callout.rb +++ b/app/models/user_callout.rb @@ -27,7 +27,8 @@ class UserCallout < ApplicationRecord customize_homepage: 23, feature_flags_new_version: 24, registration_enabled_callout: 25, - new_user_signups_cap_reached: 26 # EE-only + new_user_signups_cap_reached: 26, # EE-only + unfinished_tag_cleanup_callout: 27 } validates :user, presence: true diff --git a/app/services/git/wiki_push_service.rb b/app/services/git/wiki_push_service.rb index 87e2be858c0..99659bc8ab2 100644 --- a/app/services/git/wiki_push_service.rb +++ b/app/services/git/wiki_push_service.rb @@ -16,6 +16,7 @@ module Git wiki.after_post_receive process_changes + perform_housekeeping if Feature.enabled?(:wiki_housekeeping, wiki.container) end private @@ -72,6 +73,14 @@ module Git def default_branch_changes @default_branch_changes ||= changes.select { |change| on_default_branch?(change) } end + + def perform_housekeeping + housekeeping = Repositories::HousekeepingService.new(wiki) + housekeeping.increment! + housekeeping.execute if housekeeping.needed? + rescue Repositories::HousekeepingService::LeaseTaken + # no-op + end end end diff --git a/app/views/admin/application_settings/metrics_and_profiling.html.haml b/app/views/admin/application_settings/metrics_and_profiling.html.haml index 4959e596148..113ff20e910 100644 --- a/app/views/admin/application_settings/metrics_and_profiling.html.haml +++ b/app/views/admin/application_settings/metrics_and_profiling.html.haml @@ -1,3 +1,5 @@ +- add_page_specific_style 'page_bundles/admin/application_settings_metrics_and_profiling' + - breadcrumb_title _("Metrics and profiling") - page_title _("Metrics and profiling") - @content_class = "limit-container-width" unless fluid_layout diff --git a/app/views/admin/jobs/index.html.haml b/app/views/admin/jobs/index.html.haml index ce377eeea54..670628f7463 100644 --- a/app/views/admin/jobs/index.html.haml +++ b/app/views/admin/jobs/index.html.haml @@ -1,4 +1,5 @@ - add_page_specific_style 'page_bundles/ci_status' +- add_page_specific_style 'page_bundles/admin/jobs_index' - breadcrumb_title _("Jobs") - page_title _("Jobs") diff --git a/app/views/admin/runners/index.html.haml b/app/views/admin/runners/index.html.haml index 9f19d3f5d4e..5ddb03bcc04 100644 --- a/app/views/admin/runners/index.html.haml +++ b/app/views/admin/runners/index.html.haml @@ -39,7 +39,9 @@ = render partial: 'ci/runner/how_to_setup_runner', locals: { registration_token: Gitlab::CurrentSettings.runners_registration_token, type: 'shared', - reset_token_url: reset_registration_token_admin_application_settings_path } + reset_token_url: reset_registration_token_admin_application_settings_path, + project_path: '', + group_path: '' } .row .col-sm-9 diff --git a/app/views/ci/runner/_how_to_setup_runner.html.haml b/app/views/ci/runner/_how_to_setup_runner.html.haml index fc3d5360f9b..6c2e4c69d83 100644 --- a/app/views/ci/runner/_how_to_setup_runner.html.haml +++ b/app/views/ci/runner/_how_to_setup_runner.html.haml @@ -21,3 +21,5 @@ = button_to _("Reset registration token"), reset_token_url, method: :put, class: 'gl-button btn btn-default', data: { confirm: _("Are you sure you want to reset the registration token?") } + +#js-install-runner{ data: { project_path: project_path, group_path: group_path } } diff --git a/app/views/groups/registry/repositories/index.html.haml b/app/views/groups/registry/repositories/index.html.haml index 6d0a3e03019..4f4b6c1089c 100644 --- a/app/views/groups/registry/repositories/index.html.haml +++ b/app/views/groups/registry/repositories/index.html.haml @@ -17,4 +17,7 @@ is_group_page: "true", "group_path": @group.full_path, "gid_prefix": container_repository_gid_prefix, - character_error: @character_error.to_s } } + character_error: @character_error.to_s, + user_callouts_path: user_callouts_path, + user_callout_id: UserCalloutsHelper::UNFINISHED_TAG_CLEANUP_CALLOUT, + show_unfinished_tag_cleanup_callout: show_unfinished_tag_cleanup_callout?.to_s } } diff --git a/app/views/groups/runners/_group_runners.html.haml b/app/views/groups/runners/_group_runners.html.haml index 944ef3435c1..f60cdc9f8da 100644 --- a/app/views/groups/runners/_group_runners.html.haml +++ b/app/views/groups/runners/_group_runners.html.haml @@ -17,5 +17,7 @@ = render partial: 'ci/runner/how_to_setup_runner', locals: { registration_token: @group.runners_token, type: 'group', - reset_token_url: reset_registration_token_group_settings_ci_cd_path } + reset_token_url: reset_registration_token_group_settings_ci_cd_path, + project_path: '', + group_path: @group.path } %br diff --git a/app/views/projects/registry/repositories/index.html.haml b/app/views/projects/registry/repositories/index.html.haml index 97bc366544f..93e94928110 100644 --- a/app/views/projects/registry/repositories/index.html.haml +++ b/app/views/projects/registry/repositories/index.html.haml @@ -19,4 +19,7 @@ "project_path": @project.full_path, "gid_prefix": container_repository_gid_prefix, "is_admin": current_user&.admin.to_s, - character_error: @character_error.to_s } } + character_error: @character_error.to_s, + user_callouts_path: user_callouts_path, + user_callout_id: UserCalloutsHelper::UNFINISHED_TAG_CLEANUP_CALLOUT, + show_unfinished_tag_cleanup_callout: show_unfinished_tag_cleanup_callout?.to_s, } } diff --git a/app/views/projects/runners/_specific_runners.html.haml b/app/views/projects/runners/_specific_runners.html.haml index 3e325b80efd..88895634990 100644 --- a/app/views/projects/runners/_specific_runners.html.haml +++ b/app/views/projects/runners/_specific_runners.html.haml @@ -9,9 +9,11 @@ clusters_path: project_clusters_path(@project) } %hr = render partial: 'ci/runner/how_to_setup_runner', - locals: { registration_token: @project.runners_token, - type: 'specific', - reset_token_url: reset_registration_token_namespace_project_settings_ci_cd_path } + locals: { registration_token: @project.runners_token, + type: 'specific', + reset_token_url: reset_registration_token_namespace_project_settings_ci_cd_path, + project_path: @project.path_with_namespace, + group_path: '' } %hr diff --git a/app/workers/projects/git_garbage_collect_worker.rb b/app/workers/projects/git_garbage_collect_worker.rb index 7c7c7f27a6b..dc22c114115 100644 --- a/app/workers/projects/git_garbage_collect_worker.rb +++ b/app/workers/projects/git_garbage_collect_worker.rb @@ -7,6 +7,17 @@ module Projects private + # At the moment this was added, the default key was like this. + # With the addition of wikis to housekeeping, this will bring a + # problem because the wiki for project 1 will have the same + # lease key as project 1. + # + # In the `GitGarbageCollectMethods` we namespaced the resource, + # giving us the option to have different resources. Nevertheless, + # we kept this override in order for backward compatibility and avoid + # starting all projects from scratch. + # + # See https://gitlab.com/gitlab-org/gitlab/-/issues/299903 override :default_lease_key def default_lease_key(task, resource) "git_gc:#{task}:#{resource.id}" |