Commit d179f002 authored by Rubén Dávila's avatar Rubén Dávila

CE backport for creating CI/CD projects from GitHub

parent 42725ea9
Pipeline #18546112 failed with stages
in 79 minutes and 41 seconds
import { __ } from './locale'; import _ from 'underscore';
import { __, sprintf } from './locale';
import axios from './lib/utils/axios_utils'; import axios from './lib/utils/axios_utils';
import flash from './flash'; import flash from './flash';
import { convertPermissionToBoolean } from './lib/utils/common_utils';
class ImporterStatus { class ImporterStatus {
constructor(jobsUrl, importUrl) { constructor({ jobsUrl, importUrl, ciCdOnly }) {
this.jobsUrl = jobsUrl; this.jobsUrl = jobsUrl;
this.importUrl = importUrl; this.importUrl = importUrl;
this.ciCdOnly = ciCdOnly;
this.initStatusPage(); this.initStatusPage();
this.setAutoUpdate(); this.setAutoUpdate();
} }
...@@ -45,6 +48,7 @@ class ImporterStatus { ...@@ -45,6 +48,7 @@ class ImporterStatus {
repo_id: id, repo_id: id,
target_namespace: targetNamespace, target_namespace: targetNamespace,
new_name: newName, new_name: newName,
ci_cd_only: this.ciCdOnly,
}) })
.then(({ data }) => { .then(({ data }) => {
const job = $(`tr#repo_${id}`); const job = $(`tr#repo_${id}`);
...@@ -54,7 +58,13 @@ class ImporterStatus { ...@@ -54,7 +58,13 @@ class ImporterStatus {
$('table.import-jobs tbody').prepend(job); $('table.import-jobs tbody').prepend(job);
job.addClass('active'); job.addClass('active');
job.find('.import-actions').html('<i class="fa fa-spinner fa-spin" aria-label="importing"></i> started'); const connectingVerb = this.ciCdOnly ? __('connecting') : __('importing');
job.find('.import-actions').html(sprintf(
_.escape(__('%{loadingIcon} Started')), {
loadingIcon: `<i class="fa fa-spinner fa-spin" aria-label="${_.escape(connectingVerb)}"></i>`,
},
false,
));
}) })
.catch(() => flash(__('An error occurred while importing project'))); .catch(() => flash(__('An error occurred while importing project')));
} }
...@@ -71,13 +81,16 @@ class ImporterStatus { ...@@ -71,13 +81,16 @@ class ImporterStatus {
switch (job.import_status) { switch (job.import_status) {
case 'finished': case 'finished':
jobItem.removeClass('active').addClass('success'); jobItem.removeClass('active').addClass('success');
statusField.html('<span><i class="fa fa-check"></i> done</span>'); statusField.html(`<span><i class="fa fa-check"></i> ${__('Done')}</span>`);
break; break;
case 'scheduled': case 'scheduled':
statusField.html(`${spinner} scheduled`); statusField.html(`${spinner} ${__('Scheduled')}`);
break; break;
case 'started': case 'started':
statusField.html(`${spinner} started`); statusField.html(`${spinner} ${__('Started')}`);
break;
case 'failed':
statusField.html(__('Failed'));
break; break;
default: default:
statusField.html(job.import_status); statusField.html(job.import_status);
...@@ -98,7 +111,11 @@ function initImporterStatus() { ...@@ -98,7 +111,11 @@ function initImporterStatus() {
if (importerStatus) { if (importerStatus) {
const data = importerStatus.dataset; const data = importerStatus.dataset;
return new ImporterStatus(data.jobsImportPath, data.importPath); return new ImporterStatus({
jobsUrl: data.jobsImportPath,
importUrl: data.importPath,
ciCdOnly: convertPermissionToBoolean(data.ciCdOnly),
});
} }
} }
......
...@@ -42,7 +42,9 @@ class Import::GithubController < Import::BaseController ...@@ -42,7 +42,9 @@ class Import::GithubController < Import::BaseController
target_namespace = find_or_create_namespace(namespace_path, current_user.namespace_path) target_namespace = find_or_create_namespace(namespace_path, current_user.namespace_path)
if can?(current_user, :create_projects, target_namespace) if can?(current_user, :create_projects, target_namespace)
project = Gitlab::LegacyGithubImport::ProjectCreator.new(repo, project_name, target_namespace, current_user, access_params, type: provider).execute project = Gitlab::LegacyGithubImport::ProjectCreator
.new(repo, project_name, target_namespace, current_user, access_params, type: provider)
.execute(extra_project_attrs)
if project.persisted? if project.persisted?
render json: ProjectSerializer.new.represent(project) render json: ProjectSerializer.new.represent(project)
...@@ -73,15 +75,15 @@ class Import::GithubController < Import::BaseController ...@@ -73,15 +75,15 @@ class Import::GithubController < Import::BaseController
end end
def new_import_url def new_import_url
public_send("new_import_#{provider}_url") # rubocop:disable GitlabSecurity/PublicSend public_send("new_import_#{provider}_url", extra_import_params) # rubocop:disable GitlabSecurity/PublicSend
end end
def status_import_url def status_import_url
public_send("status_import_#{provider}_url") # rubocop:disable GitlabSecurity/PublicSend public_send("status_import_#{provider}_url", extra_import_params) # rubocop:disable GitlabSecurity/PublicSend
end end
def callback_import_url def callback_import_url
public_send("callback_import_#{provider}_url") # rubocop:disable GitlabSecurity/PublicSend public_send("callback_import_#{provider}_url", extra_import_params) # rubocop:disable GitlabSecurity/PublicSend
end end
def provider_unauthorized def provider_unauthorized
...@@ -116,4 +118,12 @@ class Import::GithubController < Import::BaseController ...@@ -116,4 +118,12 @@ class Import::GithubController < Import::BaseController
def client_options def client_options
{} {}
end end
def extra_project_attrs
{}
end
def extra_import_params
{}
end
end end
...@@ -36,6 +36,42 @@ module ImportHelper ...@@ -36,6 +36,42 @@ module ImportHelper
_('Please wait while we import the repository for you. Refresh at will.') _('Please wait while we import the repository for you. Refresh at will.')
end end
def import_github_title
_('Import repositories from GitHub')
end
def import_github_authorize_message
_('To import GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:')
end
def import_github_personal_access_token_message
personal_access_token_link = link_to _('Personal Access Token'), 'https://github.com/settings/tokens'
if github_import_configured?
_('Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import.').html_safe % { personal_access_token_link: personal_access_token_link }
else
_('To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import.').html_safe % { personal_access_token_link: personal_access_token_link }
end
end
def import_configure_github_admin_message
github_integration_link = link_to 'GitHub integration', help_page_path('integration/github')
if current_user.admin?
_('Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token.').html_safe % { github_integration_link: github_integration_link }
else
_('Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token.').html_safe % { github_integration_link: github_integration_link }
end
end
def import_githubish_choose_repository_message
_('Choose which repositories you want to import.')
end
def import_all_githubish_repositories_button_label
_('Import all repositories')
end
private private
def github_project_url(full_path) def github_project_url(full_path)
......
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
- provider_title = Gitlab::ImportSources.title(provider) - provider_title = Gitlab::ImportSources.title(provider)
%p.light %p.light
Select projects you want to import. = import_githubish_choose_repository_message
%hr %hr
%p %p
= button_tag class: "btn btn-import btn-success js-import-all" do = button_tag class: "btn btn-import btn-success js-import-all" do
Import all projects = import_all_githubish_repositories_button_label
= icon("spinner spin", class: "loading-icon") = icon("spinner spin", class: "loading-icon")
.table-responsive .table-responsive
...@@ -16,9 +16,9 @@ ...@@ -16,9 +16,9 @@
%colgroup.import-jobs-status-col %colgroup.import-jobs-status-col
%thead %thead
%tr %tr
%th From #{provider_title} %th= _('From %{provider_title}') % { provider_title: provider_title }
%th To GitLab %th= _('To GitLab')
%th Status %th= _('Status')
%tbody %tbody
- @already_added_projects.each do |project| - @already_added_projects.each do |project|
%tr{ id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}" } %tr{ id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}" }
...@@ -30,10 +30,12 @@ ...@@ -30,10 +30,12 @@
- if project.import_status == 'finished' - if project.import_status == 'finished'
%span %span
%i.fa.fa-check %i.fa.fa-check
done = _('Done')
- elsif project.import_status == 'started' - elsif project.import_status == 'started'
%i.fa.fa-spinner.fa-spin %i.fa.fa-spinner.fa-spin
started = _('Started')
- elsif project.import_status == 'failed'
= _('Failed')
- else - else
= project.human_import_status_name = project.human_import_status_name
...@@ -55,7 +57,9 @@ ...@@ -55,7 +57,9 @@
= text_field_tag :path, repo.name, class: "input-mini form-control", tabindex: 2, autofocus: true, required: true = text_field_tag :path, repo.name, class: "input-mini form-control", tabindex: 2, autofocus: true, required: true
%td.import-actions.job-status %td.import-actions.job-status
= button_tag class: "btn btn-import js-add-to-import" do = button_tag class: "btn btn-import js-add-to-import" do
Import = has_ci_cd_only_params? ? _('Connect') : _('Import')
= icon("spinner spin", class: "loading-icon") = icon("spinner spin", class: "loading-icon")
.js-importer-status{ data: { jobs_import_path: "#{url_for([:jobs, :import, provider])}", import_path: "#{url_for([:import, provider])}" } } .js-importer-status{ data: { jobs_import_path: "#{url_for([:jobs, :import, provider])}",
import_path: "#{url_for([:import, provider])}",
ci_cd_only: "#{has_ci_cd_only_params?}" } }
- page_title "GitHub Import" - title = has_ci_cd_only_params? ? _('Connect repositories from GitHub') : _('GitHub import')
- page_title title
- breadcrumb_title title
- header_title "Projects", root_path - header_title "Projects", root_path
%h3.page-title %h3.page-title
= icon 'github', text: 'Import Projects from GitHub' = icon 'github', text: import_github_title
- if github_import_configured? - if github_import_configured?
%p %p
To import a GitHub project, you first need to authorize GitLab to access = import_github_authorize_message
the list of your GitHub repositories:
= link_to 'List your GitHub repositories', status_import_github_path, class: 'btn btn-success' = link_to _('List your GitHub repositories'), status_import_github_path, class: 'btn btn-success'
%hr %hr
%p %p
- if github_import_configured? = import_github_personal_access_token_message
Alternatively,
- else
To import a GitHub project,
you can use a
= succeed '.' do
= link_to 'Personal Access Token', 'https://github.com/settings/tokens'
When you create your Personal Access Token,
you will need to select the <code>repo</code> scope, so we can display a
list of your public and private repositories which are available for import.
= form_tag personal_access_token_import_github_path, method: :post, class: 'form-inline' do = form_tag personal_access_token_import_github_path, method: :post, class: 'form-inline' do
.form-group .form-group
= text_field_tag :personal_access_token, '', class: 'form-control', placeholder: "Personal Access Token", size: 40 = text_field_tag :personal_access_token, '', class: 'form-control', placeholder: _('Personal Access Token'), size: 40
= submit_tag 'List your GitHub repositories', class: 'btn btn-success' = submit_tag _('List your GitHub repositories'), class: 'btn btn-success'
-# EE-specific start
-# EE-specific end
- unless github_import_configured? - unless github_import_configured?
%hr %hr
%p %p
Note: = import_configure_github_admin_message
- if current_user.admin?
As an administrator you may like to configure
- else
Consider asking your GitLab administrator to configure
= link_to 'GitHub integration', help_page_path("integration/github")
which will allow login via GitHub and allow importing projects without
generating a Personal Access Token.
- page_title "GitHub Import" - title = has_ci_cd_only_params? ? _('Connect repositories from GitHub') : _('GitHub import')
- page_title title
- breadcrumb_title title
- header_title "Projects", root_path - header_title "Projects", root_path
%h3.page-title %h3.page-title
= icon 'github', text: 'Import Projects from GitHub' = icon 'github', text: import_github_title
= render 'import/githubish_status', provider: 'github' = render 'import/githubish_status', provider: 'github'
...@@ -73,7 +73,7 @@ ...@@ -73,7 +73,7 @@
= icon('gitlab', text: 'GitLab export') = icon('gitlab', text: 'GitLab export')
%div %div
- if github_import_enabled? - if github_import_enabled?
= link_to new_import_github_path, class: 'btn import_github' do = link_to new_import_github_path, class: 'btn js-import-github' do
= icon('github', text: 'GitHub') = icon('github', text: 'GitHub')
%div %div
- if bitbucket_import_enabled? - if bitbucket_import_enabled?
......
...@@ -12,9 +12,8 @@ module Gitlab ...@@ -12,9 +12,8 @@ module Gitlab
@type = type @type = type
end end
def execute def execute(extra_attrs = {})
::Projects::CreateService.new( attrs = {
current_user,
name: name, name: name,
path: name, path: name,
description: repo.description, description: repo.description,
...@@ -24,7 +23,9 @@ module Gitlab ...@@ -24,7 +23,9 @@ module Gitlab
import_source: repo.full_name, import_source: repo.full_name,
import_url: import_url, import_url: import_url,
skip_wiki: skip_wiki skip_wiki: skip_wiki
).execute }.merge!(extra_attrs)
::Projects::CreateService.new(current_user, attrs).execute
end end
private private
......
...@@ -8,8 +8,8 @@ msgid "" ...@@ -8,8 +8,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: gitlab 1.0.0\n" "Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-03-05 13:02-0600\n" "POT-Creation-Date: 2018-03-05 17:10-0600\n"
"PO-Revision-Date: 2018-03-05 13:02-0600\n" "PO-Revision-Date: 2018-03-05 17:10-0600\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n" "Language: \n"
...@@ -59,6 +59,9 @@ msgid_plural "%{count} participants" ...@@ -59,6 +59,9 @@ msgid_plural "%{count} participants"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
msgid "%{loadingIcon} Started"
msgstr ""
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead" msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr "" msgstr ""
...@@ -210,6 +213,9 @@ msgstr "" ...@@ -210,6 +213,9 @@ msgstr ""
msgid "Allows you to add and manage Kubernetes clusters." msgid "Allows you to add and manage Kubernetes clusters."
msgstr "" msgstr ""
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
msgid "An error occurred previewing the blob" msgid "An error occurred previewing the blob"
msgstr "" msgstr ""
...@@ -288,9 +294,6 @@ msgstr "" ...@@ -288,9 +294,6 @@ msgstr ""
msgid "Are you sure you want to delete this pipeline schedule?" msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "" msgstr ""
msgid "Are you sure you want to discard your changes?"
msgstr ""
msgid "Are you sure you want to reset registration token?" msgid "Are you sure you want to reset registration token?"
msgstr "" msgstr ""
...@@ -392,9 +395,6 @@ msgstr[1] "" ...@@ -392,9 +395,6 @@ msgstr[1] ""
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}" msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr "" msgstr ""
msgid "Branch has changed"
msgstr ""
msgid "Branch is already taken" msgid "Branch is already taken"
msgstr "" msgstr ""
...@@ -512,9 +512,6 @@ msgstr "" ...@@ -512,9 +512,6 @@ msgstr ""
msgid "Cancel" msgid "Cancel"
msgstr "" msgstr ""
msgid "Cancel edit"
msgstr ""
msgid "Cannot modify managed Kubernetes cluster" msgid "Cannot modify managed Kubernetes cluster"
msgstr "" msgstr ""
...@@ -569,6 +566,9 @@ msgstr "" ...@@ -569,6 +566,9 @@ msgstr ""
msgid "Choose file..." msgid "Choose file..."
msgstr "" msgstr ""
msgid "Choose which repositories you want to import."
msgstr ""
msgid "CiStatusLabel|canceled" msgid "CiStatusLabel|canceled"
msgstr "" msgstr ""
...@@ -662,6 +662,9 @@ msgstr "" ...@@ -662,6 +662,9 @@ msgstr ""
msgid "Clone repository" msgid "Clone repository"
msgstr "" msgstr ""
msgid "Close"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster" msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "" msgstr ""
...@@ -1032,6 +1035,12 @@ msgstr "" ...@@ -1032,6 +1035,12 @@ msgstr ""
msgid "Confidentiality" msgid "Confidentiality"
msgstr "" msgstr ""
msgid "Connect"
msgstr ""
msgid "Connect repositories from GitHub"
msgstr ""
msgid "Container Registry" msgid "Container Registry"
msgstr "" msgstr ""
...@@ -1128,9 +1137,6 @@ msgstr "" ...@@ -1128,9 +1137,6 @@ msgstr ""
msgid "Create empty bare repository" msgid "Create empty bare repository"
msgstr "" msgstr ""
msgid "Create file"
msgstr ""
msgid "Create lists from labels. Issues with that label appear in that list." msgid "Create lists from labels. Issues with that label appear in that list."
msgstr "" msgstr ""
...@@ -1140,15 +1146,6 @@ msgstr "" ...@@ -1140,15 +1146,6 @@ msgstr ""
msgid "Create merge request and branch" msgid "Create merge request and branch"
msgstr "" msgstr ""
msgid "Create new branch"
msgstr ""
msgid "Create new directory"
msgstr ""
msgid "Create new file"
msgstr ""
msgid "Create new label" msgid "Create new label"
msgstr "" msgstr ""
...@@ -1238,15 +1235,15 @@ msgstr "" ...@@ -1238,15 +1235,15 @@ msgstr ""
msgid "Directory name" msgid "Directory name"
msgstr "" msgstr ""
msgid "Discard changes"
msgstr ""
msgid "Dismiss Cycle Analytics introduction box" msgid "Dismiss Cycle Analytics introduction box"
msgstr "" msgstr ""
msgid "Don't show again" msgid "Don't show again"
msgstr "" msgstr ""
msgid "Done"
msgstr ""
msgid "Download" msgid "Download"
msgstr "" msgstr ""
...@@ -1397,6 +1394,9 @@ msgstr "" ...@@ -1397,6 +1394,9 @@ msgstr ""
msgid "Explore public groups" msgid "Explore public groups"
msgstr "" msgstr ""
msgid "Failed"
msgstr ""
msgid "Failed Jobs" msgid "Failed Jobs"
msgstr "" msgstr ""
...@@ -1421,9 +1421,6 @@ msgstr "" ...@@ -1421,9 +1421,6 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure" msgid "Fields on this page are now uneditable, you can configure"
msgstr "" msgstr ""
msgid "File name"
msgstr ""
msgid "Files" msgid "Files"
msgstr "" msgstr ""
...@@ -1462,6 +1459,9 @@ msgstr "" ...@@ -1462,6 +1459,9 @@ msgstr ""
msgid "Format" msgid "Format"
msgstr "" msgstr ""
msgid "From %{provider_title}"
msgstr ""
msgid "From issue creation until deploy to production" msgid "From issue creation until deploy to production"
msgstr "" msgstr ""
...@@ -1489,12 +1489,18 @@ msgstr "" ...@@ -1489,12 +1489,18 @@ msgstr ""
msgid "Git version" msgid "Git version"
msgstr "" msgstr ""
msgid "GitHub import"
msgstr ""
msgid "GitLab Runner section" msgid "GitLab Runner section"
msgstr "" msgstr ""
msgid "Gitaly Servers" msgid "Gitaly Servers"
msgstr "" msgstr ""
msgid "Go back"
msgstr ""
msgid "Go to your fork" msgid "Go to your fork"
msgstr "" msgstr ""
...@@ -1608,9 +1614,18 @@ msgstr "" ...@@ -1608,9 +1614,18 @@ msgstr ""
msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>." msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
msgstr "" msgstr ""
msgid "Import"
msgstr ""
msgid "Import all repositories"
msgstr ""
msgid "Import in progress" msgid "Import in progress"
msgstr "" msgstr ""
msgid "Import repositories from GitHub"
msgstr ""
msgid "Import repository" msgid "Import repository"
msgstr "" msgstr ""
...@@ -1701,6 +1716,15 @@ msgstr "" ...@@ -1701,6 +1716,15 @@ msgstr ""
msgid "LFSStatus|Enabled" msgid "LFSStatus|Enabled"
msgstr "" msgstr ""
msgid "Label"
msgstr ""
msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
msgstr ""
msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
msgstr ""
msgid "Labels" msgid "Labels"
msgstr "" msgstr ""
...@@ -1760,7 +1784,7 @@ msgstr "" ...@@ -1760,7 +1784,7 @@ msgstr ""
msgid "Leave project" msgid "Leave project"
msgstr "" msgstr ""
msgid "Loading the GitLab IDE..." msgid "List your GitHub repositories"
msgstr "" msgstr ""
msgid "Lock" msgid "Lock"
...@@ -1954,6 +1978,12 @@ msgstr "" ...@@ -1954,6 +1978,12 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}" msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr "" msgstr ""
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
msgid "Notification events" msgid "Notification events"
msgstr "" msgstr ""