summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorValery Sizov <vsv2711@gmail.com>2015-03-03 13:34:40 +0200
committerValery Sizov <vsv2711@gmail.com>2015-03-03 13:34:40 +0200
commite3b2180e57e677ab9e263200645a32d24b5147eb (patch)
treeec445f15052614e2b29b96926a12bf3b074ddd1f
parent83835d271fa8fb04fae5c422afeacfba6f061629 (diff)
parenteb24743b70b1ae57002d8c40aadb87c10e7a8993 (diff)
downloadgitlab-ci-e3b2180e57e677ab9e263200645a32d24b5147eb.tar.gz
Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ci
-rw-r--r--.hound.yml4
-rw-r--r--CHANGELOG2
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock10
-rw-r--r--app/controllers/application_controller.rb10
-rw-r--r--app/controllers/helps_controller.rb6
-rw-r--r--app/views/helps/oauth2.html.haml4
-rwxr-xr-xbin/bundle3
-rwxr-xr-xbin/rails8
-rwxr-xr-xbin/rake8
-rwxr-xr-xbin/rspec7
-rwxr-xr-xbin/spring15
-rw-r--r--doc/api/projects.md40
-rw-r--r--lib/api/entities.rb4
-rw-r--r--lib/api/projects.rb74
-rw-r--r--lib/upgrader.rb7
-rw-r--r--spec/lib/upgrader_spec.rb8
-rw-r--r--spec/requests/api/projects_spec.rb160
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
diff --git a/CHANGELOG b/CHANGELOG
index 7a46008..380e3b0 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -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
diff --git a/Gemfile b/Gemfile
index 0e7a3d7..a52ecf5 100644
--- a/Gemfile
+++ b/Gemfile
@@ -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"
}
}