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>2020-12-15 21:10:06 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-12-15 21:10:06 +0300
commitb07852468f800d751ddecc9e327119d7295f538e (patch)
treed1169f95ea3725d609c796a1ca87d5766646852c /app
parent0ff373dc416216d02760c7c162ee23382eb1f4a3 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js29
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/services/status_poller.js68
-rw-r--r--app/assets/javascripts/lib/utils/keycodes.js1
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.graphql4
-rw-r--r--app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue7
-rw-r--r--app/assets/javascripts/pipelines/graphql/queries/pipeline_stages.fragment.graphql12
-rw-r--r--app/assets/javascripts/pipelines/graphql/queries/pipeline_stages_connection.fragment.graphql20
-rw-r--r--app/assets/javascripts/vue_shared/components/gfm_autocomplete/gfm_autocomplete.vue6
-rw-r--r--app/models/ci/build_dependencies.rb2
-rw-r--r--app/models/user.rb4
-rw-r--r--app/services/jira/requests/base.rb7
-rw-r--r--app/views/import/bulk_imports/status.html.haml4
-rw-r--r--app/views/profiles/accounts/show.html.haml5
13 files changed, 149 insertions, 20 deletions
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 23f4190c2d0..4fcaa1b55fc 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
@@ -1,8 +1,11 @@
import axios from '~/lib/utils/axios_utils';
import createDefaultClient from '~/lib/graphql';
+import { s__ } from '~/locale';
+import createFlash from '~/flash';
import { STATUSES } from '../../constants';
import availableNamespacesQuery from './queries/available_namespaces.query.graphql';
import { SourceGroupsManager } from './services/source_groups_manager';
+import { StatusPoller } from './services/status_poller';
export const clientTypenames = {
BulkImportSourceGroup: 'ClientBulkImportSourceGroup',
@@ -10,6 +13,8 @@ export const clientTypenames = {
};
export function createResolvers({ endpoints }) {
+ let statusPoller;
+
return {
Query: {
async bulkImportSourceGroups(_, __, { client }) {
@@ -57,6 +62,30 @@ export function createResolvers({ endpoints }) {
const groupManager = new SourceGroupsManager({ client });
const group = groupManager.findById(sourceGroupId);
groupManager.setImportStatus(group, STATUSES.SCHEDULING);
+ try {
+ await axios.post(endpoints.createBulkImport, {
+ bulk_import: [
+ {
+ source_type: 'group_entity',
+ source_full_path: group.full_path,
+ destination_namespace: group.import_target.target_namespace,
+ destination_name: group.import_target.new_name,
+ },
+ ],
+ });
+ groupManager.setImportStatus(group, STATUSES.STARTED);
+ if (!statusPoller) {
+ statusPoller = new StatusPoller({ client, interval: 3000 });
+ statusPoller.startPolling();
+ }
+ } catch (e) {
+ createFlash({
+ message: s__('BulkImport|Importing the group failed'),
+ });
+
+ groupManager.setImportStatus(group, STATUSES.NONE);
+ throw e;
+ }
},
},
};
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/services/status_poller.js b/app/assets/javascripts/import_entities/import_groups/graphql/services/status_poller.js
new file mode 100644
index 00000000000..5d2922b0ba8
--- /dev/null
+++ b/app/assets/javascripts/import_entities/import_groups/graphql/services/status_poller.js
@@ -0,0 +1,68 @@
+import gql from 'graphql-tag';
+import createFlash from '~/flash';
+import { s__ } from '~/locale';
+import bulkImportSourceGroupsQuery from '../queries/bulk_import_source_groups.query.graphql';
+import { STATUSES } from '../../../constants';
+import { SourceGroupsManager } from './source_groups_manager';
+
+const groupId = i => `group${i}`;
+
+function generateGroupsQuery(groups) {
+ return gql`{
+ ${groups
+ .map(
+ (g, idx) =>
+ `${groupId(idx)}: group(fullPath: "${g.import_target.target_namespace}/${
+ g.import_target.new_name
+ }") { id }`,
+ )
+ .join('\n')}
+ }`;
+}
+
+export class StatusPoller {
+ constructor({ client, interval }) {
+ this.client = client;
+ this.interval = interval;
+ this.timeoutId = null;
+ this.groupManager = new SourceGroupsManager({ client });
+ }
+
+ startPolling() {
+ if (this.timeoutId) {
+ return;
+ }
+
+ this.checkPendingImports();
+ }
+
+ stopPolling() {
+ clearTimeout(this.timeoutId);
+ this.timeoutId = null;
+ }
+
+ async checkPendingImports() {
+ try {
+ const { bulkImportSourceGroups } = this.client.readQuery({
+ query: bulkImportSourceGroupsQuery,
+ });
+ const groupsInProgress = bulkImportSourceGroups.filter(g => g.status === STATUSES.STARTED);
+ if (groupsInProgress.length) {
+ const { data: results } = await this.client.query({
+ query: generateGroupsQuery(groupsInProgress),
+ fetchPolicy: 'no-cache',
+ });
+ const completedGroups = groupsInProgress.filter((_, idx) => Boolean(results[groupId(idx)]));
+ completedGroups.forEach(group => {
+ this.groupManager.setImportStatus(group, STATUSES.FINISHED);
+ });
+ }
+ } catch (e) {
+ createFlash({
+ message: s__('BulkImport|Update of import statuses with realtime changes failed'),
+ });
+ } finally {
+ this.timeoutId = setTimeout(() => this.checkPendingImports(), this.interval);
+ }
+ }
+}
diff --git a/app/assets/javascripts/lib/utils/keycodes.js b/app/assets/javascripts/lib/utils/keycodes.js
index 618266f7a09..6f5cd7460f8 100644
--- a/app/assets/javascripts/lib/utils/keycodes.js
+++ b/app/assets/javascripts/lib/utils/keycodes.js
@@ -2,6 +2,7 @@
// See: https://gitlab.com/gitlab-org/gitlab/-/issues/216102
export const BACKSPACE_KEY_CODE = 8;
+export const TAB_KEY_CODE = 9;
export const ENTER_KEY_CODE = 13;
export const ESC_KEY_CODE = 27;
export const UP_KEY_CODE = 38;
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.graphql
index 149cb256ced..d65d9892260 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.graphql
@@ -1,11 +1,11 @@
-#import "~/pipelines/graphql/queries/pipeline_stages.fragment.graphql"
+#import "~/pipelines/graphql/queries/pipeline_stages_connection.fragment.graphql"
query getCiConfigData($content: String!) {
ciConfig(content: $content) {
errors
status
stages {
- ...PipelineStagesData
+ ...PipelineStagesConnection
}
}
}
diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
index b1c52ffa920..8a57c9b1970 100644
--- a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
+++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
@@ -10,6 +10,7 @@ import TextEditor from './components/text_editor.vue';
import commitCiFileMutation from './graphql/mutations/commit_ci_file.mutation.graphql';
import getBlobContent from './graphql/queries/blob_content.graphql';
import getCiConfigData from './graphql/queries/ci_config.graphql';
+import { unwrapStagesWithNeeds } from '~/pipelines/components/unwrapping_utils';
const MR_SOURCE_BRANCH = 'merge_request[source_branch]';
const MR_TARGET_BRANCH = 'merge_request[target_branch]';
@@ -99,7 +100,11 @@ export default {
};
},
update(data) {
- return data?.ciConfig ?? {};
+ const { ciConfigData } = data || {};
+ const stageNodes = ciConfigData?.stages?.nodes || [];
+ const stages = unwrapStagesWithNeeds(stageNodes);
+
+ return { ...ciConfigData, stages };
},
error() {
this.reportFailure(LOAD_FAILURE_UNKNOWN);
diff --git a/app/assets/javascripts/pipelines/graphql/queries/pipeline_stages.fragment.graphql b/app/assets/javascripts/pipelines/graphql/queries/pipeline_stages.fragment.graphql
deleted file mode 100644
index 0aef2fdfd7f..00000000000
--- a/app/assets/javascripts/pipelines/graphql/queries/pipeline_stages.fragment.graphql
+++ /dev/null
@@ -1,12 +0,0 @@
-fragment PipelineStagesData on CiConfigStage {
- name
- groups {
- name
- jobs {
- name
- needs {
- name
- }
- }
- }
-}
diff --git a/app/assets/javascripts/pipelines/graphql/queries/pipeline_stages_connection.fragment.graphql b/app/assets/javascripts/pipelines/graphql/queries/pipeline_stages_connection.fragment.graphql
new file mode 100644
index 00000000000..1da4fa0a72b
--- /dev/null
+++ b/app/assets/javascripts/pipelines/graphql/queries/pipeline_stages_connection.fragment.graphql
@@ -0,0 +1,20 @@
+fragment PipelineStagesConnection on CiConfigStageConnection {
+ nodes {
+ name
+ groups {
+ nodes {
+ name
+ jobs {
+ nodes {
+ name
+ needs {
+ nodes {
+ name
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/vue_shared/components/gfm_autocomplete/gfm_autocomplete.vue b/app/assets/javascripts/vue_shared/components/gfm_autocomplete/gfm_autocomplete.vue
index fb61c13983f..1ad0ca36bf8 100644
--- a/app/assets/javascripts/vue_shared/components/gfm_autocomplete/gfm_autocomplete.vue
+++ b/app/assets/javascripts/vue_shared/components/gfm_autocomplete/gfm_autocomplete.vue
@@ -1,5 +1,5 @@
<script>
-import Tribute from 'tributejs';
+import Tribute from '@gitlab/tributejs';
import {
GfmAutocompleteType,
tributeConfig,
@@ -29,6 +29,10 @@ export default {
config() {
return this.autocompleteTypes.map(type => ({
...tributeConfig[type].config,
+ loadingItemTemplate: `<span class="gl-spinner gl-vertical-align-text-bottom gl-ml-3 gl-mr-2"></span>${__(
+ 'Loading',
+ )}`,
+ requireLeadingSpace: true,
values: this.getValues(type),
}));
},
diff --git a/app/models/ci/build_dependencies.rb b/app/models/ci/build_dependencies.rb
index 2c6a9a63bdb..a6abeb517c1 100644
--- a/app/models/ci/build_dependencies.rb
+++ b/app/models/ci/build_dependencies.rb
@@ -143,7 +143,7 @@ module Ci
def specified_cross_pipeline_dependencies
strong_memoize(:specified_cross_pipeline_dependencies) do
- next [] unless Feature.enabled?(:ci_cross_pipeline_artifacts_download, processable.project, default_enabled: false)
+ next [] unless Feature.enabled?(:ci_cross_pipeline_artifacts_download, processable.project, default_enabled: true)
specified_cross_dependencies.select { |dep| dep[:pipeline] && dep[:artifacts] }
end
diff --git a/app/models/user.rb b/app/models/user.rb
index f1c7644901a..c735f20b92c 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1493,6 +1493,10 @@ class User < ApplicationRecord
!solo_owned_groups.present?
end
+ def can_remove_self?
+ true
+ end
+
def ci_owned_runners
@ci_owned_runners ||= begin
project_runners = Ci::RunnerProject
diff --git a/app/services/jira/requests/base.rb b/app/services/jira/requests/base.rb
index 4ed8df0f235..098aae9284c 100644
--- a/app/services/jira/requests/base.rb
+++ b/app/services/jira/requests/base.rb
@@ -18,14 +18,19 @@ module Jira
request
end
+ # We have to add the context_path here because the Jira client is not taking it into account
def base_api_url
- "/rest/api/#{api_version}"
+ "#{context_path}/rest/api/#{api_version}"
end
private
attr_reader :jira_service, :project
+ def context_path
+ client.options[:context_path].to_s
+ end
+
# override this method in the specific request class implementation if a differnt API version is required
def api_version
JIRA_API_VERSION
diff --git a/app/views/import/bulk_imports/status.html.haml b/app/views/import/bulk_imports/status.html.haml
index 80b96a25ebb..6757c32d1e1 100644
--- a/app/views/import/bulk_imports/status.html.haml
+++ b/app/views/import/bulk_imports/status.html.haml
@@ -3,9 +3,9 @@
- breadcrumb_title _('Import groups')
%h1.gl-my-0.gl-py-4.gl-font-size-h1.gl-border-solid.gl-border-gray-200.gl-border-0.gl-border-b-1
- = s_('ImportGroups|Import groups from GitLab')
+ = s_('BulkImport|Import groups from GitLab')
%p.gl-my-0.gl-py-5.gl-border-solid.gl-border-gray-200.gl-border-0.gl-border-b-1
- = s_('ImportGroups|Importing groups from %{link}').html_safe % { link: external_link(@source_url, @source_url) }
+ = s_('BulkImport|Importing groups from %{link}').html_safe % { link: external_link(@source_url, @source_url) }
#import-groups-mount-element{ data: { status_path: status_import_bulk_imports_path(format: :json),
available_namespaces_path: import_available_namespaces_path(format: :json),
diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml
index fe00420c86c..ca64c5f57b3 100644
--- a/app/views/profiles/accounts/show.html.haml
+++ b/app/views/profiles/accounts/show.html.haml
@@ -79,6 +79,11 @@
%strong= current_user.solo_owned_groups.map(&:name).join(', ')
%p
= s_('Profiles|You must transfer ownership or delete these groups before you can delete your account.')
+ - elsif !current_user.can_remove_self?
+ %p
+ = s_('Profiles|GitLab is unable to verify your identity automatically.')
+ %p
+ = s_('Profiles|Please email %{data_request} to begin the account deletion process.').html_safe % { data_request: mail_to('personal-data-request@gitlab.com') }
- else
%p
= s_("Profiles|You don't have access to delete this user.")