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-12-14 15:13:33 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-12-14 15:13:33 +0300
commit79a7da2537e94c34aba92ad4b9a5dc1da431b2c4 (patch)
tree83b6a53a15a9266ca2e2aca061dd3f33d5282b1f /app
parenta58667ab4b4fc4b0d1e47e95d91c27ccadd0acd3 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/import_entities/import_groups/components/import_table.vue3
-rw-r--r--app/assets/javascripts/import_entities/import_groups/components/import_target_cell.vue126
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js16
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/fragments/bulk_import_source_group_progress.fragment.graphql1
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/mutations/import_groups.mutation.graphql1
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/services/local_storage_cache.js9
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/typedefs.graphql1
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/constants.js6
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/index.js30
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/pages/index.vue5
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/pages/list.js24
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/pages/list.vue (renamed from app/assets/javascripts/packages_and_registries/package_registry/components/list/app.vue)26
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/router.js21
-rw-r--r--app/assets/javascripts/pages/groups/packages/index/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/packages/packages/index/index.js4
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestions.vue2
-rw-r--r--app/assets/stylesheets/framework/markdown_area.scss4
-rw-r--r--app/controllers/import/bulk_imports_controller.rb8
-rw-r--r--app/controllers/projects/blob_controller.rb2
-rw-r--r--app/graphql/resolvers/ci/jobs_resolver.rb2
-rw-r--r--app/graphql/resolvers/project_pipelines_resolver.rb2
-rw-r--r--app/helpers/diff_helper.rb2
-rw-r--r--app/helpers/packages_helper.rb11
-rw-r--r--app/models/ci/pipeline.rb1
-rw-r--r--app/models/concerns/token_authenticatable_strategies/encryption_helper.rb2
-rw-r--r--app/models/hooks/project_hook.rb11
-rw-r--r--app/models/hooks/web_hook.rb32
-rw-r--r--app/models/namespaces/traversal/linear.rb2
-rw-r--r--app/models/serverless/domain.rb2
-rw-r--r--app/models/wiki_page.rb2
-rw-r--r--app/services/bulk_imports/create_service.rb2
-rw-r--r--app/services/cohorts_service.rb2
-rw-r--r--app/uploaders/lfs_object_uploader.rb2
-rw-r--r--app/views/groups/packages/index.html.haml6
-rw-r--r--app/views/projects/packages/packages/index.html.haml6
35 files changed, 235 insertions, 145 deletions
diff --git a/app/assets/javascripts/import_entities/import_groups/components/import_table.vue b/app/assets/javascripts/import_entities/import_groups/components/import_table.vue
index 298771a4d12..f2837a7bb44 100644
--- a/app/assets/javascripts/import_entities/import_groups/components/import_table.vue
+++ b/app/assets/javascripts/import_entities/import_groups/components/import_table.vue
@@ -314,9 +314,8 @@ export default {
variables: { importRequests },
});
} catch (error) {
- const message = error?.networkError?.response?.data?.error ?? i18n.ERROR_IMPORT;
createFlash({
- message,
+ message: i18n.ERROR_IMPORT,
captureError: true,
error,
});
diff --git a/app/assets/javascripts/import_entities/import_groups/components/import_target_cell.vue b/app/assets/javascripts/import_entities/import_groups/components/import_target_cell.vue
index ca9ae9447d0..344a6e45370 100644
--- a/app/assets/javascripts/import_entities/import_groups/components/import_target_cell.vue
+++ b/app/assets/javascripts/import_entities/import_groups/components/import_target_cell.vue
@@ -32,72 +32,84 @@ export default {
fullPath() {
return this.group.importTarget.targetNamespace.fullPath || s__('BulkImport|No parent');
},
- invalidNameValidationMessage() {
- return getInvalidNameValidationMessage(this.group.importTarget);
+ validationMessage() {
+ return (
+ this.group.progress?.message || getInvalidNameValidationMessage(this.group.importTarget)
+ );
+ },
+ validNameState() {
+ // bootstrap-vue requires null for "indifferent" state, if we return true
+ // this will highlight field in green like "passed validation"
+ return this.group.flags.isInvalid && this.group.flags.isAvailableForImport ? false : null;
},
},
};
</script>
<template>
- <div class="gl-display-flex gl-align-items-stretch">
- <import-group-dropdown
- #default="{ namespaces }"
- :text="fullPath"
- :disabled="!group.flags.isAvailableForImport"
- :namespaces="availableNamespaces"
- toggle-class="gl-rounded-top-right-none! gl-rounded-bottom-right-none!"
- class="gl-h-7 gl-flex-grow-1"
- data-qa-selector="target_namespace_selector_dropdown"
- >
- <gl-dropdown-item @click="$emit('update-target-namespace', { fullPath: '', id: null })">{{
- s__('BulkImport|No parent')
- }}</gl-dropdown-item>
- <template v-if="namespaces.length">
- <gl-dropdown-divider />
- <gl-dropdown-section-header>
- {{ s__('BulkImport|Existing groups') }}
- </gl-dropdown-section-header>
- <gl-dropdown-item
- v-for="ns in namespaces"
- :key="ns.fullPath"
- data-qa-selector="target_group_dropdown_item"
- :data-qa-group-name="ns.fullPath"
- @click="$emit('update-target-namespace', ns)"
- >
- {{ ns.fullPath }}
- </gl-dropdown-item>
- </template>
- </import-group-dropdown>
- <div
- class="gl-h-7 gl-px-3 gl-display-flex gl-align-items-center gl-border-solid gl-border-0 gl-border-t-1 gl-border-b-1 gl-bg-gray-10"
- :class="{
- 'gl-text-gray-400 gl-border-gray-100': !group.flags.isAvailableForImport,
- 'gl-border-gray-200': group.flags.isAvailableForImport,
- }"
- >
- /
- </div>
- <div class="gl-flex-grow-1">
- <gl-form-input
- class="gl-rounded-top-left-none gl-rounded-bottom-left-none"
+ <div>
+ <div class="gl-display-flex gl-align-items-stretch">
+ <import-group-dropdown
+ #default="{ namespaces }"
+ :text="fullPath"
+ :disabled="!group.flags.isAvailableForImport"
+ :namespaces="availableNamespaces"
+ toggle-class="gl-rounded-top-right-none! gl-rounded-bottom-right-none!"
+ class="gl-h-7 gl-flex-grow-1"
+ data-qa-selector="target_namespace_selector_dropdown"
+ >
+ <gl-dropdown-item @click="$emit('update-target-namespace', { fullPath: '', id: null })">{{
+ s__('BulkImport|No parent')
+ }}</gl-dropdown-item>
+ <template v-if="namespaces.length">
+ <gl-dropdown-divider />
+ <gl-dropdown-section-header>
+ {{ s__('BulkImport|Existing groups') }}
+ </gl-dropdown-section-header>
+ <gl-dropdown-item
+ v-for="ns in namespaces"
+ :key="ns.fullPath"
+ data-qa-selector="target_group_dropdown_item"
+ :data-qa-group-name="ns.fullPath"
+ @click="$emit('update-target-namespace', ns)"
+ >
+ {{ ns.fullPath }}
+ </gl-dropdown-item>
+ </template>
+ </import-group-dropdown>
+ <div
+ class="gl-h-7 gl-px-3 gl-display-flex gl-align-items-center gl-border-solid gl-border-0 gl-border-t-1 gl-border-b-1 gl-bg-gray-10"
:class="{
- 'gl-inset-border-1-gray-200!': group.flags.isAvailableForImport,
- 'gl-inset-border-1-gray-100!': !group.flags.isAvailableForImport,
- 'is-invalid': group.flags.isInvalid && group.flags.isAvailableForImport,
+ 'gl-text-gray-400 gl-border-gray-100': !group.flags.isAvailableForImport,
+ 'gl-border-gray-200': group.flags.isAvailableForImport,
}"
- debounce="500"
- :disabled="!group.flags.isAvailableForImport"
- :value="group.importTarget.newName"
- :aria-label="__('New name')"
- @input="$emit('update-new-name', $event)"
- />
- <p
- v-if="group.flags.isAvailableForImport && group.flags.isInvalid"
- class="gl-text-red-500 gl-m-0 gl-mt-2"
>
- {{ invalidNameValidationMessage }}
- </p>
+ /
+ </div>
+ <div class="gl-flex-grow-1">
+ <gl-form-input
+ class="gl-rounded-top-left-none gl-rounded-bottom-left-none"
+ :class="{
+ 'gl-inset-border-1-gray-200!':
+ group.flags.isAvailableForImport && !group.flags.isInvalid,
+ 'gl-inset-border-1-gray-100!':
+ !group.flags.isAvailableForImport && !group.flags.isInvalid,
+ }"
+ debounce="500"
+ :disabled="!group.flags.isAvailableForImport"
+ :value="group.importTarget.newName"
+ :aria-label="__('New name')"
+ :state="validNameState"
+ @input="$emit('update-new-name', $event)"
+ />
+ </div>
+ </div>
+ <div
+ v-if="group.flags.isAvailableForImport && (group.flags.isInvalid || validationMessage)"
+ class="gl-text-red-500 gl-m-0 gl-mt-2"
+ role="alert"
+ >
+ {{ validationMessage }}
</div>
</div>
</template>
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js b/app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js
index bce6e7bcb1f..31352bbc8bb 100644
--- a/app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js
+++ b/app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js
@@ -142,9 +142,7 @@ export function createResolvers({ endpoints }) {
};
});
- const {
- data: { id: jobId },
- } = await axios.post(endpoints.createBulkImport, {
+ const { data: originalResponse } = await axios.post(endpoints.createBulkImport, {
bulk_import: importOperations.map((op) => ({
source_type: 'group_entity',
source_full_path: op.group.fullPath,
@@ -153,15 +151,21 @@ export function createResolvers({ endpoints }) {
})),
});
- return importOperations.map((op) => {
+ const responses = Array.isArray(originalResponse)
+ ? originalResponse
+ : [{ success: true, id: originalResponse.id }];
+
+ return importOperations.map((op, idx) => {
+ const response = responses[idx];
const lastImportTarget = {
targetNamespace: op.targetNamespace,
newName: op.newName,
};
const progress = {
- id: jobId,
- status: STATUSES.CREATED,
+ id: response.id || `local-${Date.now()}-${idx}`,
+ status: response.success ? STATUSES.CREATED : STATUSES.FAILED,
+ message: response.message || null,
};
localStorageCache.set(op.group.webUrl, { progress, lastImportTarget });
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/fragments/bulk_import_source_group_progress.fragment.graphql b/app/assets/javascripts/import_entities/import_groups/graphql/fragments/bulk_import_source_group_progress.fragment.graphql
index 2d60bf82d65..33c564f36a8 100644
--- a/app/assets/javascripts/import_entities/import_groups/graphql/fragments/bulk_import_source_group_progress.fragment.graphql
+++ b/app/assets/javascripts/import_entities/import_groups/graphql/fragments/bulk_import_source_group_progress.fragment.graphql
@@ -1,4 +1,5 @@
fragment BulkImportSourceGroupProgress on ClientBulkImportProgress {
id
status
+ message
}
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/mutations/import_groups.mutation.graphql b/app/assets/javascripts/import_entities/import_groups/graphql/mutations/import_groups.mutation.graphql
index 75215471d0f..39289887b75 100644
--- a/app/assets/javascripts/import_entities/import_groups/graphql/mutations/import_groups.mutation.graphql
+++ b/app/assets/javascripts/import_entities/import_groups/graphql/mutations/import_groups.mutation.graphql
@@ -9,6 +9,7 @@ mutation importGroups($importRequests: [ImportGroupInput!]!) {
progress {
id
status
+ message
}
}
}
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/services/local_storage_cache.js b/app/assets/javascripts/import_entities/import_groups/graphql/services/local_storage_cache.js
index 09bc7b33692..1aad22f0f3f 100644
--- a/app/assets/javascripts/import_entities/import_groups/graphql/services/local_storage_cache.js
+++ b/app/assets/javascripts/import_entities/import_groups/graphql/services/local_storage_cache.js
@@ -22,7 +22,14 @@ export class LocalStorageCache {
loadCacheFromStorage() {
try {
- return JSON.parse(this.storage.getItem(KEY)) ?? {};
+ const storage = JSON.parse(this.storage.getItem(KEY)) ?? {};
+ Object.values(storage).forEach((entry) => {
+ if (entry.progress && !('message' in entry.progress)) {
+ // eslint-disable-next-line no-param-reassign
+ entry.progress.message = '';
+ }
+ });
+ return storage;
} catch {
return {};
}
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/typedefs.graphql b/app/assets/javascripts/import_entities/import_groups/graphql/typedefs.graphql
index b8dd79a5000..1639ce16758 100644
--- a/app/assets/javascripts/import_entities/import_groups/graphql/typedefs.graphql
+++ b/app/assets/javascripts/import_entities/import_groups/graphql/typedefs.graphql
@@ -16,6 +16,7 @@ type ClientBulkImportSourceGroupConnection {
type ClientBulkImportProgress {
id: ID!
status: String!
+ message: String
}
type ClientBulkImportValidationError {
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/constants.js b/app/assets/javascripts/packages_and_registries/package_registry/constants.js
index d75c195be4c..ab6541e4264 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/constants.js
+++ b/app/assets/javascripts/packages_and_registries/package_registry/constants.js
@@ -1,4 +1,5 @@
import { s__, __ } from '~/locale';
+import { helpPagePath } from '~/helpers/help_page_helper';
export {
DELETE_PACKAGE_TRACKING_ACTION,
@@ -136,3 +137,8 @@ export const PACKAGE_TYPES = [
s__('PackageRegistry|Debian'),
s__('PackageRegistry|Helm'),
];
+
+// links
+
+export const EMPTY_LIST_HELP_URL = helpPagePath('user/packages/package_registry/index');
+export const PACKAGE_HELP_URL = helpPagePath('user/packages/index');
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/index.js b/app/assets/javascripts/packages_and_registries/package_registry/index.js
new file mode 100644
index 00000000000..7ec931ff9a0
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/package_registry/index.js
@@ -0,0 +1,30 @@
+import Vue from 'vue';
+import Translate from '~/vue_shared/translate';
+import { apolloProvider } from '~/packages_and_registries/package_registry/graphql/index';
+import PackageRegistry from '~/packages_and_registries/package_registry/pages/index.vue';
+import createRouter from './router';
+
+Vue.use(Translate);
+
+export default () => {
+ const el = document.getElementById('js-vue-packages-list');
+ const { endpoint, resourceId, fullPath, pageType, emptyListIllustration } = el.dataset;
+ const router = createRouter(endpoint);
+
+ const isGroupPage = pageType === 'groups';
+
+ return new Vue({
+ el,
+ router,
+ apolloProvider,
+ provide: {
+ resourceId,
+ fullPath,
+ emptyListIllustration,
+ isGroupPage,
+ },
+ render(createElement) {
+ return createElement(PackageRegistry);
+ },
+ });
+};
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/pages/index.vue b/app/assets/javascripts/packages_and_registries/package_registry/pages/index.vue
new file mode 100644
index 00000000000..a14d0c32cbe
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/package_registry/pages/index.vue
@@ -0,0 +1,5 @@
+<template>
+ <div>
+ <router-view />
+ </div>
+</template>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/pages/list.js b/app/assets/javascripts/packages_and_registries/package_registry/pages/list.js
deleted file mode 100644
index d797a0a5327..00000000000
--- a/app/assets/javascripts/packages_and_registries/package_registry/pages/list.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import Vue from 'vue';
-import Translate from '~/vue_shared/translate';
-import { apolloProvider } from '~/packages_and_registries/package_registry/graphql/index';
-import PackagesListApp from '../components/list/app.vue';
-
-Vue.use(Translate);
-
-export default () => {
- const el = document.getElementById('js-vue-packages-list');
-
- const isGroupPage = el.dataset.pageType === 'groups';
-
- return new Vue({
- el,
- apolloProvider,
- provide: {
- ...el.dataset,
- isGroupPage,
- },
- render(createElement) {
- return createElement(PackagesListApp);
- },
- });
-};
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/list/app.vue b/app/assets/javascripts/packages_and_registries/package_registry/pages/list.vue
index d65711d061d..38df701157a 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/list/app.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/pages/list.vue
@@ -9,13 +9,15 @@ import {
GROUP_RESOURCE_TYPE,
GRAPHQL_PAGE_SIZE,
DELETE_PACKAGE_SUCCESS_MESSAGE,
+ EMPTY_LIST_HELP_URL,
+ PACKAGE_HELP_URL,
} from '~/packages_and_registries/package_registry/constants';
import getPackagesQuery from '~/packages_and_registries/package_registry/graphql/queries/get_packages.query.graphql';
import DeletePackage from '~/packages_and_registries/package_registry/components/functional/delete_package.vue';
-import PackageTitle from './package_title.vue';
-import PackageSearch from './package_search.vue';
-import PackageList from './packages_list.vue';
+import PackageTitle from '~/packages_and_registries/package_registry/components/list/package_title.vue';
+import PackageSearch from '~/packages_and_registries/package_registry/components/list/package_search.vue';
+import PackageList from '~/packages_and_registries/package_registry/components/list/packages_list.vue';
export default {
components: {
@@ -27,13 +29,7 @@ export default {
PackageSearch,
DeletePackage,
},
- inject: [
- 'packageHelpUrl',
- 'emptyListIllustration',
- 'emptyListHelpUrl',
- 'isGroupPage',
- 'fullPath',
- ],
+ inject: ['emptyListIllustration', 'isGroupPage', 'fullPath'],
data() {
return {
packages: {},
@@ -156,12 +152,16 @@ export default {
'PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab.',
),
},
+ links: {
+ EMPTY_LIST_HELP_URL,
+ PACKAGE_HELP_URL,
+ },
};
</script>
<template>
<div>
- <package-title :help-url="packageHelpUrl" :count="packagesCount" />
+ <package-title :help-url="$options.links.PACKAGE_HELP_URL" :count="packagesCount" />
<package-search @update="handleSearchUpdate" />
<delete-package
@@ -185,7 +185,9 @@ export default {
<gl-sprintf v-if="hasFilters" :message="$options.i18n.widenFilters" />
<gl-sprintf v-else :message="$options.i18n.noResultsText">
<template #noPackagesLink="{ content }">
- <gl-link :href="emptyListHelpUrl" target="_blank">{{ content }}</gl-link>
+ <gl-link :href="$options.links.EMPTY_LIST_HELP_URL" target="_blank">{{
+ content
+ }}</gl-link>
</template>
</gl-sprintf>
</template>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/router.js b/app/assets/javascripts/packages_and_registries/package_registry/router.js
new file mode 100644
index 00000000000..ea5b740e879
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/package_registry/router.js
@@ -0,0 +1,21 @@
+import Vue from 'vue';
+import VueRouter from 'vue-router';
+import List from '~/packages_and_registries/package_registry/pages/list.vue';
+
+Vue.use(VueRouter);
+
+export default function createRouter(base) {
+ const router = new VueRouter({
+ base,
+ mode: 'history',
+ routes: [
+ {
+ name: 'list',
+ path: '/',
+ component: List,
+ },
+ ],
+ });
+
+ return router;
+}
diff --git a/app/assets/javascripts/pages/groups/packages/index/index.js b/app/assets/javascripts/pages/groups/packages/index/index.js
index f9eecff4ac4..174973a9fad 100644
--- a/app/assets/javascripts/pages/groups/packages/index/index.js
+++ b/app/assets/javascripts/pages/groups/packages/index/index.js
@@ -1,3 +1,3 @@
-import packageList from '~/packages_and_registries/package_registry/pages/list';
+import packageApp from '~/packages_and_registries/package_registry/index';
-packageList();
+packageApp();
diff --git a/app/assets/javascripts/pages/projects/packages/packages/index/index.js b/app/assets/javascripts/pages/projects/packages/packages/index/index.js
index f9eecff4ac4..174973a9fad 100644
--- a/app/assets/javascripts/pages/projects/packages/packages/index/index.js
+++ b/app/assets/javascripts/pages/projects/packages/packages/index/index.js
@@ -1,3 +1,3 @@
-import packageList from '~/packages_and_registries/package_registry/pages/list';
+import packageApp from '~/packages_and_registries/package_registry/index';
-packageList();
+packageApp();
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
index e36cfb3b275..2f6776f835e 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
@@ -165,6 +165,6 @@ export default {
<template>
<div>
<div class="flash-container js-suggestions-flash"></div>
- <div v-show="isRendered" ref="container" v-safe-html="noteHtml" class="md"></div>
+ <div v-show="isRendered" ref="container" v-safe-html="noteHtml" class="md suggestions"></div>
</div>
</template>
diff --git a/app/assets/stylesheets/framework/markdown_area.scss b/app/assets/stylesheets/framework/markdown_area.scss
index 9b04b9a2612..c6e52c13e83 100644
--- a/app/assets/stylesheets/framework/markdown_area.scss
+++ b/app/assets/stylesheets/framework/markdown_area.scss
@@ -139,6 +139,10 @@
font-family: $monospace-font !important;
}
+.suggestions.md > .markdown-code-block {
+ @include gl-static;
+}
+
.md-suggestion-header {
height: $suggestion-header-height;
display: flex;
diff --git a/app/controllers/import/bulk_imports_controller.rb b/app/controllers/import/bulk_imports_controller.rb
index bec26cb547d..f26c06b7e37 100644
--- a/app/controllers/import/bulk_imports_controller.rb
+++ b/app/controllers/import/bulk_imports_controller.rb
@@ -40,13 +40,9 @@ class Import::BulkImportsController < ApplicationController
end
def create
- response = ::BulkImports::CreateService.new(current_user, create_params, credentials).execute
+ responses = create_params.map { |entry| ::BulkImports::CreateService.new(current_user, entry, credentials).execute }
- if response.success?
- render json: response.payload.to_json(only: [:id])
- else
- render json: { error: response.message }, status: response.http_status
- end
+ render json: responses.map { |response| { success: response.success?, id: response.payload[:id], message: response.message } }
end
def realtime_changes
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 2b42dcb66ad..b30ef7506aa 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -99,7 +99,7 @@ class Projects::BlobController < Projects::ApplicationController
@content = params[:content]
@blob.load_all_data!
diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3', include_diff_info: true)
- diff_lines = diffy.diff.scan(/.*\n/)[2..-1]
+ diff_lines = diffy.diff.scan(/.*\n/)[2..]
diff_lines = Gitlab::Diff::Parser.new.parse(diff_lines).to_a
@diff_lines = Gitlab::Diff::Highlight.new(diff_lines, repository: @repository).highlight
diff --git a/app/graphql/resolvers/ci/jobs_resolver.rb b/app/graphql/resolvers/ci/jobs_resolver.rb
index 5ae9e721cc8..df138a15538 100644
--- a/app/graphql/resolvers/ci/jobs_resolver.rb
+++ b/app/graphql/resolvers/ci/jobs_resolver.rb
@@ -29,7 +29,7 @@ module Resolvers
job_types: security_report_types
).execute
else
- pipeline.statuses
+ pipeline.statuses_order_id_desc
end
end
end
diff --git a/app/graphql/resolvers/project_pipelines_resolver.rb b/app/graphql/resolvers/project_pipelines_resolver.rb
index 23423b9274a..47a8b028d4d 100644
--- a/app/graphql/resolvers/project_pipelines_resolver.rb
+++ b/app/graphql/resolvers/project_pipelines_resolver.rb
@@ -18,7 +18,7 @@ module Resolvers
def preloads
{
- jobs: { statuses: [:needs] },
+ jobs: { statuses_order_id_desc: [:needs] },
upstream: [:triggered_by_pipeline],
downstream: [:triggered_pipelines]
}
diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb
index ca5fe38576e..2b5f726dad1 100644
--- a/app/helpers/diff_helper.rb
+++ b/app/helpers/diff_helper.rb
@@ -283,7 +283,7 @@ module DiffHelper
return path unless path.size > max && max > 3
- "...#{path[-(max - 3)..-1]}"
+ "...#{path[-(max - 3)..]}"
end
def code_navigation_path(diffs)
diff --git a/app/helpers/packages_helper.rb b/app/helpers/packages_helper.rb
index c69d9eb1326..66f80e7eeb8 100644
--- a/app/helpers/packages_helper.rb
+++ b/app/helpers/packages_helper.rb
@@ -38,17 +38,6 @@ module PackagesHelper
"#{Gitlab.config.gitlab.host}/#{group_id}"
end
- def packages_list_data(type, resource)
- {
- resource_id: resource.id,
- full_path: resource.full_path,
- page_type: type,
- empty_list_help_url: help_page_path('user/packages/package_registry/index'),
- empty_list_illustration: image_path('illustrations/no-packages.svg'),
- package_help_url: help_page_path('user/packages/index')
- }
- end
-
def track_package_event(event_name, scope, **args)
::Packages::CreateEventService.new(nil, current_user, event_name: event_name, scope: scope).execute
category = args.delete(:category) || self.class.name
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 2a746784a01..d0db3e134ed 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -63,6 +63,7 @@ module Ci
has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline
has_many :latest_statuses_ordered_by_stage, -> { latest.order(:stage_idx, :stage) }, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline
has_many :latest_statuses, -> { latest }, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline
+ has_many :statuses_order_id_desc, -> { order_id_desc }, class_name: 'CommitStatus', foreign_key: :commit_id
has_many :processables, class_name: 'Ci::Processable', foreign_key: :commit_id, inverse_of: :pipeline
has_many :bridges, class_name: 'Ci::Bridge', foreign_key: :commit_id, inverse_of: :pipeline
has_many :builds, foreign_key: :commit_id, inverse_of: :pipeline
diff --git a/app/models/concerns/token_authenticatable_strategies/encryption_helper.rb b/app/models/concerns/token_authenticatable_strategies/encryption_helper.rb
index 3be82ed72d3..447521ad8c1 100644
--- a/app/models/concerns/token_authenticatable_strategies/encryption_helper.rb
+++ b/app/models/concerns/token_authenticatable_strategies/encryption_helper.rb
@@ -11,7 +11,7 @@ module TokenAuthenticatableStrategies
# The pattern of the token is "#{DYNAMIC_NONCE_IDENTIFIER}#{token}#{iv_of_12_characters}"
if token.start_with?(DYNAMIC_NONCE_IDENTIFIER) && token.size > NONCE_SIZE + DYNAMIC_NONCE_IDENTIFIER.size
token_to_decrypt = token[1...-NONCE_SIZE]
- iv = token[-NONCE_SIZE..-1]
+ iv = token[-NONCE_SIZE..]
Gitlab::CryptoHelper.aes256_gcm_decrypt(token_to_decrypt, nonce: iv)
else
diff --git a/app/models/hooks/project_hook.rb b/app/models/hooks/project_hook.rb
index d1584a62bfb..16b95d2a2b9 100644
--- a/app/models/hooks/project_hook.rb
+++ b/app/models/hooks/project_hook.rb
@@ -31,10 +31,6 @@ class ProjectHook < WebHook
_('Webhooks')
end
- def web_hooks_disable_failed?
- Feature.enabled?(:web_hooks_disable_failed, project)
- end
-
override :rate_limit
def rate_limit
project.actual_limits.limit_for(:web_hook_calls)
@@ -44,6 +40,13 @@ class ProjectHook < WebHook
def application_context
super.merge(project: project)
end
+
+ private
+
+ override :web_hooks_disable_failed?
+ def web_hooks_disable_failed?
+ Feature.enabled?(:web_hooks_disable_failed, project)
+ end
end
ProjectHook.prepend_mod_with('ProjectHook')
diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb
index cb5c1ac48cd..e8a55abfc8f 100644
--- a/app/models/hooks/web_hook.rb
+++ b/app/models/hooks/web_hook.rb
@@ -34,9 +34,19 @@ class WebHook < ApplicationRecord
end
def executable?
- return true unless web_hooks_disable_failed?
+ !temporarily_disabled? && !permanently_disabled?
+ end
+
+ def temporarily_disabled?
+ return false unless web_hooks_disable_failed?
+
+ disabled_until.present? && disabled_until >= Time.current
+ end
+
+ def permanently_disabled?
+ return false unless web_hooks_disable_failed?
- recent_failures <= FAILURE_THRESHOLD && (disabled_until.nil? || disabled_until < Time.current)
+ recent_failures > FAILURE_THRESHOLD
end
# rubocop: disable CodeReuse/ServiceClass
@@ -69,6 +79,8 @@ class WebHook < ApplicationRecord
end
def disable!
+ return if permanently_disabled?
+
update_attribute(:recent_failures, FAILURE_THRESHOLD + 1)
end
@@ -80,7 +92,7 @@ class WebHook < ApplicationRecord
end
def backoff!
- return if backoff_count >= MAX_FAILURES && disabled_until && disabled_until > Time.current
+ return if permanently_disabled? || (backoff_count >= MAX_FAILURES && temporarily_disabled?)
assign_attributes(disabled_until: next_backoff.from_now, backoff_count: backoff_count.succ.clamp(0, MAX_FAILURES))
save(validate: false)
@@ -93,7 +105,19 @@ class WebHook < ApplicationRecord
save(validate: false)
end
- # Overridden in ProjectHook and GroupHook, other webhooks are not rate-limited.
+ # @return [Boolean] Whether or not the WebHook is currently throttled.
+ def rate_limited?
+ return false unless rate_limit
+
+ Gitlab::ApplicationRateLimiter.peek(
+ :web_hook_calls,
+ scope: [self],
+ threshold: rate_limit
+ )
+ end
+
+ # Threshold for the rate-limit.
+ # Overridden in ProjectHook and GroupHook, other WebHooks are not rate-limited.
def rate_limit
nil
end
diff --git a/app/models/namespaces/traversal/linear.rb b/app/models/namespaces/traversal/linear.rb
index 36b45dde6b4..5a5f2a5d063 100644
--- a/app/models/namespaces/traversal/linear.rb
+++ b/app/models/namespaces/traversal/linear.rb
@@ -204,7 +204,7 @@ module Namespaces
end
if bottom
- skope = skope.where(id: bottom.traversal_ids[0..-1])
+ skope = skope.where(id: bottom.traversal_ids)
end
# The original `with_depth` attribute in ObjectHierarchy increments as you
diff --git a/app/models/serverless/domain.rb b/app/models/serverless/domain.rb
index 2fef3b66b08..164f93afa9a 100644
--- a/app/models/serverless/domain.rb
+++ b/app/models/serverless/domain.rb
@@ -37,7 +37,7 @@ module Serverless
'a1',
serverless_domain_cluster.uuid[2..-3],
'f2',
- serverless_domain_cluster.uuid[-2..-1]
+ serverless_domain_cluster.uuid[-2..]
].join
end
end
diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb
index 25438581f2f..3dbbbcdfe23 100644
--- a/app/models/wiki_page.rb
+++ b/app/models/wiki_page.rb
@@ -338,7 +338,7 @@ class WikiPage
current_dirname = File.dirname(title)
if persisted?
- return title[1..-1] if current_dirname == '/'
+ return title[1..] if current_dirname == '/'
return File.join([directory.presence, title].compact) if current_dirname == '.'
end
diff --git a/app/services/bulk_imports/create_service.rb b/app/services/bulk_imports/create_service.rb
index c1becbb5609..cbf2b34b33c 100644
--- a/app/services/bulk_imports/create_service.rb
+++ b/app/services/bulk_imports/create_service.rb
@@ -59,7 +59,7 @@ module BulkImports
)
bulk_import.create_configuration!(credentials.slice(:url, :access_token))
- params.each do |entity|
+ Array.wrap(params).each do |entity|
BulkImports::Entity.create!(
bulk_import: bulk_import,
source_type: entity[:source_type],
diff --git a/app/services/cohorts_service.rb b/app/services/cohorts_service.rb
index 7bc3b267a12..1b1598b301c 100644
--- a/app/services/cohorts_service.rb
+++ b/app/services/cohorts_service.rb
@@ -38,7 +38,7 @@ class CohortsService
{
registration_month: registration_month,
- activity_months: activity_months[1..-1],
+ activity_months: activity_months[1..],
total: activity_months.first[:total],
inactive: inactive
}
diff --git a/app/uploaders/lfs_object_uploader.rb b/app/uploaders/lfs_object_uploader.rb
index 0a966f3d44f..027857500f4 100644
--- a/app/uploaders/lfs_object_uploader.rb
+++ b/app/uploaders/lfs_object_uploader.rb
@@ -9,7 +9,7 @@ class LfsObjectUploader < GitlabUploader
alias_method :upload, :model
def filename
- model.oid[4..-1]
+ model.oid[4..]
end
def store_dir
diff --git a/app/views/groups/packages/index.html.haml b/app/views/groups/packages/index.html.haml
index 7910217c939..d56a806f082 100644
--- a/app/views/groups/packages/index.html.haml
+++ b/app/views/groups/packages/index.html.haml
@@ -3,4 +3,8 @@
.row
.col-12
- #js-vue-packages-list{ data: packages_list_data('groups', @group) }
+ #js-vue-packages-list{ data: { resource_id: @group.id,
+ full_path: @group.full_path,
+ endpoint: group_packages_path(@group),
+ page_type: 'groups',
+ empty_list_illustration: image_path('illustrations/no-packages.svg'), } }
diff --git a/app/views/projects/packages/packages/index.html.haml b/app/views/projects/packages/packages/index.html.haml
index 0d5350ab62b..c67b06218e2 100644
--- a/app/views/projects/packages/packages/index.html.haml
+++ b/app/views/projects/packages/packages/index.html.haml
@@ -3,4 +3,8 @@
.row
.col-12
- #js-vue-packages-list{ data: packages_list_data('projects', @project) }
+ #js-vue-packages-list{ data: { resource_id: @project.id,
+ full_path: @project.full_path,
+ endpoint: project_packages_path(@project),
+ page_type: 'projects',
+ empty_list_illustration: image_path('illustrations/no-packages.svg'), } }