diff options
author | Valery Sizov <vsv2711@gmail.com> | 2015-03-03 13:34:40 +0200 |
---|---|---|
committer | Valery Sizov <vsv2711@gmail.com> | 2015-03-03 13:34:40 +0200 |
commit | e3b2180e57e677ab9e263200645a32d24b5147eb (patch) | |
tree | ec445f15052614e2b29b96926a12bf3b074ddd1f | |
parent | 83835d271fa8fb04fae5c422afeacfba6f061629 (diff) | |
parent | eb24743b70b1ae57002d8c40aadb87c10e7a8993 (diff) | |
download | gitlab-ci-e3b2180e57e677ab9e263200645a32d24b5147eb.tar.gz |
Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ci
-rw-r--r-- | .hound.yml | 4 | ||||
-rw-r--r-- | CHANGELOG | 2 | ||||
-rw-r--r-- | Gemfile | 2 | ||||
-rw-r--r-- | Gemfile.lock | 10 | ||||
-rw-r--r-- | app/controllers/application_controller.rb | 10 | ||||
-rw-r--r-- | app/controllers/helps_controller.rb | 6 | ||||
-rw-r--r-- | app/views/helps/oauth2.html.haml | 4 | ||||
-rwxr-xr-x | bin/bundle | 3 | ||||
-rwxr-xr-x | bin/rails | 8 | ||||
-rwxr-xr-x | bin/rake | 8 | ||||
-rwxr-xr-x | bin/rspec | 7 | ||||
-rwxr-xr-x | bin/spring | 15 | ||||
-rw-r--r-- | doc/api/projects.md | 40 | ||||
-rw-r--r-- | lib/api/entities.rb | 4 | ||||
-rw-r--r-- | lib/api/projects.rb | 74 | ||||
-rw-r--r-- | lib/upgrader.rb | 7 | ||||
-rw-r--r-- | spec/lib/upgrader_spec.rb | 8 | ||||
-rw-r--r-- | spec/requests/api/projects_spec.rb | 160 |
18 files changed, 349 insertions, 23 deletions
diff --git a/.hound.yml b/.hound.yml new file mode 100644 index 0000000..3bde29f --- /dev/null +++ b/.hound.yml @@ -0,0 +1,4 @@ +# Prefer single quotes +StringLiterals: + EnforcedStyle: single_quotes + Enabled: true @@ -14,6 +14,8 @@ v7.8.0 - Disable turbolink on links pointing out to GitLab server - Add test coverage parsing example for pytest-cov - Upgrade raindrops gem + - Allow to pass description and tag list during Runner's registration + - Added api for project jobs v5.4.2 - Fix exposure of project token via build data @@ -87,6 +87,7 @@ group :development do gem 'annotate' gem 'quiet_assets' gem "letter_opener" + gem "spring-commands-rspec" end @@ -97,6 +98,7 @@ group :development, :test do gem 'poltergeist' gem 'factory_girl_rails' gem "ffaker" + gem "byebug" gem 'shoulda-matchers' gem 'guard-rspec' diff --git a/Gemfile.lock b/Gemfile.lock index c98e681..979c046 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -45,6 +45,9 @@ GEM bootstrap-sass (3.0.3.0) sass (~> 3.2) builder (3.1.4) + byebug (3.2.0) + columnize (~> 0.8) + debugger-linecache (~> 1.2) capybara (2.1.0) mime-types (>= 1.16) nokogiri (>= 1.3.3) @@ -65,6 +68,7 @@ GEM coffee-script-source execjs coffee-script-source (1.6.3) + columnize (0.9.0) connection_pool (1.2.0) coveralls (0.7.0) multi_json (~> 1.3) @@ -74,6 +78,7 @@ GEM thor crack (0.4.1) safe_yaml (~> 0.9.0) + debugger-linecache (1.2.0) default_value_for (3.0.0.1) activerecord (>= 3.2.0, < 5.0) descendants_tracker (0.0.4) @@ -287,6 +292,9 @@ GEM temple (~> 0.6.6) tilt (>= 1.3.3, < 2.1) slop (3.4.7) + spring (1.3.3) + spring-commands-rspec (1.0.4) + spring (>= 0.9.1) sprockets (2.11.0) hike (~> 1.2) multi_json (~> 1.0) @@ -343,6 +351,7 @@ DEPENDENCIES acts-as-taggable-on (~> 3.4) annotate bootstrap-sass (~> 3.0) + byebug capybara coffee-rails (~> 4.0.0) coveralls @@ -388,6 +397,7 @@ DEPENDENCIES sinatra slack-notifier (~> 1.0.0) slim + spring-commands-rspec stamp state_machine therubyracer diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 87d59d6..0c8180e 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -71,13 +71,19 @@ class ApplicationController < ActionController::Base end def check_config + redirect_to oauth2_help_path unless valid_config? + end + + def valid_config? server = GitlabCi.config.gitlab_server if server.blank? || server.url.blank? || server.app_id.blank? || server.app_secret.blank? - redirect_to oauth2_help_path + false + else + true end rescue Settingslogic::MissingSetting, NoMethodError - redirect_to oauth2_help_path + false end def invalid_token diff --git a/app/controllers/helps_controller.rb b/app/controllers/helps_controller.rb index b1885b2..6fc46ef 100644 --- a/app/controllers/helps_controller.rb +++ b/app/controllers/helps_controller.rb @@ -5,6 +5,10 @@ class HelpsController < ApplicationController end def oauth2 - render layout: "empty" + if valid_config? + redirect_to root_path + else + render layout: 'empty' + end end end diff --git a/app/views/helps/oauth2.html.haml b/app/views/helps/oauth2.html.haml index c79380a..fe9802f 100644 --- a/app/views/helps/oauth2.html.haml +++ b/app/views/helps/oauth2.html.haml @@ -12,5 +12,9 @@ %code= callback_user_sessions_url %li Update the GitLab CI config with the application id and the application secret from GitLab. + %li + Restart your GitLab CI instance + %li + Refresh this page when GitLab CI has started again diff --git a/bin/bundle b/bin/bundle new file mode 100755 index 0000000..66e9889 --- /dev/null +++ b/bin/bundle @@ -0,0 +1,3 @@ +#!/usr/bin/env ruby +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +load Gem.bin_path('bundler', 'bundle') diff --git a/bin/rails b/bin/rails new file mode 100755 index 0000000..7feb6a3 --- /dev/null +++ b/bin/rails @@ -0,0 +1,8 @@ +#!/usr/bin/env ruby +begin + load File.expand_path("../spring", __FILE__) +rescue LoadError +end +APP_PATH = File.expand_path('../../config/application', __FILE__) +require_relative '../config/boot' +require 'rails/commands' diff --git a/bin/rake b/bin/rake new file mode 100755 index 0000000..8017a02 --- /dev/null +++ b/bin/rake @@ -0,0 +1,8 @@ +#!/usr/bin/env ruby +begin + load File.expand_path("../spring", __FILE__) +rescue LoadError +end +require_relative '../config/boot' +require 'rake' +Rake.application.run diff --git a/bin/rspec b/bin/rspec new file mode 100755 index 0000000..20060eb --- /dev/null +++ b/bin/rspec @@ -0,0 +1,7 @@ +#!/usr/bin/env ruby +begin + load File.expand_path("../spring", __FILE__) +rescue LoadError +end +require 'bundler/setup' +load Gem.bin_path('rspec-core', 'rspec') diff --git a/bin/spring b/bin/spring new file mode 100755 index 0000000..7b45d37 --- /dev/null +++ b/bin/spring @@ -0,0 +1,15 @@ +#!/usr/bin/env ruby + +# This file loads spring without using Bundler, in order to be fast. +# It gets overwritten when you run the `spring binstub` command. + +unless defined?(Spring) + require "rubygems" + require "bundler" + + if match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m) + Gem.paths = { "GEM_PATH" => [Bundler.bundle_path.to_s, *Gem.path].uniq } + gem "spring", match[1] + require "spring/binstub" + end +end diff --git a/doc/api/projects.md b/doc/api/projects.md index 61514b8..dae4591 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -150,3 +150,43 @@ Parameters: * `id` (required) - The ID of the Gitlab CI project * `runner_id` (required) - The ID of the Gitlab CI runner +### List All Jobs for a Project + +List the jobs associated to a Gitlab CI Project (only via +authorized user). + + GET /projects/:id/jobs + +Parameters: + + * `id` (required) - The ID of the Gitlab CI project + +### Add a Job to a Project + +Adds a Job to a Gitlab CI Project (only via +authorized user). + + POST /projects/:id/jobs + +Parameters: + + * `id` (required) - The ID of the Gitlab CI project + * `name` (required) - The name of the Job to add + * `commands` (required) - The script commands of the job + * `active` (optional) - The command is active of not + * `build_branches` (optional) - Trigger commit builds + * `build_tags` (optional) - Trigger tag builds + * `tags` (optional) - The tags associated with this job + +### Remove a Job from a Project + +Removes a Job from a Gitlab CI Project (only +via authorized user). + + DELETE /projects/:id/jobs/:job_id + +Parameters: + + * `id` (required) - The ID of the Gitlab CI project + * `job_id` (required) - The ID of the Job + diff --git a/lib/api/entities.rb b/lib/api/entities.rb index dfd419a..8c4b3c1 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -27,5 +27,9 @@ module API class WebHook < Grape::Entity expose :id, :project_id, :url end + + class Job < Grape::Entity + expose :id, :project_id, :commands, :active, :name, :build_branches, :build_tags, :tags + end end end diff --git a/lib/api/projects.rb b/lib/api/projects.rb index c6da7e5..c60d619 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -28,6 +28,80 @@ module API end end + # Retrieve all jobs for a project + # + # Parameters + # id (required) - The ID of a project + # Example Request + # GET /projects/:id/jobs + get ":id/jobs" do + project = Project.find(params[:id]) + + not_found! if project.blank? + unauthorized! unless current_user.can_access_project?(project.gitlab_id) + + project.jobs + end + + # Add a new job to a project + # + # Parameters + # id (required) - The ID of a project + # name (required) - The job name + # commands (required) - The command line script for the job + # active (optional) - The command is active of not + # build_branches (optional) - Trigger commit builds + # build_tags (optional) - Trigger tag builds + # tags (optional) - The tags associated with this job + # Example Request + # POST /projects/:id/jobs + post ":id/jobs" do + required_attributes! [:name, :commands] + + project = Project.find(params[:id]) + + not_found! if project.blank? + unauthorized! unless current_user.can_access_project?(project.gitlab_id) + + job_params = + { + name: params[:name], + commands: params[:commands], + } + + job_params[:active] = params[:active] unless params[:active].nil? + job_params[:build_branches] = params[:build_branches] unless params[:build_branches].nil? + job_params[:build_tags] = params[:build_tags] unless params[:build_tags].nil? + job_params[:tag_list] = params[:tags] unless params[:tags].nil? + + job = project.jobs.new(job_params) + if job.save + present job, with: Entities::Job + else + errors = job.errors.full_messages.join(", ") + render_api_error!(errors, 400) + end + end + + # Delete a job for a project + # + # Parameters + # id (required) - The ID of a project + # job_id (required) - The ID of the job to delete + # Example Request + # DELETE /projects/:id/jobs/:job_id + delete ":id/jobs/:job_id" do + required_attributes! [:job_id] + + project = Project.find(params[:id]) + job = project.jobs.find(params[:job_id]) + + not_found! if project.blank? || job.blank? + unauthorized! unless current_user.can_access_project?(project.gitlab_id) + + job.destroy + end + # Retrieve all Gitlab CI projects that the user has access to # # Example Request: diff --git a/lib/upgrader.rb b/lib/upgrader.rb index 3dff6a8..3969fa2 100644 --- a/lib/upgrader.rb +++ b/lib/upgrader.rb @@ -41,8 +41,6 @@ class Upgrader end def latest_version_raw - git_tags = `git ls-remote --tags origin | grep tags\/v#{current_version.major}` - git_tags = git_tags.lines.to_a.select { |version| version =~ /v\d\.\d\.\d\Z/ } last_tag = git_tags.last.match(/v\d\.\d\.\d/).to_s end @@ -91,4 +89,9 @@ class Upgrader end while !choices.include?(answer) answer end + + def git_tags + tags = `git ls-remote --tags origin | grep tags\/v#{current_version.major}` + tags.lines.to_a.select { |version| version =~ /v\d\.\d\.\d\Z/ } + end end diff --git a/spec/lib/upgrader_spec.rb b/spec/lib/upgrader_spec.rb index 9674907..b37d0e4 100644 --- a/spec/lib/upgrader_spec.rb +++ b/spec/lib/upgrader_spec.rb @@ -16,9 +16,11 @@ describe Upgrader do end describe 'latest_version_raw' do - it 'should be latest version for GitLab 5' do - upgrader.stub(current_version_raw: "3.0.0") - upgrader.latest_version_raw.should == "v3.2.0" + it 'should be latest version for GitLab' do + upgrader.stub(current_version_raw: '3.0.0') + upgrader.stub(git_tags: [ + '1b5bee25b51724214c7a3307ef94027ab93ec982 refs/tags/v7.8.1']) + upgrader.latest_version_raw.should == 'v7.8.1' end end end diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 1209855..03d704b 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -6,16 +6,16 @@ describe API::API do let(:gitlab_url) { GitlabCi.config.gitlab_server.url } let(:auth_opts) { { - :email => "test@test.com", - :password => "123456" + 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 + private_token: private_token, + url: gitlab_url } } @@ -26,8 +26,8 @@ describe API::API do context "requests for scoped projects" do # NOTE: These ids are tied to the actual projects on demo.gitlab.com describe "GET /projects" do - let!(:project1) { FactoryGirl.create(:project, :name => "gitlabhq", :gitlab_id => 3) } - let!(:project2) { FactoryGirl.create(:project, :name => "gitlab-ci", :gitlab_id => 4) } + let!(:project1) { FactoryGirl.create(:project, name: "gitlabhq", gitlab_id: 3) } + let!(:project2) { FactoryGirl.create(:project, name: "gitlab-ci", gitlab_id: 4) } it "should return all projects on the CI instance" do get api("/projects"), options @@ -40,8 +40,8 @@ describe API::API do describe "GET /projects/owned" do # NOTE: This user doesn't own any of these projects on demo.gitlab.com - let!(:project1) { FactoryGirl.create(:project, :name => "gitlabhq", :gitlab_id => 3) } - let!(:project2) { FactoryGirl.create(:project, :name => "random-project", :gitlab_id => 9898) } + let!(:project1) { FactoryGirl.create(:project, name: "gitlabhq", gitlab_id: 3) } + let!(:project2) { FactoryGirl.create(:project, name: "random-project", gitlab_id: 9898) } it "should return all projects on the CI instance" do get api("/projects/owned"), options @@ -52,11 +52,141 @@ describe API::API do end end + describe "POST /projects/:project_id/jobs" do + let!(:project) { FactoryGirl.create(:project) } + + let(:job_info) { + { + name: "A Job Name", + commands: "ls -lad", + active: false, + build_branches: false, + build_tags: true, + tags: "release, deployment", + } + } + let(:invalid_job_info) { {} } + + context "Invalid Job Info" do + before do + options.merge!(invalid_job_info) + end + + it "should error with invalid data" do + post api("/projects/#{project.id}/jobs"), options + response.status.should == 400 + end + end + + context "Valid Job Info" do + before do + options.merge!(job_info) + end + + it "should create a job for specified project" do + post api("/projects/#{project.id}/jobs"), options + response.status.should == 201 + json_response["name"].should == job_info[:name] + json_response["commands"].should == job_info[:commands] + json_response["active"].should == job_info[:active] + json_response["build_branches"].should == job_info[:build_branches] + json_response["build_tags"].should == job_info[:build_tags] + json_response["tags"].should have(2).items + end + + it "fails to create job for non existsing project" do + post api("/projects/non-existant-id/jobs"), options + response.status.should == 404 + end + end + end + + describe "GET /projects/:project_id/jobs" do + let!(:project) { FactoryGirl.create(:project) } + let(:job_info) { + { + name: "A Job Name", + commands: "ls -lad", + } + } + + before do + options.merge!(job_info) + end + + it "should list the project's jobs" do + get api("/projects/#{project.id}/jobs"), options + response.status.should == 200 + json_response.count.should == 1 + json_response.first["project_id"].should == project.id + end + + it "should delete default job, add & list the project's new jobs" do + # delete default job + get api("/projects/#{project.id}/jobs"), options + response.status.should == 200 + json_response.count.should == 1 + job_id = json_response.first["id"] + delete api("/projects/#{project.id}/jobs/#{job_id}"), options + # add a new job + post api("/projects/#{project.id}/jobs"), options + response.status.should == 201 + # get the new job + get api("/projects/#{project.id}/jobs"), options + # assert job + response.status.should == 200 + json_response.count.should == 1 + json_response.first["project_id"].should == project.id + json_response.first["name"].should == job_info[:name] + json_response.first["commands"].should == job_info[:commands] + end + + it "fails to list jobs for non existsing project" do + get api("/projects/non-existant-id/jobs"), options + response.status.should == 404 + end + end + + describe "DELETE /projects/:id/jobs/:job_id" do + let!(:project) { FactoryGirl.create(:project) } + + let(:job_info) { + { + commands: "ls -lad", + name: "A Job Name", + } + } + + before do + options.merge!(job_info) + end + + it "should delete a project job" do + post api("/projects/#{project.id}/jobs"), options + response.status.should == 201 + json_response["name"].should == job_info[:name] + json_response["commands"].should == job_info[:commands] + job_id = json_response["id"] + delete api("/projects/#{project.id}/jobs/#{job_id}"), options + response.status.should == 200 + end + + it "fails to delete a job for a non existsing project" do + delete api("/projects/non-existant-id/jobs/non-existant-job-id"), options + response.status.should == 404 + end + + it "fails to delete a job for a non existsing job id" do + delete api("/projects/#{project.id}/jobs/non-existant-job-id"), options + response.status.should == 404 + end + end + describe "POST /projects/:project_id/webhooks" do let!(:project) { FactoryGirl.create(:project) } context "Valid Webhook URL" do - let!(:webhook) { {:web_hook => "http://example.com/sth/1/ala_ma_kota" } } + let!(:webhook) { {web_hook: "http://example.com/sth/1/ala_ma_kota" } } before do options.merge!(webhook) @@ -76,7 +206,7 @@ describe API::API do end context "Invalid Webhook URL" do - let!(:webhook) { {:web_hook => "ala_ma_kota" } } + let!(:webhook) { {web_hook: "ala_ma_kota" } } before do options.merge!(webhook) @@ -117,7 +247,7 @@ describe API::API do describe "PUT /projects/:id" do let!(:project) { FactoryGirl.create(:project) } - let!(:project_info) { {:name => "An updated name!" } } + let!(:project_info) { {name: "An updated name!" } } before do options.merge!(project_info) @@ -149,10 +279,10 @@ describe API::API do describe "POST /projects" do let(:project_info) { { - :name => "My project", - :gitlab_id => 1, - :gitlab_url => "http://example.com/testing/testing", - :ssh_url_to_repo => "ssh://example.com/testing/testing.git" + name: "My project", + gitlab_id: 1, + gitlab_url: "http://example.com/testing/testing", + ssh_url_to_repo: "ssh://example.com/testing/testing.git" } } |