Skip to content
This repository has been archived by the owner on May 12, 2018. It is now read-only.

Commit

Permalink
Merge branch 'fork_support' into 'master'
Browse files Browse the repository at this point in the history
  • Loading branch information
dzaporozhets committed Apr 8, 2015
2 parents 306ac71 + b13c8b9 commit e91a2cf
Show file tree
Hide file tree
Showing 10 changed files with 181 additions and 6 deletions.
8 changes: 6 additions & 2 deletions app/models/project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,12 @@ def base_build_script
eos
end

def parse(project_yaml)
project = YAML.load(project_yaml)
def parse(project_params)
project = if project_params.is_a?(String)
YAML.load(project_params)
else
project_params
end

params = {
name: project.name_with_namespace,
Expand Down
20 changes: 16 additions & 4 deletions app/services/create_project_service.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
class CreateProjectService
include Rails.application.routes.url_helpers

def execute(current_user, params, project_route)
def execute(current_user, params, project_route, forked_project = nil)
@project = Project.parse(params)

Project.transaction do
Expand All @@ -13,13 +13,25 @@ def execute(current_user, params, project_route)
project_url: project_route.gsub(":project_id", @project.id.to_s),
}

if Network.new.enable_ci(current_user.url, @project.gitlab_id, opts, current_user.private_token)
true
else
unless Network.new.enable_ci(current_user.url, @project.gitlab_id, opts, current_user.private_token)
raise ActiveRecord::Rollback
end
end

if forked_project
# Copy jobs
@project.jobs = forked_project.jobs.map do |job|
Job.new(job.attributes)
end

# Copy settings
settings = forked_project.attributes.select do |attr_name, value|
["public", "shared_runners_enabled", "allow_git_fetch"].include? attr_name
end

@project.update(settings)
end

EventService.new.create_project(current_user, @project)

@project
Expand Down
1 change: 1 addition & 0 deletions doc/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- [Runners](runners.md)
- [Commits](commits.md)
- [Builds](builds.md)
- [Forks](forks.md)


## Authentication
Expand Down
23 changes: 23 additions & 0 deletions doc/api/forks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Forks API

This API is intended to aid in the setup and configuration of
forked projects on Gitlab CI.

__Authentication is done by GitLab user token & GitLab project token__

## Forks

### Create fork for project



```
POST /forks
```

Parameters:

project_id (required) - The ID of a project
project_token (requires) - Project token
private_token(required) - User private token
data (required) - GitLab project data (name_with_namespace, web_url, default_branch, ssh_url_to_repo)
1 change: 1 addition & 0 deletions lib/api/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ class API < Grape::API
mount Commits
mount Runners
mount Projects
mount Forks
end
end
38 changes: 38 additions & 0 deletions lib/api/forks.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
module API
class Forks < Grape::API
resource :forks do
# Create a fork
#
# Parameters:
# project_id (required) - The ID of a project
# project_token (requires) - Project token
# private_token(required) - User private token
# data (required) - GitLab project data (name_with_namespace, web_url, default_branch, ssh_url_to_repo)
#
#
# Example Request:
# POST /forks
post do
required_attributes! [:project_id, :data, :project_token, :private_token]
project = Project.find_by!(gitlab_id: params[:project_id])
authenticate_project_token!(project)

user_session = UserSession.new
user = user_session.authenticate_by_token(private_token: params[:private_token], url: GitlabCi.config.gitlab_server.url)

fork = CreateProjectService.new.execute(
user,
params[:data],
RoutesHelper.project_url(":project_id"),
project
)

if fork
present fork, with: Entities::Project
else
not_found!
end
end
end
end
end
5 changes: 5 additions & 0 deletions spec/models/project_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@
it { parsed_project.name.should eq("GitLab / api.gitlab.org") }
it { parsed_project.gitlab_id.should eq(189) }
it { parsed_project.gitlab_url.should eq("http://localhost:3000/gitlab/api-gitlab-org") }

it "parses plain hash" do
data = YAML.load(project_dump)
Project.parse(data).name.should eq("GitLab / api.gitlab.org")
end
end

describe :repo_url_with_auth do
Expand Down
66 changes: 66 additions & 0 deletions spec/requests/api/forks_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
require 'spec_helper'

describe API::API do
include ApiHelpers

let(:project) { FactoryGirl.create(:project) }
let(:gitlab_url) { GitlabCi.config.gitlab_server.url }
let(:auth_opts) {
{
email: "test@test.com",
password: "123456"
}
}
let(:private_token) { Network.new.authenticate(gitlab_url, auth_opts)["private_token"] }

let(:options) {
{
private_token: private_token,
url: gitlab_url
}
}

before {
stub_gitlab_calls
}


describe "POST /forks" do
let(:project_info) {
{
project_id: project.gitlab_id,
project_token: project.token,
data: {
id: 2,
name_with_namespace: "Gitlab.org / Underscore",
web_url: "http://example.com/gitlab-org/underscore",
default_branch: "master",
ssh_url_to_repo: "git@example.com:gitlab-org/underscore"
}
}
}

context "with valid info" do
before do
options.merge!(project_info)
end

it "should create a project with valid data" do
post api("/forks"), options
response.status.should == 201
json_response['name'].should == "Gitlab.org / Underscore"
end
end

context "with invalid project info" do
before do
options.merge!({})
end

it "should error with invalid data" do
post api("/forks"), options
response.status.should == 400
end
end
end
end
18 changes: 18 additions & 0 deletions spec/services/create_project_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,23 @@
expect { service.execute(current_user, '', '') }.to raise_error
end
end

context "forking" do
it "uses project as a template for settings and jobs" do
origin_project = FactoryGirl.create(:project)
origin_project.jobs << Job.new(commands: "pwd")
origin_project.shared_runners_enabled = true
origin_project.public = true
origin_project.allow_git_fetch = true
origin_project.save!

project = service.execute(current_user, project_dump, 'http://localhost/projects/:project_id', origin_project)

project.shared_runners_enabled.should be_true
project.public.should be_true
project.allow_git_fetch.should be_true
project.jobs.last.commands.should == "pwd"
end
end
end
end
7 changes: 7 additions & 0 deletions spec/support/stub_gitlab_calls.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ def stub_gitlab_calls
stub_project_8_hooks
stub_projects
stub_projects_owned
stub_ci_enable
end

def stub_js_gitlab_calls
Expand Down Expand Up @@ -73,6 +74,12 @@ def stub_projects_owned
to_return(:status => 200, :body => "", :headers => {})
end

def stub_ci_enable
stub_request(:put, "#{gitlab_url}api/v3/projects/2/services/gitlab-ci.json?private_token=Wvjy2Krpb7y8xi93owUz").
with(:headers => {'Content-Type'=>'application/json'}).
to_return(:status => 200, :body => "", :headers => {})
end

def project_hash_array
f = File.read(Rails.root.join('spec/support/gitlab_stubs/projects.json'))
return JSON.parse f
Expand Down

0 comments on commit e91a2cf

Please sign in to comment.