Commit 99ddd1dc authored by Rémy Coutable's avatar Rémy Coutable

Modify GithubImport to support Gitea

The reason is that Gitea plan to be GitHub-compatible so it makes sense
to just modify GitHubImport a bit for now, and hopefully we can change
it to GitHubishImport once Gitea is 100%-compatible.
Signed-off-by: default avatarRémy Coutable <remy@rymai.me>
parent 103114e3
...@@ -11,7 +11,7 @@ class Import::GiteaController < Import::GithubController ...@@ -11,7 +11,7 @@ class Import::GiteaController < Import::GithubController
end end
def status def status
@gitea_root_url = session[:host_url] @gitea_host_url = session[:host_url]
super super
end end
......
...@@ -8,8 +8,8 @@ module ImportHelper ...@@ -8,8 +8,8 @@ module ImportHelper
link_to path_with_namespace, github_project_url(path_with_namespace), target: '_blank' link_to path_with_namespace, github_project_url(path_with_namespace), target: '_blank'
end end
def gitea_project_link(root_url, path_with_namespace) def gitea_project_link(path_with_namespace)
link_to path_with_namespace, gitea_project_url(root_url, path_with_namespace), target: '_blank' link_to path_with_namespace, gitea_project_url(path_with_namespace), target: '_blank'
end end
private private
...@@ -25,7 +25,7 @@ module ImportHelper ...@@ -25,7 +25,7 @@ module ImportHelper
@github_url = provider.fetch('url', 'https://github.com') if provider @github_url = provider.fetch('url', 'https://github.com') if provider
end end
def gitea_project_url(root_url, path_with_namespace) def gitea_project_url(path_with_namespace)
"#{root_url}/#{path_with_namespace}" "#{@gitea_host_url.sub(%r{/+\z}, '')}/#{path_with_namespace}"
end end
end end
- page_title "Gitea import" - page_title "Gitea Import"
- header_title "Projects", root_path - header_title "Projects", root_path
%h3.page-title %h3.page-title
= custom_icon('go_logo') = custom_icon('go_logo')
Import projects from Gitea Import Projects from Gitea
%p.light %p.light
Select projects you want to import. Select projects you want to import.
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
- @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)}"}
%td %td
= gitea_project_link(@gitea_root_url, project.import_source) = gitea_project_link(project.import_source)
%td %td
= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project] = link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
%td.job-status %td.job-status
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
- @repos.each do |repo| - @repos.each do |repo|
%tr{id: "repo_#{repo.id}"} %tr{id: "repo_#{repo.id}"}
%td %td
= gitea_project_link(@gitea_root_url, repo.full_name) = gitea_project_link(repo.full_name)
%td.import-target %td.import-target
%fieldset.row %fieldset.row
.input-group .input-group
......
- page_title "GitHub import" - page_title "GitHub Import"
- header_title "Projects", root_path - header_title "Projects", root_path
%h3.page-title %h3.page-title
%i.fa.fa-github = icon 'github', text: 'Import Projects from GitHub'
Import projects from GitHub
%p.light %p.light
Select projects you want to import. Select projects you want to import.
......
--- ---
title: New Gitea importer title: New Gitea importer
merge_request: 6945 merge_request: 8116
author: author:
...@@ -15,6 +15,10 @@ module Gitlab ...@@ -15,6 +15,10 @@ module Gitlab
end end
end end
def url
raw_data.url || ''
end
private private
def gitlab_user_id(github_id) def gitlab_user_id(github_id)
......
...@@ -8,7 +8,7 @@ module Gitlab ...@@ -8,7 +8,7 @@ module Gitlab
def initialize(access_token, host: nil, api_version: 'v3') def initialize(access_token, host: nil, api_version: 'v3')
@access_token = access_token @access_token = access_token
@host = host @host = host.to_s.sub(%r{/+\z}, '')
@api_version = api_version @api_version = api_version
if access_token if access_token
...@@ -16,10 +16,6 @@ module Gitlab ...@@ -16,10 +16,6 @@ module Gitlab
end end
end end
def api_endpoint
host.present? && api_version.present? ? "#{host}/api/#{api_version}" : github_options[:site]
end
def api def api
@api ||= ::Octokit::Client.new( @api ||= ::Octokit::Client.new(
access_token: access_token, access_token: access_token,
...@@ -27,7 +23,7 @@ module Gitlab ...@@ -27,7 +23,7 @@ module Gitlab
# If there is no config, we're connecting to github.com and we # If there is no config, we're connecting to github.com and we
# should verify ssl. # should verify ssl.
connection_options: { connection_options: {
ssl: { verify: config ? config['verify_ssl'] : false } ssl: { verify: config ? config['verify_ssl'] : true }
} }
) )
end end
...@@ -70,6 +66,14 @@ module Gitlab ...@@ -70,6 +66,14 @@ module Gitlab
private private
def api_endpoint
if host.present? && api_version.present?
"#{host}/api/#{api_version}"
else
github_options[:site]
end
end
def config def config
Gitlab.config.omniauth.providers.find { |provider| provider.name == "github" } Gitlab.config.omniauth.providers.find { |provider| provider.name == "github" }
end end
......
...@@ -3,7 +3,7 @@ module Gitlab ...@@ -3,7 +3,7 @@ module Gitlab
class Importer class Importer
include Gitlab::ShellAdapter include Gitlab::ShellAdapter
attr_reader :client, :errors, :project, :repo, :repo_url attr_reader :errors, :project, :repo, :repo_url
def initialize(project) def initialize(project)
@project = project @project = project
...@@ -11,12 +11,27 @@ module Gitlab ...@@ -11,12 +11,27 @@ module Gitlab
@repo_url = project.import_url @repo_url = project.import_url
@errors = [] @errors = []
@labels = {} @labels = {}
end
if credentials def client
@client = Client.new(credentials[:user]) return @client if defined?(@client)
else unless credentials
raise Projects::ImportService::Error, "Unable to find project import data credentials for project ID: #{@project.id}" raise Projects::ImportService::Error,
"Unable to find project import data credentials for project ID: #{@project.id}"
end
opts = {}
# Gitea plan to be GitHub compliant
if project.import_type == 'gitea'
uri = URI.parse(project.import_url)
host = "#{uri.scheme}://#{uri.host}:#{uri.port}#{uri.path}".sub(%r{/?[\w-]+/[\w-]+\.git\z}, '')
opts = {
host: host,
api_version: 'v1'
}
end end
@client = Client.new(credentials[:user], opts)
end end
def execute def execute
...@@ -35,7 +50,13 @@ module Gitlab ...@@ -35,7 +50,13 @@ module Gitlab
import_comments(:issues) import_comments(:issues)
import_comments(:pull_requests) import_comments(:pull_requests)
import_wiki import_wiki
# Gitea doesn't have a Release API yet
# See https://github.com/go-gitea/gitea/issues/330
unless project.import_type == 'gitea'
import_releases import_releases
end
handle_errors handle_errors
true true
...@@ -44,7 +65,9 @@ module Gitlab ...@@ -44,7 +65,9 @@ module Gitlab
private private
def credentials def credentials
@credentials ||= project.import_data.credentials if project.import_data return @credentials if defined?(@credentials)
@credentials = project.import_data ? project.import_data.credentials : nil
end end
def handle_errors def handle_errors
...@@ -60,9 +83,10 @@ module Gitlab ...@@ -60,9 +83,10 @@ module Gitlab
fetch_resources(:labels, repo, per_page: 100) do |labels| fetch_resources(:labels, repo, per_page: 100) do |labels|
labels.each do |raw| labels.each do |raw|
begin begin
GithubImport::LabelFormatter.new(project, raw).create! gh_label = LabelFormatter.new(project, raw)
gh_label.create!
rescue => e rescue => e
errors << { type: :label, url: Gitlab::UrlSanitizer.sanitize(raw.url), errors: e.message } errors << { type: :label, url: Gitlab::UrlSanitizer.sanitize(gh_label.url), errors: e.message }
end end
end end
end end
...@@ -74,9 +98,10 @@ module Gitlab ...@@ -74,9 +98,10 @@ module Gitlab
fetch_resources(:milestones, repo, state: :all, per_page: 100) do |milestones| fetch_resources(:milestones, repo, state: :all, per_page: 100) do |milestones|
milestones.each do |raw| milestones.each do |raw|
begin begin
GithubImport::MilestoneFormatter.new(project, raw).create! gh_milestone = MilestoneFormatter.new(project, raw)
gh_milestone.create!
rescue => e rescue => e
errors << { type: :milestone, url: Gitlab::UrlSanitizer.sanitize(raw.url), errors: e.message } errors << { type: :milestone, url: Gitlab::UrlSanitizer.sanitize(gh_milestone.url), errors: e.message }
end end
end end
end end
...@@ -85,7 +110,7 @@ module Gitlab ...@@ -85,7 +110,7 @@ module Gitlab
def import_issues def import_issues
fetch_resources(:issues, repo, state: :all, sort: :created, direction: :asc, per_page: 100) do |issues| fetch_resources(:issues, repo, state: :all, sort: :created, direction: :asc, per_page: 100) do |issues|
issues.each do |raw| issues.each do |raw|
gh_issue = GithubImport::IssueFormatter.new(project, raw) gh_issue = IssueFormatter.new(project, raw)
begin begin
issuable = issuable =
...@@ -97,7 +122,7 @@ module Gitlab ...@@ -97,7 +122,7 @@ module Gitlab
apply_labels(issuable, raw) apply_labels(issuable, raw)
rescue => e rescue => e
errors << { type: :issue, url: Gitlab::UrlSanitizer.sanitize(raw.url), errors: e.message } errors << { type: :issue, url: Gitlab::UrlSanitizer.sanitize(gh_issue.url), errors: e.message }
end end
end end
end end
...@@ -106,18 +131,23 @@ module Gitlab ...@@ -106,18 +131,23 @@ module Gitlab
def import_pull_requests def import_pull_requests
fetch_resources(:pull_requests, repo, state: :all, sort: :created, direction: :asc, per_page: 100) do |pull_requests| fetch_resources(:pull_requests, repo, state: :all, sort: :created, direction: :asc, per_page: 100) do |pull_requests|
pull_requests.each do |raw| pull_requests.each do |raw|
pull_request = GithubImport::PullRequestFormatter.new(project, raw) gh_pull_request = PullRequestFormatter.new(project, raw)
next unless pull_request.valid? next unless gh_pull_request.valid?
begin begin
restore_source_branch(pull_request) unless pull_request.source_branch_exists? restore_source_branch(gh_pull_request) unless gh_pull_request.source_branch_exists?
restore_target_branch(pull_request) unless pull_request.target_branch_exists? restore_target_branch(gh_pull_request) unless gh_pull_request.target_branch_exists?
pull_request.create! merge_request = gh_pull_request.create!
# Gitea doesn't return PR in the Issue API endpoint, so labels must be assigned at this stage
if project.import_type == 'gitea'
apply_labels(merge_request, raw)
end
rescue => e rescue => e
errors << { type: :pull_request, url: Gitlab::UrlSanitizer.sanitize(pull_request.url), errors: e.message } errors << { type: :pull_request, url: Gitlab::UrlSanitizer.sanitize(gh_pull_request.url), errors: e.message }
ensure ensure
clean_up_restored_branches(pull_request) clean_up_restored_branches(gh_pull_request)
end end
end end
end end
...@@ -179,7 +209,7 @@ module Gitlab ...@@ -179,7 +209,7 @@ module Gitlab
ActiveRecord::Base.no_touching do ActiveRecord::Base.no_touching do
comments.each do |raw| comments.each do |raw|
begin begin
comment = GithubImport::CommentFormatter.new(project, raw) comment = CommentFormatter.new(project, raw)
# GH does not return info about comment's parent, so we guess it by checking its URL! # GH does not return info about comment's parent, so we guess it by checking its URL!
*_, parent, iid = URI(raw.html_url).path.split('/') *_, parent, iid = URI(raw.html_url).path.split('/')
issuable_class = parent == 'issues' ? Issue : MergeRequest issuable_class = parent == 'issues' ? Issue : MergeRequest
...@@ -198,7 +228,7 @@ module Gitlab ...@@ -198,7 +228,7 @@ module Gitlab
last_note_attrs = nil last_note_attrs = nil
cut_off_index = comments.find_index do |raw| cut_off_index = comments.find_index do |raw|
comment = GithubImport::CommentFormatter.new(project, raw) comment = CommentFormatter.new(project, raw)
comment_attrs = comment.attributes comment_attrs = comment.attributes
last_note_attrs ||= last_note.slice(*comment_attrs.keys) last_note_attrs ||= last_note.slice(*comment_attrs.keys)
...@@ -214,7 +244,7 @@ module Gitlab ...@@ -214,7 +244,7 @@ module Gitlab
def import_wiki def import_wiki
unless project.wiki.repository_exists? unless project.wiki.repository_exists?
wiki = GithubImport::WikiFormatter.new(project) wiki = WikiFormatter.new(project)
gitlab_shell.import_repository(project.repository_storage_path, wiki.path_with_namespace, wiki.import_url) gitlab_shell.import_repository(project.repository_storage_path, wiki.path_with_namespace, wiki.import_url)
end end
rescue Gitlab::Shell::Error => e rescue Gitlab::Shell::Error => e
...@@ -230,10 +260,10 @@ module Gitlab ...@@ -230,10 +260,10 @@ module Gitlab
fetch_resources(:releases, repo, per_page: 100) do |releases| fetch_resources(:releases, repo, per_page: 100) do |releases|
releases.each do |raw| releases.each do |raw|
begin begin
gh_release = GithubImport::ReleaseFormatter.new(project, raw) gh_release = ReleaseFormatter.new(project, raw)
gh_release.create! if gh_release.valid? gh_release.create! if gh_release.valid?
rescue => e rescue => e
errors << { type: :release, url: Gitlab::UrlSanitizer.sanitize(raw.url), errors: e.message } errors << { type: :release, url: Gitlab::UrlSanitizer.sanitize(gh_release.url), errors: e.message }
end end
end end
end end
......
module Gitlab
module GithubImport
class IssuableFormatter < BaseFormatter
def project_association
raise NotImplementedError
end
def number
raw_data.number
end
def find_condition
{ iid: number }
end
private
def state
raw_data.state == 'closed' ? 'closed' : 'opened'
end
def assigned?
raw_data.assignee.present?
end
def assignee_id
if assigned?
gitlab_user_id(raw_data.assignee.id)
end
end
def author
raw_data.user.login
end
def author_id
gitlab_author_id || project.creator_id
end
def body
raw_data.body || ""
end
def description
if gitlab_author_id
body
else
formatter.author_line(author) + body
end
end
def milestone
if raw_data.milestone.present?
milestone = MilestoneFormatter.new(project, raw_data.milestone)
project.milestones.find_by(milestone.find_condition)
end
end
end
end
end
module Gitlab module Gitlab
module GithubImport module GithubImport
class IssueFormatter < BaseFormatter class IssueFormatter < IssuableFormatter
def attributes def attributes
{ {
iid: number, iid: number,
...@@ -24,59 +24,9 @@ module Gitlab ...@@ -24,59 +24,9 @@ module Gitlab
:issues :issues
end end
def find_condition
{ iid: number }
end
def number
raw_data.number
end
def pull_request? def pull_request?
raw_data.pull_request.present? raw_data.pull_request.present?
end end
private
def assigned?
raw_data.assignee.present?
end
def assignee_id
if assigned?
gitlab_user_id(raw_data.assignee.id)
end
end
def author
raw_data.user.login
end
def author_id
gitlab_author_id || project.creator_id
end
def body
raw_data.body || ""
end
def description
if gitlab_author_id
body
else
formatter.author_line(author) + body
end
end
def milestone
if raw_data.milestone.present?
project.milestones.find_by(iid: raw_data.milestone.public_send("Gitlab::#{project.import_type.camelize}Import::MilestoneFormatter".constantize.iid_attr))
end
end
def state
raw_data.state == 'closed' ? 'closed' : 'opened'
end
end end
end end
end end
...@@ -3,7 +3,7 @@ module Gitlab ...@@ -3,7 +3,7 @@ module Gitlab
class MilestoneFormatter < BaseFormatter class MilestoneFormatter < BaseFormatter
def attributes def attributes
{ {
iid: raw_data.public_send("Gitlab::#{project.import_type.camelize}Import::MilestoneFormatter".constantize.iid_attr), iid: number,
project: project, project: project,
title: raw_data.title, title: raw_data.title,
description: raw_data.description, description: raw_data.description,
...@@ -19,11 +19,15 @@ module Gitlab ...@@ -19,11 +19,15 @@ module Gitlab
end end
def find_condition def find_condition
{ iid: raw_data.public_send("Gitlab::#{project.import_type.camelize}Import::MilestoneFormatter".constantize.iid_attr) } { iid: number }
end end
def self.iid_attr def number
:number if project.import_type == 'gitea'
raw_data.id
else
raw_data.number
end
end end
private private
......
module Gitlab module Gitlab
module GithubImport module GithubImport
class PullRequestFormatter < BaseFormatter class PullRequestFormatter < IssuableFormatter
delegate :exists?, :project, :ref, :repo, :sha, to: :source_branch, prefix: true delegate :exists?, :project, :ref, :repo, :sha, to: :source_branch, prefix: true
delegate :exists?, :project, :ref, :repo, :sha, to: :target_branch, prefix: true delegate :exists?, :project, :ref, :repo, :sha, to: :target_branch, prefix: true
...@@ -28,14 +28,6 @@ module Gitlab ...@@ -28,14 +28,6 @@ module Gitlab
:merge_requests :merge_requests
end end
def find_condition
{ iid: number }
end
def number
raw_data.number
end
def valid? def valid?
source_branch.valid? && target_branch.valid? source_branch.valid? && target_branch.valid?
end end
...@@ -60,55 +52,13 @@ module Gitlab ...@@ -60,55 +52,13 @@ module Gitlab
end end
end end
def url
raw_data.url
end
private private
def assigned?
raw_data.assignee.present?
end
def assignee_id
if assigned?
gitlab_user_id(raw_data.assignee.id)
end
end
def author
raw_data.user.login
end
def author_id
gitlab_author_id || project.creator_id
end
def body
raw_data.body || ""
end
def description
if gitlab_author_id
body
else
formatter.author_line(author) + body
end
end
def milestone
if raw_data.milestone.present?
project.milestones.find_by(iid: raw_data.milestone.public_send("Gitlab::#{project.import_type.camelize}Import::MilestoneFormatter".constantize.iid_attr))
end
end
def state def state
@state ||= if raw_data.state == 'closed' && raw_data.merged_at.present? if raw_data.state == 'closed' && raw_data.merged_at.present?
'merged' 'merged'
elsif raw_data.state == 'closed'
'closed'
else else
'opened' super
end end
end end
end end
......
...@@ -29,7 +29,7 @@ describe Import::GiteaController do ...@@ -29,7 +29,7 @@ describe Import::GiteaController do
before do before do
assign_host_url assign_host_url
end end
let(:extra_assign_expectations) { { gitea_root_url: host_url } } let(:extra_assign_expectations) { { gitea_host_url: host_url } }
end end
end end
......
...@@ -45,6 +45,7 @@ describe Gitlab::GithubImport::Client, lib: true do ...@@ -45,6 +45,7 @@ describe Gitlab::GithubImport::Client, lib: true do
end end
end end
describe '#api_endpoint' do
context 'when provider does not specity an API endpoint' do context 'when provider does not specity an API endpoint' do
it 'uses GitHub root API endpoint' do it 'uses GitHub root API endpoint' do
expect(client.api.api_endpoint).to eq 'https://api.github.com/' expect(client.api.api_endpoint).to eq 'https://api.github.com/'
...@@ -62,6 +63,31 @@ describe Gitlab::GithubImport::Client, lib: true do ...@@ -62,6 +63,31 @@ describe Gitlab::GithubImport::Client, lib: true do
end end
end end
context 'when given a host' do
subject(:client) { described_class.new(token, host: 'https://try.gitea.io/') }
it 'builds a endpoint with the given host and the default API version' do
expect(client.api.api_endpoint).to eq 'https://try.gitea.io/api/v3/'
end
end
context 'when given an API version' do
subject(:client) { described_class.new(token, api_version: 'v3') }
it 'does not use the API version without a host' do
expect(client.api.api_endpoint).to eq 'https://api.github.com/'
end
end
context 'when given a host and version' do
subject(:client) { described_class.new(token, host: 'https://try.gitea.io/', api_version: 'v3') }
it 'builds a endpoint with the given options' do
expect(client.api.api_endpoint).to eq 'https://try.gitea.io/api/v3/'
end
end
end
it 'does not raise error when rate limit is disabled' do it 'does not raise error when rate limit is disabled' do
stub_request(:get, /api.github.com/) stub_request(:get, /api.github.com/)
allow(client.api).to receive(:rate_limit!).and_raise(Octokit::NotFound) allow(client.api).to receive(:rate_limit!).and_raise(Octokit::NotFound)
......
require 'spec_helper' require 'spec_helper'
describe Gitlab::GithubImport::Importer, lib: true do describe Gitlab::GithubImport::Importer, lib: true do
describe '#execute' do shared_examples 'Gitlab::GithubImport::Importer#execute' do
let(:expected_not_called) { [] }
before do before do
allow(Rails).to receive(:cache).and_return(ActiveSupport::Cache::MemoryStore.new) allow(project).to receive(:import_data).and_return(double.as_null_object)
end
it 'calls import methods' do
importer = described_class.new(project)
expected_called = [
:import_labels, :import_milestones, :import_pull_requests, :import_issues,
:import_wiki, :import_releases, :handle_errors
]
expected_called -= expected_not_called
aggregate_failures do
expected_called.each do |method_name|
expect(importer).to receive(method_name)
end
expect(importer).to receive(:import_comments).with(:issues)
expect(importer).to receive(:import_comments).with(:pull_requests)
expected_not_called.each do |method_name|
expect(importer).not_to receive(method_name)
end
end
importer.execute
end
end end
context 'when an error occurs' do shared_examples 'Gitlab::GithubImport::Importer#execute an error occurs' do
let(:project) { create(:project, import_url: 'https://github.com/octocat/Hello-World.git', wiki_access_level: ProjectFeature::DISABLED) } before do
allow(project).to receive(:import_data).and_return(double.as_null_object)
allow(Rails).to receive(:cache).and_return(ActiveSupport::Cache::MemoryStore.new)
allow_any_instance_of(Octokit::Client).to receive(:rate_limit!).and_raise(Octokit::NotFound)
allow_any_instance_of(Gitlab::Shell).to receive(:import_repository).and_raise(Gitlab::Shell::Error)
allow_any_instance_of(Octokit::Client).to receive(:labels).and_return([label1, label2])
allow_any_instance_of(Octokit::Client).to receive(:milestones).and_return([milestone, milestone])
allow_any_instance_of(Octokit::Client).to receive(:issues).and_return([issue1, issue2])
allow_any_instance_of(Octokit::Client).to receive(:pull_requests).and_return([pull_request, pull_request])
allow_any_instance_of(Octokit::Client).to receive(:issues_comments).and_return([])
allow_any_instance_of(Octokit::Client).to receive(:pull_requests_comments).and_return([])
allow_any_instance_of(Octokit::Client).to receive(:last_response).and_return(double(rels: { next: nil }))
allow_any_instance_of(Octokit::Client).to receive(:releases).and_return([release1, release2])
end
let(:octocat) { double(id: 123456, login: 'octocat') } let(:octocat) { double(id: 123456, login: 'octocat') }
let(:created_at) { DateTime.strptime('2011-01-26T19:01:12Z') } let(:created_at) { DateTime.strptime('2011-01-26T19:01:12Z') }
let(:updated_at) { DateTime.strptime('2011-01-27T19:01:12Z') } let(:updated_at) { DateTime.strptime('2011-01-27T19:01:12Z') }
let(:repository) { double(id: 1, fork: false) }
let(:source_sha) { create(:commit, project: project).id }
let(:source_branch) { double(ref: 'feature', repo: repository, sha: source_sha) }
let(:target_sha) { create(:commit, project: project, git_commit: RepoHelpers.another_sample_commit).id }
let(:target_branch) { double(ref: 'master', repo: repository, sha: target_sha) }
let(:label1) do let(:label1) do
double( double(
name: 'Bug', name: 'Bug',
color: 'ff0000', color: 'ff0000',
url: 'https://api.github.com/repos/octocat/Hello-World/labels/bug' url: "#{api_root}/repos/octocat/Hello-World/labels/bug"
) )
end end
...@@ -29,12 +68,13 @@ describe Gitlab::GithubImport::Importer, lib: true do ...@@ -29,12 +68,13 @@ describe Gitlab::GithubImport::Importer, lib: true do
double( double(
name: nil, name: nil,
color: 'ff0000', color: 'ff0000',
url: 'https://api.github.com/repos/octocat/Hello-World/labels/bug' url: "#{api_root}/repos/octocat/Hello-World/labels/bug"
) )
end end
let(:milestone) do let(:milestone) do
double( double(
id: 1347, # For Gitea
number: 1347, number: 1347,
state: 'open', state: 'open',
title: '1.0', title: '1.0',
...@@ -43,7 +83,7 @@ describe Gitlab::GithubImport::Importer, lib: true do ...@@ -43,7 +83,7 @@ describe Gitlab::GithubImport::Importer, lib: true do
created_at: created_at, created_at: created_at,
updated_at: updated_at, updated_at: updated_at,
closed_at: nil, closed_at: nil,
url: 'https://api.github.com/repos/octocat/Hello-World/milestones/1' url: "#{api_root}/repos/octocat/Hello-World/milestones/1"
) )
end end
...@@ -61,8 +101,8 @@ describe Gitlab::GithubImport::Importer, lib: true do ...@@ -61,8 +101,8 @@ describe Gitlab::GithubImport::Importer, lib: true do
created_at: created_at, created_at: created_at,
updated_at: updated_at, updated_at: updated_at,
closed_at: nil, closed_at: nil,
url: 'https://api.github.com/repos/octocat/Hello-World/issues/1347', url: "#{api_root}/repos/octocat/Hello-World/issues/1347",
labels: [double(name: 'Label #1')], labels: [double(name: 'Label #1')]
) )
end end
...@@ -80,11 +120,16 @@ describe Gitlab::GithubImport::Importer, lib: true do ...@@ -80,11 +120,16 @@ describe Gitlab::GithubImport::Importer, lib: true do
created_at: created_at, created_at: created_at,
updated_at: updated_at, updated_at: updated_at,
closed_at: nil, closed_at: nil,
url: 'https://api.github.com/repos/octocat/Hello-World/issues/1348', url: "#{api_root}/repos/octocat/Hello-World/issues/1348",
labels: [double(name: 'Label #2')], labels: [double(name: 'Label #2')]
) )
end end
let(:repository) { double(id: 1, fork: false) }
let(:source_sha) { create(:commit, project: project).id }
let(:source_branch) { double(ref: 'feature', repo: repository, sha: source_sha) }
let(:target_sha) { create(:commit, project: project, git_commit: RepoHelpers.another_sample_commit).id }
let(:target_branch) { double(ref: 'master', repo: repository, sha: target_sha) }
let(:pull_request) do let(:pull_request) do
double( double(
number: 1347, number: 1347,
...@@ -100,7 +145,8 @@ describe Gitlab::GithubImport::Importer, lib: true do ...@@ -100,7 +145,8 @@ describe Gitlab::GithubImport::Importer, lib: true do
updated_at: updated_at, updated_at: updated_at,
closed_at: nil, closed_at: nil,
merged_at: nil, merged_at: nil,
url: 'https://api.github.com/repos/octocat/Hello-World/pulls/1347', url: "#{api_root}/repos/octocat/Hello-World/pulls/1347",
labels: [double(name: 'Label #2')]
) )
end end
...@@ -112,7 +158,7 @@ describe Gitlab::GithubImport::Importer, lib: true do ...@@ -112,7 +158,7 @@ describe Gitlab::GithubImport::Importer, lib: true do
draft: false, draft: false,
created_at: created_at, created_at: created_at,
updated_at: updated_at, updated_at: updated_at,
url: 'https://api.github.com/repos/octocat/Hello-World/releases/1' url: "#{api_root}/repos/octocat/Hello-World/releases/1"
) )
end end
...@@ -124,24 +170,10 @@ describe Gitlab::GithubImport::Importer, lib: true do ...@@ -124,24 +170,10 @@ describe Gitlab::GithubImport::Importer, lib: true do
draft: false, draft: false,
created_at: created_at, created_at: created_at,
updated_at: updated_at, updated_at: updated_at,
url: 'https://api.github.com/repos/octocat/Hello-World/releases/2' url: "#{api_root}/repos/octocat/Hello-World/releases/2"
) )
end end
before do
allow(project).to receive(:import_data).and_return(double.as_null_object)
allow_any_instance_of(Octokit::Client).to receive(:rate_limit!).and_raise(Octokit::NotFound)
allow_any_instance_of(Octokit::Client).to receive(:labels).and_return([label1, label2])
allow_any_instance_of(Octokit::Client).to receive(:milestones).and_return([milestone, milestone])
allow_any_instance_of(Octokit::Client).to receive(:issues).and_return([issue1, issue2])
allow_any_instance_of(Octokit::Client).to receive(:pull_requests).and_return([pull_request, pull_request])
allow_any_instance_of(Octokit::Client).to receive(:issues_comments).and_return([])
allow_any_instance_of(Octokit::Client).to receive(:pull_requests_comments).and_return([])
allow_any_instance_of(Octokit::Client).to receive(:last_response).and_return(double(rels: { next: nil }))
allow_any_instance_of(Octokit::Client).to receive(:releases).and_return([release1, release2])
allow_any_instance_of(Gitlab::Shell).to receive(:import_repository).and_raise(Gitlab::Shell::Error)
end
it 'returns true' do it 'returns true' do
expect(described_class.new(project).execute).to eq true expect(described_class.new(project).execute).to eq true
end end
...@@ -154,17 +186,67 @@ describe Gitlab::GithubImport::Importer, lib: true do ...@@ -154,17 +186,67 @@ describe Gitlab::GithubImport::Importer, lib: true do
error = { error = {
message: 'The remote data could not be fully imported.', message: 'The remote data could not be fully imported.',
errors: [ errors: [
{ type: :label, url: "https://api.github.com/repos/octocat/Hello-World/labels/bug", errors: "Validation failed: Title can't be blank, Title is invalid" }, { type: :label, url: "#{api_root}/repos/octocat/Hello-World/labels/bug", errors: "Validation failed: Title can't be blank, Title is invalid" },
{ type: :issue, url: "https://api.github.com/repos/octocat/Hello-World/issues/1348", errors: "Validation failed: Title can't be blank" }, { type: :issue, url: "#{api_root}/repos/octocat/Hello-World/issues/1348", errors: "Validation failed: Title can't be blank" },
{ type: :wiki, errors: "Gitlab::Shell::Error" }, { type: :wiki, errors: "Gitlab::Shell::Error" }
{ type: :release, url: 'https://api.github.com/repos/octocat/Hello-World/releases/2', errors: "Validation failed: Description can't be blank" }
] ]
} }
unless project.import_type == 'gitea'
error[:errors] << { type: :release, url: "#{api_root}/repos/octocat/Hello-World/releases/2", errors: "Validation failed: Description can't be blank" }
end
described_class.new(project).execute described_class.new(project).execute
expect(project.import_error).to eq error.to_json expect(project.import_error).to eq error.to_json
end end
end end
let(:project) { create(:project, import_url: "#{repo_root}/octocat/Hello-World.git", wiki_access_level: ProjectFeature::DISABLED) }
let(:credentials) { { user: 'joe' } }
context 'when importing a GitHub project' do
let(:api_root) { 'https://api.github.com' }
let(:repo_root) { 'https://github.com' }
it_behaves_like 'Gitlab::GithubImport::Importer#execute'
it_behaves_like 'Gitlab::GithubImport::Importer#execute an error occurs'
describe '#client' do
it 'instantiates a Client' do
allow(project).to receive(:import_data).and_return(double(credentials: credentials))
expect(Gitlab::GithubImport::Client).to receive(:new).with(
credentials[:user],
{}
)
described_class.new(project).client
end
end
end
context 'when importing a Gitea project' do
let(:api_root) { 'https://try.gitea.io/api/v1' }
let(:repo_root) { 'https://try.gitea.io' }
before do
project.update(import_type: 'gitea', import_url: "#{repo_root}/foo/group/project.git")
end
it_behaves_like 'Gitlab::GithubImport::Importer#execute' do
let(:expected_not_called) { [:import_releases] }
end
it_behaves_like 'Gitlab::GithubImport::Importer#execute an error occurs'
describe '#client' do
it 'instantiates a Client' do
allow(project).to receive(:import_data).and_return(double(credentials: credentials))
expect(Gitlab::GithubImport::Client).to receive(:new).with(
credentials[:user],
{ host: "#{repo_root}:443/foo", api_version: 'v1' }
)
described_class.new(project).client
end
end
end end
end end
require 'spec_helper'
describe Gitlab::GithubImport::IssuableFormatter, lib: true do
let(:raw_data) do
double(number: 42)
end
let(:project) { double(import_type: 'github') }
let(:issuable_formatter) { described_class.new(project, raw_data) }
describe '#project_association' do
it { expect { issuable_formatter.project_association }.to raise_error(NotImplementedError) }
end
describe '#number' do
it { expect(issuable_formatter.number).to eq(42) }
end
describe '#find_condition' do
it { expect(issuable_formatter.find_condition).to eq({ iid: 42 }) }
end
end
...@@ -23,9 +23,9 @@ describe Gitlab::GithubImport::IssueFormatter, lib: true do ...@@ -23,9 +23,9 @@ describe Gitlab::GithubImport::IssueFormatter, lib: true do
} }
end end
subject(:issue) { described_class.new(project, raw_data)} subject(:issue) { described_class.new(project, raw_data) }
describe '#attributes' do shared_examples 'Gitlab::GithubImport::IssueFormatter#attributes' do
context 'when issue is open' do context 'when issue is open' do
let(:raw_data) { double(base_data.merge(state: 'open')) } let(:raw_data) { double(base_data.merge(state: 'open')) }
...@@ -83,7 +83,7 @@ describe Gitlab::GithubImport::IssueFormatter, lib: true do ...@@ -83,7 +83,7 @@ describe Gitlab::GithubImport::IssueFormatter, lib: true do
end end
context 'when it has a milestone' do context 'when it has a milestone' do
let(:milestone) { double(number: 45) } let(:milestone) { double(id: 42, number: 42) }
let(:raw_data) { double(base_data.merge(milestone: milestone)) } let(:raw_data) { double(base_data.merge(milestone: milestone)) }
it 'returns nil when milestone does not exist' do it 'returns nil when milestone does not exist' do
...@@ -91,7 +91,7 @@ describe Gitlab::GithubImport::IssueFormatter, lib: true do ...@@ -91,7 +91,7 @@ describe Gitlab::GithubImport::IssueFormatter, lib: true do
end end
it 'returns milestone when it exists' do it 'returns milestone when it exists' do
milestone = create(:milestone, project: project, iid: 45) milestone = create(:milestone, project: project, iid: 42)
expect(issue.attributes.fetch(:milestone)).to eq milestone expect(issue.attributes.fetch(:milestone)).to eq milestone
end end
...@@ -118,6 +118,28 @@ describe Gitlab::GithubImport::IssueFormatter, lib: true do ...@@ -118,6 +118,28 @@ describe Gitlab::GithubImport::IssueFormatter, lib: true do
end end
end end
shared_examples 'Gitlab::GithubImport::IssueFormatter#number' do
let(:raw_data) { double(base_data.merge(number: 1347)) }
it 'returns issue number' do
expect(issue.number).to eq 1347
end
end
context 'when importing a GitHub project' do
it_behaves_like 'Gitlab::GithubImport::IssueFormatter#attributes'
it_behaves_like 'Gitlab::GithubImport::IssueFormatter#number'
end
context 'when importing a Gitea project' do
before do
project.update(import_type: 'gitea')
end
it_behaves_like 'Gitlab::GithubImport::IssueFormatter#attributes'
it_behaves_like 'Gitlab::GithubImport::IssueFormatter#number'
end
describe '#has_comments?' do describe '#has_comments?' do
context 'when number of comments is greater than zero' do context 'when number of comments is greater than zero' do
let(:raw_data) { double(base_data.merge(comments: 1)) } let(:raw_data) { double(base_data.merge(comments: 1)) }
...@@ -136,14 +158,6 @@ describe Gitlab::GithubImport::IssueFormatter, lib: true do ...@@ -136,14 +158,6 @@ describe Gitlab::GithubImport::IssueFormatter, lib: true do
end end
end end
describe '#number' do
let(:raw_data) { double(base_data.merge(number: 1347)) }
it 'returns pull request number' do
expect(issue.number).to eq 1347
end
end
describe '#pull_request?' do describe '#pull_request?' do
context 'when mention a pull request' do context 'when mention a pull request' do
let(:raw_data) { double(base_data.merge(pull_request: double)) } let(:raw_data) { double(base_data.merge(pull_request: double)) }
......
...@@ -6,7 +6,6 @@ describe Gitlab::GithubImport::MilestoneFormatter, lib: true do ...@@ -6,7 +6,6 @@ describe Gitlab::GithubImport::MilestoneFormatter, lib: true do
let(:updated_at) { DateTime.strptime('2011-01-27T19:01:12Z') } let(:updated_at) { DateTime.strptime('2011-01-27T19:01:12Z') }
let(:base_data) do let(:base_data) do
{ {
number: 1347,
state: 'open', state: 'open',
title: '1.0', title: '1.0',
description: 'Version 1.0', description: 'Version 1.0',
...@@ -16,12 +15,15 @@ describe Gitlab::GithubImport::MilestoneFormatter, lib: true do ...@@ -16,12 +15,15 @@ describe Gitlab::GithubImport::MilestoneFormatter, lib: true do
closed_at: nil closed_at: nil
} }
end end
let(:iid_attr) { :number }
subject(:formatter) { described_class.new(project, raw_data)} subject(:formatter) { described_class.new(project, raw_data) }
shared_examples 'Gitlab::GithubImport::MilestoneFormatter#attributes' do
let(:data) { base_data.merge(iid_attr => 1347) }
describe '#attributes' do
context 'when milestone is open' do context 'when milestone is open' do
let(:raw_data) { double(base_data.merge(state: 'open')) } let(:raw_data) { double(data.merge(state: 'open')) }
it 'returns formatted attributes' do it 'returns formatted attributes' do
expected = { expected = {
...@@ -40,7 +42,7 @@ describe Gitlab::GithubImport::MilestoneFormatter, lib: true do ...@@ -40,7 +42,7 @@ describe Gitlab::GithubImport::MilestoneFormatter, lib: true do
end end
context 'when milestone is closed' do context 'when milestone is closed' do
let(:raw_data) { double(base_data.merge(state: 'closed')) } let(:raw_data) { double(data.merge(state: 'closed')) }
it 'returns formatted attributes' do it 'returns formatted attributes' do
expected = { expected = {
...@@ -60,7 +62,7 @@ describe Gitlab::GithubImport::MilestoneFormatter, lib: true do ...@@ -60,7 +62,7 @@ describe Gitlab::GithubImport::MilestoneFormatter, lib: true do
context 'when milestone has a due date' do context 'when milestone has a due date' do
let(:due_date) { DateTime.strptime('2011-01-28T19:01:12Z') } let(:due_date) { DateTime.strptime('2011-01-28T19:01:12Z') }
let(:raw_data) { double(base_data.merge(due_on: due_date)) } let(:raw_data) { double(data.merge(due_on: due_date)) }
it 'returns formatted attributes' do it 'returns formatted attributes' do
expected = { expected = {
...@@ -78,4 +80,17 @@ describe Gitlab::GithubImport::MilestoneFormatter, lib: true do ...@@ -78,4 +80,17 @@ describe Gitlab::GithubImport::MilestoneFormatter, lib: true do
end end
end end
end end
context 'when importing a GitHub project' do
it_behaves_like 'Gitlab::GithubImport::MilestoneFormatter#attributes'
end
context 'when importing a Gitea project' do
let(:iid_attr) { :id }
before do
project.update(import_type: 'gitea')
end
it_behaves_like 'Gitlab::GithubImport::MilestoneFormatter#attributes'
end
end end
...@@ -32,9 +32,9 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do ...@@ -32,9 +32,9 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do
} }
end end
subject(:pull_request) { described_class.new(project, raw_data)} subject(:pull_request) { described_class.new(project, raw_data) }
describe '#attributes' do shared_examples 'Gitlab::GithubImport::PullRequestFormatter#attributes' do
context 'when pull request is open' do context 'when pull request is open' do
let(:raw_data) { double(base_data.merge(state: 'open')) } let(:raw_data) { double(base_data.merge(state: 'open')) }
...@@ -149,7 +149,7 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do ...@@ -149,7 +149,7 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do
end end
context 'when it has a milestone' do context 'when it has a milestone' do
let(:milestone) { double(number: 45) } let(:milestone) { double(id: 42, number: 42) }
let(:raw_data) { double(base_data.merge(milestone: milestone)) } let(:raw_data) { double(base_data.merge(milestone: milestone)) }
it 'returns nil when milestone does not exist' do it 'returns nil when milestone does not exist' do
...@@ -157,22 +157,22 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do ...@@ -157,22 +157,22 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do
end end
it 'returns milestone when it exists' do it 'returns milestone when it exists' do
milestone = create(:milestone, project: project, iid: 45) milestone = create(:milestone, project: project, iid: 42)
expect(pull_request.attributes.fetch(:milestone)).to eq milestone expect(pull_request.attributes.fetch(:milestone)).to eq milestone
end end
end end
end end
describe '#number' do shared_examples 'Gitlab::GithubImport::PullRequestFormatter#number' do
let(:raw_data) { double(base_data.merge(number: 1347)) } let(:raw_data) { double(base_data) }
it 'returns pull request number' do it 'returns pull request number' do
expect(pull_request.number).to eq 1347 expect(pull_request.number).to eq 1347
end end
end end
describe '#source_branch_name' do shared_examples 'Gitlab::GithubImport::PullRequestFormatter#source_branch_name' do
context 'when source branch exists' do context 'when source branch exists' do
let(:raw_data) { double(base_data) } let(:raw_data) { double(base_data) }
...@@ -190,7 +190,7 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do ...@@ -190,7 +190,7 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do
end end
end end
describe '#target_branch_name' do shared_examples 'Gitlab::GithubImport::PullRequestFormatter#target_branch_name' do
context 'when source branch exists' do context 'when source branch exists' do
let(:raw_data) { double(base_data) } let(:raw_data) { double(base_data) }
...@@ -208,6 +208,24 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do ...@@ -208,6 +208,24 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do
end end
end end
context 'when importing a GitHub project' do
it_behaves_like 'Gitlab::GithubImport::PullRequestFormatter#attributes'
it_behaves_like 'Gitlab::GithubImport::PullRequestFormatter#number'
it_behaves_like 'Gitlab::GithubImport::PullRequestFormatter#source_branch_name'
it_behaves_like 'Gitlab::GithubImport::PullRequestFormatter#target_branch_name'
end
context 'when importing a Gitea project' do
before do
project.update(import_type: 'gitea')
end
it_behaves_like 'Gitlab::GithubImport::PullRequestFormatter#attributes'
it_behaves_like 'Gitlab::GithubImport::PullRequestFormatter#number'
it_behaves_like 'Gitlab::GithubImport::PullRequestFormatter#source_branch_name'
it_behaves_like 'Gitlab::GithubImport::PullRequestFormatter#target_branch_name'
end
describe '#valid?' do describe '#valid?' do
context 'when source, and target repos are not a fork' do context 'when source, and target repos are not a fork' do
let(:raw_data) { double(base_data) } let(:raw_data) { double(base_data) }
......
...@@ -75,7 +75,6 @@ describe Import::GiteaController, 'routing' do ...@@ -75,7 +75,6 @@ describe Import::GiteaController, 'routing' do
it 'to #personal_access_token' do it 'to #personal_access_token' do
expect(post('/import/gitea/personal_access_token')).to route_to('import/gitea#personal_access_token') expect(post('/import/gitea/personal_access_token')).to route_to('import/gitea#personal_access_token')
end end
end end
# status_import_gitlab GET /import/gitlab/status(.:format) import/gitlab#status # status_import_gitlab GET /import/gitlab/status(.:format) import/gitlab#status
......
...@@ -82,7 +82,7 @@ shared_examples 'a GitHub-ish import controller: GET status' do ...@@ -82,7 +82,7 @@ shared_examples 'a GitHub-ish import controller: GET status' do
expect(session[:access_token]).to eq(nil) expect(session[:access_token]).to eq(nil)
expect(controller).to redirect_to(new_import_url) expect(controller).to redirect_to(new_import_url)
expect(flash[:alert]).to eq("Access denied to your #{Gitlab::ImportSources.options.key(provider.to_s)} account.") expect(flash[:alert]).to eq("Access denied to your #{Gitlab::ImportSources.title(provider.to_s)} account.")
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment