Skip to content
Snippets Groups Projects
Commit 4584eb0e authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent bdbded58
No related branches found
No related tags found
No related merge requests found
Showing
with 153 additions and 21 deletions
<script>
import _ from 'underscore';
import { mapActions, mapState, mapGetters } from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
Loading
Loading
@@ -7,6 +8,8 @@ import ImportedProjectTableRow from './imported_project_table_row.vue';
import ProviderRepoTableRow from './provider_repo_table_row.vue';
import eventHub from '../event_hub';
 
const reposFetchThrottleDelay = 1000;
export default {
name: 'ImportProjectsTable',
components: {
Loading
Loading
@@ -23,11 +26,11 @@ export default {
},
 
computed: {
...mapState(['importedProjects', 'providerRepos', 'isLoadingRepos']),
...mapState(['importedProjects', 'providerRepos', 'isLoadingRepos', 'filter']),
...mapGetters(['isImportingAnyRepo', 'hasProviderRepos', 'hasImportedProjects']),
 
emptyStateText() {
return sprintf(__('No %{providerTitle} repositories available to import'), {
return sprintf(__('No %{providerTitle} repositories found'), {
providerTitle: this.providerTitle,
});
},
Loading
Loading
@@ -47,21 +50,38 @@ export default {
},
 
methods: {
...mapActions(['fetchRepos', 'fetchJobs', 'stopJobsPolling', 'clearJobsEtagPoll']),
...mapActions([
'fetchRepos',
'fetchReposFiltered',
'fetchJobs',
'stopJobsPolling',
'clearJobsEtagPoll',
'setFilter',
]),
 
importAll() {
eventHub.$emit('importAll');
},
handleFilterInput({ target }) {
this.setFilter(target.value);
},
throttledFetchRepos: _.throttle(function fetch() {
eventHub.$off('importAll');
this.fetchRepos();
}, reposFetchThrottleDelay),
},
};
</script>
 
<template>
<div>
<p class="light text-nowrap mt-2">
{{ s__('ImportProjects|Select the projects you want to import') }}
</p>
<div class="d-flex justify-content-between align-items-end flex-wrap mb-3">
<p class="light text-nowrap mt-2 my-sm-0">
{{ s__('ImportProjects|Select the projects you want to import') }}
</p>
<loading-button
container-class="btn btn-success js-import-all"
:loading="isImportingAnyRepo"
Loading
Loading
@@ -70,6 +90,19 @@ export default {
type="button"
@click="importAll"
/>
<form novalidate @submit.prevent>
<input
:value="filter"
data-qa-selector="githubish_import_filter_field"
class="form-control"
name="filter"
:placeholder="__('Filter your projects by name')"
autofocus
size="40"
@input="handleFilterInput($event)"
@keyup.enter="throttledFetchRepos"
/>
</form>
</div>
<gl-loading-icon
v-if="isLoadingRepos"
Loading
Loading
Loading
Loading
@@ -38,7 +38,7 @@ export default function mountImportProjectsTable(mountElement) {
},
 
methods: {
...mapActions(['setInitialData']),
...mapActions(['setInitialData', 'setFilter']),
},
 
render(createElement) {
Loading
Loading
Loading
Loading
@@ -5,6 +5,7 @@ import Poll from '~/lib/utils/poll';
import createFlash from '~/flash';
import { s__, sprintf } from '~/locale';
import axios from '~/lib/utils/axios_utils';
import { jobsPathWithFilter, reposPathWithFilter } from './getters';
 
let eTagPoll;
 
Loading
Loading
@@ -19,16 +20,20 @@ export const restartJobsPolling = () => {
};
 
export const setInitialData = ({ commit }, data) => commit(types.SET_INITIAL_DATA, data);
export const setFilter = ({ commit }, filter) => commit(types.SET_FILTER, filter);
 
export const requestRepos = ({ commit }, repos) => commit(types.REQUEST_REPOS, repos);
export const receiveReposSuccess = ({ commit }, repos) =>
commit(types.RECEIVE_REPOS_SUCCESS, repos);
export const receiveReposError = ({ commit }) => commit(types.RECEIVE_REPOS_ERROR);
export const fetchRepos = ({ state, dispatch }) => {
dispatch('stopJobsPolling');
dispatch('requestRepos');
 
const { provider } = state;
return axios
.get(state.reposPath)
.get(reposPathWithFilter(state))
.then(({ data }) =>
dispatch('receiveReposSuccess', convertObjectPropsToCamelCase(data, { deep: true })),
)
Loading
Loading
@@ -36,7 +41,7 @@ export const fetchRepos = ({ state, dispatch }) => {
.catch(() => {
createFlash(
sprintf(s__('ImportProjects|Requesting your %{provider} repositories failed'), {
provider: state.provider,
provider,
}),
);
 
Loading
Loading
@@ -77,16 +82,23 @@ export const fetchImport = ({ state, dispatch }, { newName, targetNamespace, rep
export const receiveJobsSuccess = ({ commit }, updatedProjects) =>
commit(types.RECEIVE_JOBS_SUCCESS, updatedProjects);
export const fetchJobs = ({ state, dispatch }) => {
if (eTagPoll) return;
const { filter } = state;
if (eTagPoll) {
stopJobsPolling();
clearJobsEtagPoll();
}
 
eTagPoll = new Poll({
resource: {
fetchJobs: () => axios.get(state.jobsPath),
fetchJobs: () => axios.get(jobsPathWithFilter(state)),
},
method: 'fetchJobs',
successCallback: ({ data }) =>
dispatch('receiveJobsSuccess', convertObjectPropsToCamelCase(data, { deep: true })),
errorCallback: () => createFlash(s__('ImportProjects|Updating the imported projects failed')),
errorCallback: () =>
createFlash(s__('ImportProjects|Update of imported projects with realtime changes failed')),
data: { filter },
});
 
if (!Visibility.hidden()) {
Loading
Loading
Loading
Loading
@@ -20,3 +20,8 @@ export const isImportingAnyRepo = state => state.reposBeingImported.length > 0;
export const hasProviderRepos = state => state.providerRepos.length > 0;
 
export const hasImportedProjects = state => state.importedProjects.length > 0;
export const reposPathWithFilter = ({ reposPath, filter = '' }) =>
filter ? `${reposPath}?filter=${filter}` : reposPath;
export const jobsPathWithFilter = ({ jobsPath, filter = '' }) =>
filter ? `${jobsPath}?filter=${filter}` : jobsPath;
Loading
Loading
@@ -9,3 +9,5 @@ export const RECEIVE_IMPORT_SUCCESS = 'RECEIVE_IMPORT_SUCCESS';
export const RECEIVE_IMPORT_ERROR = 'RECEIVE_IMPORT_ERROR';
 
export const RECEIVE_JOBS_SUCCESS = 'RECEIVE_JOBS_SUCCESS';
export const SET_FILTER = 'SET_FILTER';
Loading
Loading
@@ -6,6 +6,10 @@ export default {
Object.assign(state, data);
},
 
[types.SET_FILTER](state, filter) {
state.filter = filter;
},
[types.REQUEST_REPOS](state) {
state.isLoadingRepos = true;
},
Loading
Loading
Loading
Loading
@@ -12,4 +12,5 @@ export default () => ({
isLoadingRepos: false,
canSelectNamespace: false,
ciCdOnly: false,
filter: '',
});
Loading
Loading
@@ -2,6 +2,7 @@
 
class Import::GithubController < Import::BaseController
include ImportHelper
include ActionView::Helpers::SanitizeHelper
 
before_action :verify_import_enabled
before_action :provider_auth, only: [:status, :realtime_changes, :create]
Loading
Loading
@@ -55,7 +56,7 @@ class Import::GithubController < Import::BaseController
def realtime_changes
Gitlab::PollingInterval.set_header(response, interval: 3_000)
 
render json: find_jobs(provider)
render json: already_added_projects.to_json(only: [:id], methods: [:import_status])
end
 
private
Loading
Loading
@@ -82,7 +83,7 @@ class Import::GithubController < Import::BaseController
end
 
def already_added_projects
@already_added_projects ||= find_already_added_projects(provider)
@already_added_projects ||= filtered(find_already_added_projects(provider))
end
 
def already_added_project_names
Loading
Loading
@@ -104,7 +105,7 @@ class Import::GithubController < Import::BaseController
end
 
def client_repos
@client_repos ||= client.repos
@client_repos ||= filtered(client.repos)
end
 
def verify_import_enabled
Loading
Loading
@@ -185,6 +186,20 @@ class Import::GithubController < Import::BaseController
def extra_import_params
{}
end
def sanitized_filter_param
@filter ||= sanitize(params[:filter])
end
def filter_attribute
:name
end
def filtered(collection)
return collection unless sanitized_filter_param
collection.select { |item| item[filter_attribute].include?(sanitized_filter_param) }
end
end
 
Import::GithubController.prepend_if_ee('EE::Import::GithubController')
---
title: Add GitHub & Gitea importers project filtering
merge_request: 16823
author:
type: added
Loading
Loading
@@ -66,10 +66,14 @@ From there, you can see the import statuses of your Gitea repositories.
- whereas those that are not yet imported will have an **Import** button on the
right side of the table.
 
If you want, you can import all your Gitea projects in one go by hitting
**Import all projects** in the upper left corner.
You also can:
 
![Gitea importer page](img/import_projects_from_github_importer.png)
- Import all your Gitea projects in one go by hitting **Import all projects** in
the upper left corner
- Filter projects by name. If filter is applied, hitting **Import all projects**
will only import matched projects
![Gitea importer page](img/import_projects_from_gitea_importer_v12_3.png)
 
---
 
Loading
Loading
Loading
Loading
@@ -115,11 +115,14 @@ your GitHub repositories are listed.
 
1. By default, the proposed repository namespaces match the names as they exist in GitHub, but based on your permissions,
you can choose to edit these names before you proceed to import any of them.
1. Select the **Import** button next to any number of repositories, or select **Import all repositories**.
1. Select the **Import** button next to any number of repositories, or select **Import all repositories**. Additionally,
you can filter projects by name. If filter is applied, **Import all repositories** only imports matched repositories.
1. The **Status** column shows the import status of each repository. You can choose to leave the page open and it will
update in realtime or you can return to it later.
1. Once a repository has been imported, click its GitLab path to open its GitLab URL.
 
![Github importer page](img/import_projects_from_github_importer_v12_3.png)
## Mirroring and pipeline status sharing
 
Depending your GitLab tier, [project mirroring](../../../workflow/repository_mirroring.md) can be set up to keep
Loading
Loading
doc/user/project/import/img/import_projects_from_gitea_importer_v12_3.png

49.5 KiB

doc/user/project/import/img/import_projects_from_github_importer.png

17.5 KiB

doc/user/project/import/img/import_projects_from_github_importer_v12_3.png

52.2 KiB

Loading
Loading
@@ -18,7 +18,8 @@ module Gitlab
StageEvents::MergeRequestMerged => 104,
StageEvents::CodeStageStart => 1_000,
StageEvents::IssueStageEnd => 1_001,
StageEvents::PlanStageStart => 1_002
StageEvents::PlanStageStart => 1_002,
StageEvents::ProductionStageEnd => 1_003
}.freeze
 
EVENTS = ENUM_MAPPING.keys.freeze
Loading
Loading
@@ -32,7 +33,8 @@ module Gitlab
StageEvents::MergeRequestCreated
],
StageEvents::IssueCreated => [
StageEvents::IssueStageEnd
StageEvents::IssueStageEnd,
StageEvents::ProductionStageEnd
],
StageEvents::MergeRequestCreated => [
StageEvents::MergeRequestMerged
Loading
Loading
Loading
Loading
@@ -16,6 +16,21 @@ module Gitlab
def object_type
MergeRequest
end
def timestamp_projection
issue_metrics_table[:first_mentioned_in_commit_at]
end
# rubocop: disable CodeReuse/ActiveRecord
def apply_query_customization(query)
issue_metrics_join = mr_closing_issues_table
.join(issue_metrics_table)
.on(mr_closing_issues_table[:issue_id].eq(issue_metrics_table[:issue_id]))
.join_sources
query.joins(:merge_requests_closing_issues).joins(issue_metrics_join)
end
# rubocop: enable CodeReuse/ActiveRecord
end
end
end
Loading
Loading
Loading
Loading
@@ -16,6 +16,10 @@ module Gitlab
def object_type
Issue
end
def timestamp_projection
issue_table[:created_at]
end
end
end
end
Loading
Loading
Loading
Loading
@@ -16,6 +16,16 @@ module Gitlab
def object_type
Issue
end
def timestamp_projection
issue_metrics_table[:first_mentioned_in_commit_at]
end
# rubocop: disable CodeReuse/ActiveRecord
def apply_query_customization(query)
query.joins(:metrics)
end
# rubocop: enable CodeReuse/ActiveRecord
end
end
end
Loading
Loading
Loading
Loading
@@ -16,6 +16,19 @@ module Gitlab
def object_type
Issue
end
def timestamp_projection
Arel::Nodes::NamedFunction.new('COALESCE', [
issue_metrics_table[:first_associated_with_milestone_at],
issue_metrics_table[:first_added_to_board_at]
])
end
# rubocop: disable CodeReuse/ActiveRecord
def apply_query_customization(query)
query.joins(:metrics).where(issue_metrics_table[:first_added_to_board_at].not_eq(nil).or(issue_metrics_table[:first_associated_with_milestone_at].not_eq(nil)))
end
# rubocop: enable CodeReuse/ActiveRecord
end
end
end
Loading
Loading
Loading
Loading
@@ -16,6 +16,10 @@ module Gitlab
def object_type
MergeRequest
end
def timestamp_projection
mr_table[:created_at]
end
end
end
end
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment