diff options
author | Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> | 2015-04-08 13:55:01 +0000 |
---|---|---|
committer | Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> | 2015-04-08 13:55:01 +0000 |
commit | e91a2cf15942af6e90b736eb5d9e2d994f4a023f (patch) | |
tree | 16c153cfa5ea224f665b9c1c21a9c716e37c7d20 | |
parent | 306ac71b7f7fdf710eaf8e3d5d8be0803f7d3b88 (diff) | |
parent | b13c8b91bc3441e6012c5dd249f4689e0ae94704 (diff) | |
download | gitlab-ci-e91a2cf15942af6e90b736eb5d9e2d994f4a023f.tar.gz |
Merge branch 'fork_support' into 'master'
Support for forks
https://dev.gitlab.org/gitlab/gitlab-ci/issues/187
!!! GitLab side MR - https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/499
See merge request !56
-rw-r--r-- | app/models/project.rb | 8 | ||||
-rw-r--r-- | app/services/create_project_service.rb | 20 | ||||
-rw-r--r-- | doc/api/README.md | 1 | ||||
-rw-r--r-- | doc/api/forks.md | 23 | ||||
-rw-r--r-- | lib/api/api.rb | 1 | ||||
-rw-r--r-- | lib/api/forks.rb | 38 | ||||
-rw-r--r-- | spec/models/project_spec.rb | 5 | ||||
-rw-r--r-- | spec/requests/api/forks_spec.rb | 66 | ||||
-rw-r--r-- | spec/services/create_project_service_spec.rb | 18 | ||||
-rw-r--r-- | spec/support/stub_gitlab_calls.rb | 7 |
10 files changed, 181 insertions, 6 deletions
diff --git a/app/models/project.rb b/app/models/project.rb index c931c50..4351da1 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -74,8 +74,12 @@ ls -la 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, diff --git a/app/services/create_project_service.rb b/app/services/create_project_service.rb index 1d99330..e5f9440 100644 --- a/app/services/create_project_service.rb +++ b/app/services/create_project_service.rb @@ -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 @@ -13,13 +13,25 @@ class CreateProjectService 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 diff --git a/doc/api/README.md b/doc/api/README.md index 9e3a868..95fe2f8 100644 --- a/doc/api/README.md +++ b/doc/api/README.md @@ -6,6 +6,7 @@ - [Runners](runners.md) - [Commits](commits.md) - [Builds](builds.md) +- [Forks](forks.md) ## Authentication diff --git a/doc/api/forks.md b/doc/api/forks.md new file mode 100644 index 0000000..1a5ea80 --- /dev/null +++ b/doc/api/forks.md @@ -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) diff --git a/lib/api/api.rb b/lib/api/api.rb index a969e4b..d1127ed 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -29,5 +29,6 @@ module API mount Commits mount Runners mount Projects + mount Forks end end diff --git a/lib/api/forks.rb b/lib/api/forks.rb new file mode 100644 index 0000000..92f232c --- /dev/null +++ b/lib/api/forks.rb @@ -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 diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 28ccca7..482a401 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -133,6 +133,11 @@ describe Project do 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 diff --git a/spec/requests/api/forks_spec.rb b/spec/requests/api/forks_spec.rb new file mode 100644 index 0000000..e0469db --- /dev/null +++ b/spec/requests/api/forks_spec.rb @@ -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 diff --git a/spec/services/create_project_service_spec.rb b/spec/services/create_project_service_spec.rb index 7046830..6ecb93e 100644 --- a/spec/services/create_project_service_spec.rb +++ b/spec/services/create_project_service_spec.rb @@ -20,5 +20,23 @@ describe CreateProjectService do 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 diff --git a/spec/support/stub_gitlab_calls.rb b/spec/support/stub_gitlab_calls.rb index 6c047ec..3058d03 100644 --- a/spec/support/stub_gitlab_calls.rb +++ b/spec/support/stub_gitlab_calls.rb @@ -7,6 +7,7 @@ module StubGitlabCalls stub_project_8_hooks stub_projects stub_projects_owned + stub_ci_enable end def stub_js_gitlab_calls @@ -73,6 +74,12 @@ module StubGitlabCalls 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 |