Drone CI service
This commit is contained in:
parent
308c6428ae
commit
263abda3fd
15 changed files with 1037 additions and 131 deletions
|
@ -31,6 +31,9 @@ v 8.0.0 (unreleased)
|
||||||
- Don't notify users without access to the project when they are (accidentally) mentioned in a note.
|
- Don't notify users without access to the project when they are (accidentally) mentioned in a note.
|
||||||
- Retrieving oauth token with LDAP credentials
|
- Retrieving oauth token with LDAP credentials
|
||||||
- Load Application settings from running database unless env var USE_DB=false
|
- Load Application settings from running database unless env var USE_DB=false
|
||||||
|
- Added Drone CI integration (Kirill Zaitsev)
|
||||||
|
- Refactored service API and added automatically service docs generator (Kirill Zaitsev)
|
||||||
|
- Added web_url key project hook_attrs (Kirill Zaitsev)
|
||||||
|
|
||||||
v 7.14.1
|
v 7.14.1
|
||||||
- Improve abuse reports management from admin area
|
- Improve abuse reports management from admin area
|
||||||
|
|
|
@ -2,7 +2,7 @@ class Projects::ServicesController < Projects::ApplicationController
|
||||||
ALLOWED_PARAMS = [:title, :token, :type, :active, :api_key, :api_version, :subdomain,
|
ALLOWED_PARAMS = [:title, :token, :type, :active, :api_key, :api_version, :subdomain,
|
||||||
:room, :recipients, :project_url, :webhook,
|
:room, :recipients, :project_url, :webhook,
|
||||||
:user_key, :device, :priority, :sound, :bamboo_url, :username, :password,
|
:user_key, :device, :priority, :sound, :bamboo_url, :username, :password,
|
||||||
:build_key, :server, :teamcity_url, :build_type,
|
:build_key, :server, :teamcity_url, :drone_url, :build_type,
|
||||||
:description, :issues_url, :new_issue_url, :restrict_to_branch, :channel,
|
:description, :issues_url, :new_issue_url, :restrict_to_branch, :channel,
|
||||||
:colorize_messages, :channels,
|
:colorize_messages, :channels,
|
||||||
:push_events, :issues_events, :merge_requests_events, :tag_push_events,
|
:push_events, :issues_events, :merge_requests_events, :tag_push_events,
|
||||||
|
|
|
@ -73,6 +73,7 @@ class Project < ActiveRecord::Base
|
||||||
has_many :services
|
has_many :services
|
||||||
has_one :gitlab_ci_service, dependent: :destroy
|
has_one :gitlab_ci_service, dependent: :destroy
|
||||||
has_one :campfire_service, dependent: :destroy
|
has_one :campfire_service, dependent: :destroy
|
||||||
|
has_one :drone_ci_service, dependent: :destroy
|
||||||
has_one :emails_on_push_service, dependent: :destroy
|
has_one :emails_on_push_service, dependent: :destroy
|
||||||
has_one :irker_service, dependent: :destroy
|
has_one :irker_service, dependent: :destroy
|
||||||
has_one :pivotaltracker_service, dependent: :destroy
|
has_one :pivotaltracker_service, dependent: :destroy
|
||||||
|
@ -613,6 +614,7 @@ class Project < ActiveRecord::Base
|
||||||
name: name,
|
name: name,
|
||||||
ssh_url: ssh_url_to_repo,
|
ssh_url: ssh_url_to_repo,
|
||||||
http_url: http_url_to_repo,
|
http_url: http_url_to_repo,
|
||||||
|
web_url: web_url,
|
||||||
namespace: namespace.name,
|
namespace: namespace.name,
|
||||||
visibility_level: visibility_level
|
visibility_level: visibility_level
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,11 +26,23 @@ class CiService < Service
|
||||||
:ci
|
:ci
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def valid_token?(token)
|
||||||
|
self.respond_to?(:token) && self.token.present? && self.token == token
|
||||||
|
end
|
||||||
|
|
||||||
def supported_events
|
def supported_events
|
||||||
%w(push)
|
%w(push)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Return complete url to build page
|
def merge_request_page(iid, sha, ref)
|
||||||
|
commit_page(sha, ref)
|
||||||
|
end
|
||||||
|
|
||||||
|
def commit_page(sha, ref)
|
||||||
|
build_page(sha, ref)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Return complete url to merge_request page
|
||||||
#
|
#
|
||||||
# Ex.
|
# Ex.
|
||||||
# http://jenkins.example.com:8888/job/test1/scm/bySHA1/12d65c
|
# http://jenkins.example.com:8888/job/test1/scm/bySHA1/12d65c
|
||||||
|
@ -45,10 +57,27 @@ class CiService < Service
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Ex.
|
# Ex.
|
||||||
# @service.commit_status('13be4ac')
|
# @service.merge_request_status(9, '13be4ac', 'dev')
|
||||||
# # => 'success'
|
# # => 'success'
|
||||||
#
|
#
|
||||||
# @service.commit_status('2abe4ac')
|
# @service.merge_request_status(10, '2abe4ac', 'dev)
|
||||||
|
# # => 'running'
|
||||||
|
#
|
||||||
|
#
|
||||||
|
def merge_request_status(iid, sha, ref)
|
||||||
|
commit_status(sha, ref)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Return string with build status or :error symbol
|
||||||
|
#
|
||||||
|
# Allowed states: 'success', 'failed', 'running', 'pending', 'skipped'
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Ex.
|
||||||
|
# @service.commit_status('13be4ac', 'master')
|
||||||
|
# # => 'success'
|
||||||
|
#
|
||||||
|
# @service.commit_status('2abe4ac', 'dev')
|
||||||
# # => 'running'
|
# # => 'running'
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
170
app/models/project_services/drone_ci_service.rb
Normal file
170
app/models/project_services/drone_ci_service.rb
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
class DroneCiService < CiService
|
||||||
|
|
||||||
|
prop_accessor :drone_url, :token, :enable_ssl_verification
|
||||||
|
validates :drone_url,
|
||||||
|
presence: true,
|
||||||
|
format: { with: /\A#{URI.regexp(%w(http https))}\z/, message: "should be a valid url" }, if: :activated?
|
||||||
|
validates :token,
|
||||||
|
presence: true,
|
||||||
|
format: { with: /\A([A-Za-z0-9]+)\z/ }, if: :activated?
|
||||||
|
|
||||||
|
after_save :compose_service_hook, if: :activated?
|
||||||
|
|
||||||
|
def compose_service_hook
|
||||||
|
hook = service_hook || build_service_hook
|
||||||
|
hook.url = [drone_url, "/api/hook", "?owner=#{project.namespace.path}", "&name=#{project.path}", "&access_token=#{token}"].join
|
||||||
|
hook.enable_ssl_verification = enable_ssl_verification
|
||||||
|
hook.save
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute(data)
|
||||||
|
case data[:object_kind]
|
||||||
|
when 'push'
|
||||||
|
service_hook.execute(data) if push_valid?(data)
|
||||||
|
when 'merge_request'
|
||||||
|
service_hook.execute(data) if merge_request_valid?(data)
|
||||||
|
when 'tag_push'
|
||||||
|
service_hook.execute(data) if tag_push_valid?(data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def allow_target_ci?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def supported_events
|
||||||
|
%w(push merge_request tag_push)
|
||||||
|
end
|
||||||
|
|
||||||
|
def merge_request_status_path(iid, sha = nil, ref = nil)
|
||||||
|
url = [drone_url,
|
||||||
|
"gitlab/#{project.namespace.path}/#{project.path}/pulls/#{iid}",
|
||||||
|
"?access_token=#{token}"]
|
||||||
|
|
||||||
|
URI.join(*url).to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def commit_status_path(sha, ref)
|
||||||
|
url = [drone_url,
|
||||||
|
"gitlab/#{project.namespace.path}/#{project.path}/commits/#{sha}",
|
||||||
|
"?branch=#{URI::encode(ref.to_s)}&access_token=#{token}"]
|
||||||
|
|
||||||
|
URI.join(*url).to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def merge_request_status(iid, sha, ref)
|
||||||
|
response = HTTParty.get(merge_request_status_path(iid), verify: enable_ssl_verification)
|
||||||
|
|
||||||
|
if response.code == 200 and response['status']
|
||||||
|
case response['status']
|
||||||
|
when 'killed'
|
||||||
|
:canceled
|
||||||
|
when 'failure', 'error'
|
||||||
|
# Because drone return error if some test env failed
|
||||||
|
:failed
|
||||||
|
else
|
||||||
|
response["status"]
|
||||||
|
end
|
||||||
|
else
|
||||||
|
:error
|
||||||
|
end
|
||||||
|
rescue Errno::ECONNREFUSED
|
||||||
|
:error
|
||||||
|
end
|
||||||
|
|
||||||
|
def commit_status(sha, ref)
|
||||||
|
response = HTTParty.get(commit_status_path(sha, ref), verify: enable_ssl_verification)
|
||||||
|
|
||||||
|
if response.code == 200 and response['status']
|
||||||
|
case response['status']
|
||||||
|
when 'killed'
|
||||||
|
:canceled
|
||||||
|
when 'failure', 'error'
|
||||||
|
# Because drone return error if some test env failed
|
||||||
|
:failed
|
||||||
|
else
|
||||||
|
response["status"]
|
||||||
|
end
|
||||||
|
else
|
||||||
|
:error
|
||||||
|
end
|
||||||
|
rescue Errno::ECONNREFUSED
|
||||||
|
:error
|
||||||
|
end
|
||||||
|
|
||||||
|
def merge_request_page(iid, sha, ref)
|
||||||
|
url = [drone_url,
|
||||||
|
"gitlab/#{project.namespace.path}/#{project.path}/redirect/pulls/#{iid}"]
|
||||||
|
|
||||||
|
URI.join(*url).to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def commit_page(sha, ref)
|
||||||
|
url = [drone_url,
|
||||||
|
"gitlab/#{project.namespace.path}/#{project.path}/redirect/commits/#{sha}",
|
||||||
|
"?branch=#{URI::encode(ref.to_s)}"]
|
||||||
|
|
||||||
|
URI.join(*url).to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def commit_coverage(sha, ref)
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_page(sha, ref)
|
||||||
|
commit_page(sha, ref)
|
||||||
|
end
|
||||||
|
|
||||||
|
def builds_path
|
||||||
|
url = [drone_url, "#{project.namespace.path}/#{project.path}"]
|
||||||
|
|
||||||
|
URI.join(*url).to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def status_img_path
|
||||||
|
url = [drone_url,
|
||||||
|
"api/badges/#{project.namespace.path}/#{project.path}/status.svg",
|
||||||
|
"?branch=#{URI::encode(project.default_branch)}"]
|
||||||
|
|
||||||
|
URI.join(*url).to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def title
|
||||||
|
'Drone CI'
|
||||||
|
end
|
||||||
|
|
||||||
|
def description
|
||||||
|
'Drone is a Continuous Integration platform built on Docker, written in Go'
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_param
|
||||||
|
'drone_ci'
|
||||||
|
end
|
||||||
|
|
||||||
|
def fields
|
||||||
|
[
|
||||||
|
{ type: 'text', name: 'token', placeholder: 'Drone CI project specific token' },
|
||||||
|
{ type: 'text', name: 'drone_url', placeholder: 'http://drone.example.com' },
|
||||||
|
{ type: 'checkbox', name: 'enable_ssl_verification', title: "Enable SSL verification" }
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def tag_push_valid?(data)
|
||||||
|
data[:total_commits_count] > 0 && !Gitlab::Git.blank_ref?(data[:after])
|
||||||
|
end
|
||||||
|
|
||||||
|
def push_valid?(data)
|
||||||
|
opened_merge_requests = project.merge_requests.opened.where(source_project_id: project.id,
|
||||||
|
source_branch: Gitlab::Git.ref_name(data[:ref]))
|
||||||
|
|
||||||
|
opened_merge_requests.empty? && data[:total_commits_count] > 0 &&
|
||||||
|
!Gitlab::Git.blank_ref?(data[:after])
|
||||||
|
end
|
||||||
|
|
||||||
|
def merge_request_valid?(data)
|
||||||
|
['opened', 'reopened'].include?(data[:object_attributes][:state]) &&
|
||||||
|
data[:object_attributes][:merge_status] == 'unchecked'
|
||||||
|
end
|
||||||
|
end
|
|
@ -135,6 +135,7 @@ class Service < ActiveRecord::Base
|
||||||
buildkite
|
buildkite
|
||||||
campfire
|
campfire
|
||||||
custom_issue_tracker
|
custom_issue_tracker
|
||||||
|
drone_ci
|
||||||
emails_on_push
|
emails_on_push
|
||||||
external_wiki
|
external_wiki
|
||||||
flowdock
|
flowdock
|
||||||
|
|
|
@ -1,8 +1,296 @@
|
||||||
# Services
|
# Services
|
||||||
|
|
||||||
|
## Asana
|
||||||
|
|
||||||
|
Asana - Teamwork without email
|
||||||
|
|
||||||
|
### Create/Edit Asana service
|
||||||
|
|
||||||
|
Set Asana service for a project.
|
||||||
|
|
||||||
|
> This service adds commit messages as comments to Asana tasks. Once enabled, commit messages are checked for Asana task URLs (for example, `https://app.asana.com/0/123456/987654`) or task IDs starting with # (for example, `#987654`). Every task ID found will get the commit comment added to it. You can also close a task with a message containing: `fix #123456`. You can find your Api Keys here: http://developer.asana.com/documentation/#api_keys
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /projects/:id/services/asana
|
||||||
|
```
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- `api_key` (**required**) - User API token. User must have access to task,all comments will be attributed to this user.
|
||||||
|
- `restrict_to_branch` (optional) - Comma-separated list of branches which will beautomatically inspected. Leave blank to include all branches.
|
||||||
|
|
||||||
|
### Delete Asana service
|
||||||
|
|
||||||
|
Delete Asana service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
DELETE /projects/:id/services/asana
|
||||||
|
```
|
||||||
|
|
||||||
|
## Assembla
|
||||||
|
|
||||||
|
Project Management Software (Source Commits Endpoint)
|
||||||
|
|
||||||
|
### Create/Edit Assembla service
|
||||||
|
|
||||||
|
Set Assembla service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /projects/:id/services/assembla
|
||||||
|
```
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- `token` (**required**)
|
||||||
|
- `subdomain` (optional)
|
||||||
|
|
||||||
|
### Delete Assembla service
|
||||||
|
|
||||||
|
Delete Assembla service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
DELETE /projects/:id/services/assembla
|
||||||
|
```
|
||||||
|
|
||||||
|
## Atlassian Bamboo CI
|
||||||
|
|
||||||
|
A continuous integration and build server
|
||||||
|
|
||||||
|
### Create/Edit Atlassian Bamboo CI service
|
||||||
|
|
||||||
|
Set Atlassian Bamboo CI service for a project.
|
||||||
|
|
||||||
|
> You must set up automatic revision labeling and a repository trigger in Bamboo.
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /projects/:id/services/bamboo
|
||||||
|
```
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- `bamboo_url` (**required**) - Bamboo root URL like https://bamboo.example.com
|
||||||
|
- `build_key` (**required**) - Bamboo build plan key like KEY
|
||||||
|
- `username` (**required**) - A user with API access, if applicable
|
||||||
|
- `password` (**required**)
|
||||||
|
|
||||||
|
### Delete Atlassian Bamboo CI service
|
||||||
|
|
||||||
|
Delete Atlassian Bamboo CI service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
DELETE /projects/:id/services/bamboo
|
||||||
|
```
|
||||||
|
|
||||||
|
## Buildkite
|
||||||
|
|
||||||
|
Continuous integration and deployments
|
||||||
|
|
||||||
|
### Create/Edit Buildkite service
|
||||||
|
|
||||||
|
Set Buildkite service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /projects/:id/services/buildkite
|
||||||
|
```
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- `token` (**required**) - Buildkite project GitLab token
|
||||||
|
- `project_url` (**required**) - https://buildkite.com/example/project
|
||||||
|
- `enable_ssl_verification` (optional) - Enable SSL verification
|
||||||
|
|
||||||
|
### Delete Buildkite service
|
||||||
|
|
||||||
|
Delete Buildkite service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
DELETE /projects/:id/services/buildkite
|
||||||
|
```
|
||||||
|
|
||||||
|
## Campfire
|
||||||
|
|
||||||
|
Simple web-based real-time group chat
|
||||||
|
|
||||||
|
### Create/Edit Campfire service
|
||||||
|
|
||||||
|
Set Campfire service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /projects/:id/services/campfire
|
||||||
|
```
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- `token` (**required**)
|
||||||
|
- `subdomain` (optional)
|
||||||
|
- `room` (optional)
|
||||||
|
|
||||||
|
### Delete Campfire service
|
||||||
|
|
||||||
|
Delete Campfire service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
DELETE /projects/:id/services/campfire
|
||||||
|
```
|
||||||
|
|
||||||
|
## Custom Issue Tracker
|
||||||
|
|
||||||
|
Custom issue tracker
|
||||||
|
|
||||||
|
### Create/Edit Custom Issue Tracker service
|
||||||
|
|
||||||
|
Set Custom Issue Tracker service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /projects/:id/services/custom-issue-tracker
|
||||||
|
```
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- `new_issue_url` (**required**) - New Issue url
|
||||||
|
- `issues_url` (**required**) - Issue url
|
||||||
|
- `project_url` (**required**) - Project url
|
||||||
|
- `description` (optional) - Custom issue tracker
|
||||||
|
- `title` (optional) - Custom Issue Tracker
|
||||||
|
|
||||||
|
### Delete Custom Issue Tracker service
|
||||||
|
|
||||||
|
Delete Custom Issue Tracker service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
DELETE /projects/:id/services/custom-issue-tracker
|
||||||
|
```
|
||||||
|
|
||||||
|
## Drone CI
|
||||||
|
|
||||||
|
Drone is a Continuous Integration platform built on Docker, written in Go
|
||||||
|
|
||||||
|
### Create/Edit Drone CI service
|
||||||
|
|
||||||
|
Set Drone CI service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /projects/:id/services/drone-ci
|
||||||
|
```
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- `token` (**required**) - Drone CI project specific token
|
||||||
|
- `drone_url` (**required**) - http://drone.example.com
|
||||||
|
- `enable_ssl_verification` (optional) - Enable SSL verification
|
||||||
|
|
||||||
|
### Delete Drone CI service
|
||||||
|
|
||||||
|
Delete Drone CI service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
DELETE /projects/:id/services/drone-ci
|
||||||
|
```
|
||||||
|
|
||||||
|
## Emails on push
|
||||||
|
|
||||||
|
Email the commits and diff of each push to a list of recipients.
|
||||||
|
|
||||||
|
### Create/Edit Emails on push service
|
||||||
|
|
||||||
|
Set Emails on push service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /projects/:id/services/emails-on-push
|
||||||
|
```
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- `recipients` (**required**) - Emails separated by whitespace
|
||||||
|
- `disable_diffs` (optional) - Disable code diffs
|
||||||
|
- `send_from_committer_email` (optional) - Send from committer
|
||||||
|
|
||||||
|
### Delete Emails on push service
|
||||||
|
|
||||||
|
Delete Emails on push service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
DELETE /projects/:id/services/emails-on-push
|
||||||
|
```
|
||||||
|
|
||||||
|
## External Wiki
|
||||||
|
|
||||||
|
Replaces the link to the internal wiki with a link to an external wiki.
|
||||||
|
|
||||||
|
### Create/Edit External Wiki service
|
||||||
|
|
||||||
|
Set External Wiki service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /projects/:id/services/external-wiki
|
||||||
|
```
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- `external_wiki_url` (**required**) - The URL of the external Wiki
|
||||||
|
|
||||||
|
### Delete External Wiki service
|
||||||
|
|
||||||
|
Delete External Wiki service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
DELETE /projects/:id/services/external-wiki
|
||||||
|
```
|
||||||
|
|
||||||
|
## Flowdock
|
||||||
|
|
||||||
|
Flowdock is a collaboration web app for technical teams.
|
||||||
|
|
||||||
|
### Create/Edit Flowdock service
|
||||||
|
|
||||||
|
Set Flowdock service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /projects/:id/services/flowdock
|
||||||
|
```
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- `token` (**required**) - Flowdock Git source token
|
||||||
|
|
||||||
|
### Delete Flowdock service
|
||||||
|
|
||||||
|
Delete Flowdock service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
DELETE /projects/:id/services/flowdock
|
||||||
|
```
|
||||||
|
|
||||||
|
## Gemnasium
|
||||||
|
|
||||||
|
Gemnasium monitors your project dependencies and alerts you about updates and security vulnerabilities.
|
||||||
|
|
||||||
|
### Create/Edit Gemnasium service
|
||||||
|
|
||||||
|
Set Gemnasium service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /projects/:id/services/gemnasium
|
||||||
|
```
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- `api_key` (**required**) - Your personal API KEY on gemnasium.com
|
||||||
|
- `token` (**required**) - The project's slug on gemnasium.com
|
||||||
|
|
||||||
|
### Delete Gemnasium service
|
||||||
|
|
||||||
|
Delete Gemnasium service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
DELETE /projects/:id/services/gemnasium
|
||||||
|
```
|
||||||
|
|
||||||
## GitLab CI
|
## GitLab CI
|
||||||
|
|
||||||
### Edit GitLab CI service
|
Continuous integration server from GitLab
|
||||||
|
|
||||||
|
### Create/Edit GitLab CI service
|
||||||
|
|
||||||
Set GitLab CI service for a project.
|
Set GitLab CI service for a project.
|
||||||
|
|
||||||
|
@ -12,12 +300,13 @@ PUT /projects/:id/services/gitlab-ci
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
|
|
||||||
- `token` (required) - CI project token
|
- `token` (**required**) - GitLab CI project specific token
|
||||||
- `project_url` (required) - CI project URL
|
- `project_url` (**required**) - http://ci.gitlabhq.com/projects/3
|
||||||
|
- `enable_ssl_verification` (optional) - Enable SSL verification
|
||||||
|
|
||||||
### Delete GitLab CI service
|
### Delete GitLab CI service
|
||||||
|
|
||||||
Delete GitLab CI service settings for a project.
|
Delete GitLab CI service for a project.
|
||||||
|
|
||||||
```
|
```
|
||||||
DELETE /projects/:id/services/gitlab-ci
|
DELETE /projects/:id/services/gitlab-ci
|
||||||
|
@ -25,17 +314,24 @@ DELETE /projects/:id/services/gitlab-ci
|
||||||
|
|
||||||
## HipChat
|
## HipChat
|
||||||
|
|
||||||
### Edit HipChat service
|
Private group chat and IM
|
||||||
|
|
||||||
Set HipChat service for project.
|
### Create/Edit HipChat service
|
||||||
|
|
||||||
|
Set HipChat service for a project.
|
||||||
|
|
||||||
```
|
```
|
||||||
PUT /projects/:id/services/hipchat
|
PUT /projects/:id/services/hipchat
|
||||||
```
|
```
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
|
|
||||||
- `token` (required) - HipChat token
|
- `token` (**required**) - Room token
|
||||||
- `room` (required) - HipChat room name
|
- `color` (optional)
|
||||||
|
- `notify` (optional)
|
||||||
|
- `room` (optional) - Room name or ID
|
||||||
|
- `api_version` (optional) - Leave blank for default (v2)
|
||||||
|
- `server` (optional) - Leave blank for default. https://hipchat.example.com
|
||||||
|
|
||||||
### Delete HipChat service
|
### Delete HipChat service
|
||||||
|
|
||||||
|
@ -44,3 +340,197 @@ Delete HipChat service for a project.
|
||||||
```
|
```
|
||||||
DELETE /projects/:id/services/hipchat
|
DELETE /projects/:id/services/hipchat
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Irker (IRC gateway)
|
||||||
|
|
||||||
|
Send IRC messages, on update, to a list of recipients through an Irker gateway.
|
||||||
|
|
||||||
|
### Create/Edit Irker (IRC gateway) service
|
||||||
|
|
||||||
|
Set Irker (IRC gateway) service for a project.
|
||||||
|
|
||||||
|
> NOTE: Irker does NOT have built-in authentication, which makes it vulnerable to spamming IRC channels if it is hosted outside of a firewall. Please make sure you run the daemon within a secured network to prevent abuse. For more details, read: http://www.catb.org/~esr/irker/security.html.
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /projects/:id/services/irker
|
||||||
|
```
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- `recipients` (**required**) - Recipients/channels separated by whitespaces
|
||||||
|
- `default_irc_uri` (optional) - irc://irc.network.net:6697/
|
||||||
|
- `server_port` (optional) - 6659
|
||||||
|
- `server_host` (optional) - localhost
|
||||||
|
- `colorize_messages` (optional)
|
||||||
|
|
||||||
|
### Delete Irker (IRC gateway) service
|
||||||
|
|
||||||
|
Delete Irker (IRC gateway) service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
DELETE /projects/:id/services/irker
|
||||||
|
```
|
||||||
|
|
||||||
|
## JIRA
|
||||||
|
|
||||||
|
Jira issue tracker
|
||||||
|
|
||||||
|
### Create/Edit JIRA service
|
||||||
|
|
||||||
|
Set JIRA service for a project.
|
||||||
|
|
||||||
|
> Setting `project_url`, `issues_url` and `new_issue_url` will allow a user to easily navigate to the Jira issue tracker. See the [integration doc](http://doc.gitlab.com/ce/integration/external-issue-tracker.html) for details. Support for referencing commits and automatic closing of Jira issues directly from GitLab is [available in GitLab EE.](http://doc.gitlab.com/ee/integration/jira.html)
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /projects/:id/services/jira
|
||||||
|
```
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- `new_issue_url` (**required**) - New Issue url
|
||||||
|
- `project_url` (**required**) - Project url
|
||||||
|
- `issues_url` (**required**) - Issue url
|
||||||
|
- `description` (optional) - Jira issue tracker
|
||||||
|
|
||||||
|
### Delete JIRA service
|
||||||
|
|
||||||
|
Delete JIRA service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
DELETE /projects/:id/services/jira
|
||||||
|
```
|
||||||
|
|
||||||
|
## PivotalTracker
|
||||||
|
|
||||||
|
Project Management Software (Source Commits Endpoint)
|
||||||
|
|
||||||
|
### Create/Edit PivotalTracker service
|
||||||
|
|
||||||
|
Set PivotalTracker service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /projects/:id/services/pivotaltracker
|
||||||
|
```
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- `token` (**required**)
|
||||||
|
|
||||||
|
### Delete PivotalTracker service
|
||||||
|
|
||||||
|
Delete PivotalTracker service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
DELETE /projects/:id/services/pivotaltracker
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pushover
|
||||||
|
|
||||||
|
Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop.
|
||||||
|
|
||||||
|
### Create/Edit Pushover service
|
||||||
|
|
||||||
|
Set Pushover service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /projects/:id/services/pushover
|
||||||
|
```
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- `api_key` (**required**) - Your application key
|
||||||
|
- `user_key` (**required**) - Your user key
|
||||||
|
- `priority` (**required**)
|
||||||
|
- `device` (optional) - Leave blank for all active devices
|
||||||
|
- `sound` (optional)
|
||||||
|
|
||||||
|
### Delete Pushover service
|
||||||
|
|
||||||
|
Delete Pushover service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
DELETE /projects/:id/services/pushover
|
||||||
|
```
|
||||||
|
|
||||||
|
## Redmine
|
||||||
|
|
||||||
|
Redmine issue tracker
|
||||||
|
|
||||||
|
### Create/Edit Redmine service
|
||||||
|
|
||||||
|
Set Redmine service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /projects/:id/services/redmine
|
||||||
|
```
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- `new_issue_url` (**required**) - New Issue url
|
||||||
|
- `project_url` (**required**) - Project url
|
||||||
|
- `issues_url` (**required**) - Issue url
|
||||||
|
- `description` (optional) - Redmine issue tracker
|
||||||
|
|
||||||
|
### Delete Redmine service
|
||||||
|
|
||||||
|
Delete Redmine service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
DELETE /projects/:id/services/redmine
|
||||||
|
```
|
||||||
|
|
||||||
|
## Slack
|
||||||
|
|
||||||
|
A team communication tool for the 21st century
|
||||||
|
|
||||||
|
### Create/Edit Slack service
|
||||||
|
|
||||||
|
Set Slack service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /projects/:id/services/slack
|
||||||
|
```
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- `webhook` (**required**) - https://hooks.slack.com/services/...
|
||||||
|
- `username` (optional) - username
|
||||||
|
- `channel` (optional) - #channel
|
||||||
|
|
||||||
|
### Delete Slack service
|
||||||
|
|
||||||
|
Delete Slack service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
DELETE /projects/:id/services/slack
|
||||||
|
```
|
||||||
|
|
||||||
|
## JetBrains TeamCity CI
|
||||||
|
|
||||||
|
A continuous integration and build server
|
||||||
|
|
||||||
|
### Create/Edit JetBrains TeamCity CI service
|
||||||
|
|
||||||
|
Set JetBrains TeamCity CI service for a project.
|
||||||
|
|
||||||
|
> The build configuration in Teamcity must use the build format number %build.vcs.number% you will also want to configure monitoring of all branches so merge requests build, that setting is in the vsc root advanced settings.
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /projects/:id/services/teamcity
|
||||||
|
```
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- `teamcity_url` (**required**) - TeamCity root URL like https://teamcity.example.com
|
||||||
|
- `build_type` (**required**) - Build configuration ID
|
||||||
|
- `username` (**required**) - A user with permissions to trigger a manual build
|
||||||
|
- `password` (**required**)
|
||||||
|
|
||||||
|
### Delete JetBrains TeamCity CI service
|
||||||
|
|
||||||
|
Delete JetBrains TeamCity CI service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
DELETE /projects/:id/services/teamcity
|
||||||
|
```
|
||||||
|
|
||||||
|
|
|
@ -279,6 +279,7 @@ X-Gitlab-Event: Note Hook
|
||||||
"name": "Gitlab Test",
|
"name": "Gitlab Test",
|
||||||
"ssh_url": "git@example.com:gitlab-org/gitlab-test.git",
|
"ssh_url": "git@example.com:gitlab-org/gitlab-test.git",
|
||||||
"http_url": "http://example.com/gitlab-org/gitlab-test.git",
|
"http_url": "http://example.com/gitlab-org/gitlab-test.git",
|
||||||
|
"web_url": "http://example.com/gitlab-org/gitlab-test",
|
||||||
"namespace": "Gitlab Org",
|
"namespace": "Gitlab Org",
|
||||||
"visibility_level": 10
|
"visibility_level": 10
|
||||||
},
|
},
|
||||||
|
@ -286,6 +287,7 @@ X-Gitlab-Event: Note Hook
|
||||||
"name": "Gitlab Test",
|
"name": "Gitlab Test",
|
||||||
"ssh_url": "git@example.com:gitlab-org/gitlab-test.git",
|
"ssh_url": "git@example.com:gitlab-org/gitlab-test.git",
|
||||||
"http_url": "http://example.com/gitlab-org/gitlab-test.git",
|
"http_url": "http://example.com/gitlab-org/gitlab-test.git",
|
||||||
|
"web_url": "http://example.com/gitlab-org/gitlab-test",
|
||||||
"namespace": "Gitlab Org",
|
"namespace": "Gitlab Org",
|
||||||
"visibility_level": 10
|
"visibility_level": 10
|
||||||
},
|
},
|
||||||
|
@ -462,6 +464,7 @@ X-Gitlab-Event: Merge Request Hook
|
||||||
"name": "awesome_project",
|
"name": "awesome_project",
|
||||||
"ssh_url": "ssh://git@example.com/awesome_space/awesome_project.git",
|
"ssh_url": "ssh://git@example.com/awesome_space/awesome_project.git",
|
||||||
"http_url": "http://example.com/awesome_space/awesome_project.git",
|
"http_url": "http://example.com/awesome_space/awesome_project.git",
|
||||||
|
"web_url": "http://example.com/awesome_space/awesome_project",
|
||||||
"visibility_level": 20,
|
"visibility_level": 20,
|
||||||
"namespace": "awesome_space"
|
"namespace": "awesome_space"
|
||||||
},
|
},
|
||||||
|
@ -469,6 +472,7 @@ X-Gitlab-Event: Merge Request Hook
|
||||||
"name": "awesome_project",
|
"name": "awesome_project",
|
||||||
"ssh_url": "ssh://git@example.com/awesome_space/awesome_project.git",
|
"ssh_url": "ssh://git@example.com/awesome_space/awesome_project.git",
|
||||||
"http_url": "http://example.com/awesome_space/awesome_project.git",
|
"http_url": "http://example.com/awesome_space/awesome_project.git",
|
||||||
|
"web_url": "http://example.com/awesome_space/awesome_project",
|
||||||
"visibility_level": 20,
|
"visibility_level": 20,
|
||||||
"namespace": "awesome_space"
|
"namespace": "awesome_space"
|
||||||
},
|
},
|
||||||
|
|
|
@ -55,6 +55,32 @@ module API
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def project_service
|
||||||
|
@project_service ||= begin
|
||||||
|
underscored_service = params[:service_slug].underscore
|
||||||
|
|
||||||
|
if Service.available_services_names.include?(underscored_service)
|
||||||
|
user_project.build_missing_services
|
||||||
|
|
||||||
|
service_method = "#{underscored_service}_service"
|
||||||
|
|
||||||
|
send_service(service_method)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@project_service || not_found!("Service")
|
||||||
|
end
|
||||||
|
|
||||||
|
def send_service(service_method)
|
||||||
|
user_project.send(service_method)
|
||||||
|
end
|
||||||
|
|
||||||
|
def service_attributes
|
||||||
|
@service_attributes ||= project_service.fields.inject([]) do |arr, hash|
|
||||||
|
arr << hash[:name].to_sym
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def find_group(id)
|
def find_group(id)
|
||||||
begin
|
begin
|
||||||
group = Group.find(id)
|
group = Group.find(id)
|
||||||
|
|
|
@ -4,74 +4,50 @@ module API
|
||||||
before { authenticate! }
|
before { authenticate! }
|
||||||
before { authorize_admin_project }
|
before { authorize_admin_project }
|
||||||
|
|
||||||
|
|
||||||
resource :projects do
|
resource :projects do
|
||||||
# Set GitLab CI service for project
|
# Set <service_slug> service for project
|
||||||
#
|
|
||||||
# Parameters:
|
|
||||||
# token (required) - CI project token
|
|
||||||
# project_url (required) - CI project url
|
|
||||||
#
|
#
|
||||||
# Example Request:
|
# Example Request:
|
||||||
|
#
|
||||||
# PUT /projects/:id/services/gitlab-ci
|
# PUT /projects/:id/services/gitlab-ci
|
||||||
put ":id/services/gitlab-ci" do
|
#
|
||||||
required_attributes! [:token, :project_url]
|
put ':id/services/:service_slug' do
|
||||||
attrs = attributes_for_keys [:token, :project_url]
|
if project_service
|
||||||
user_project.build_missing_services
|
validators = project_service.class.validators.select do |s|
|
||||||
|
s.class == ActiveRecord::Validations::PresenceValidator &&
|
||||||
|
s.attributes != [:project_id]
|
||||||
|
end
|
||||||
|
|
||||||
if user_project.gitlab_ci_service.update_attributes(attrs.merge(active: true))
|
required_attributes! validators.map(&:attributes).flatten.uniq
|
||||||
|
attrs = attributes_for_keys service_attributes
|
||||||
|
|
||||||
|
if project_service.update_attributes(attrs.merge(active: true))
|
||||||
true
|
true
|
||||||
else
|
else
|
||||||
not_found!
|
not_found!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Delete GitLab CI service settings
|
|
||||||
#
|
|
||||||
# Example Request:
|
|
||||||
# DELETE /projects/:id/services/gitlab-ci
|
|
||||||
delete ":id/services/gitlab-ci" do
|
|
||||||
if user_project.gitlab_ci_service
|
|
||||||
user_project.gitlab_ci_service.update_attributes(
|
|
||||||
active: false,
|
|
||||||
token: nil,
|
|
||||||
project_url: nil
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Set Hipchat service for project
|
# Delete <service_slug> service for project
|
||||||
#
|
|
||||||
# Parameters:
|
|
||||||
# token (required) - Hipchat token
|
|
||||||
# room (required) - Hipchat room name
|
|
||||||
#
|
#
|
||||||
# Example Request:
|
# Example Request:
|
||||||
# PUT /projects/:id/services/hipchat
|
#
|
||||||
put ':id/services/hipchat' do
|
# DELETE /project/:id/services/gitlab-ci
|
||||||
required_attributes! [:token, :room]
|
#
|
||||||
attrs = attributes_for_keys [:token, :room]
|
delete ':id/services/:service_slug' do
|
||||||
user_project.build_missing_services
|
if project_service
|
||||||
|
attrs = service_attributes.inject({}) do |hash, key|
|
||||||
|
hash.merge!(key => nil)
|
||||||
|
end
|
||||||
|
|
||||||
if user_project.hipchat_service.update_attributes(
|
if project_service.update_attributes(attrs.merge(active: false))
|
||||||
attrs.merge(active: true))
|
|
||||||
true
|
true
|
||||||
else
|
else
|
||||||
not_found!
|
not_found!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Delete Hipchat service settings
|
|
||||||
#
|
|
||||||
# Example Request:
|
|
||||||
# DELETE /projects/:id/services/hipchat
|
|
||||||
delete ':id/services/hipchat' do
|
|
||||||
if user_project.hipchat_service
|
|
||||||
user_project.hipchat_service.update_attributes(
|
|
||||||
active: false,
|
|
||||||
token: nil,
|
|
||||||
room: nil
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,7 +10,7 @@ module Grack
|
||||||
@request = Rack::Request.new(env)
|
@request = Rack::Request.new(env)
|
||||||
@auth = Request.new(env)
|
@auth = Request.new(env)
|
||||||
|
|
||||||
@gitlab_ci = false
|
@ci = false
|
||||||
|
|
||||||
# Need this patch due to the rails mount
|
# Need this patch due to the rails mount
|
||||||
# Need this if under RELATIVE_URL_ROOT
|
# Need this if under RELATIVE_URL_ROOT
|
||||||
|
@ -28,7 +28,7 @@ module Grack
|
||||||
if project && authorized_request?
|
if project && authorized_request?
|
||||||
# Tell gitlab-git-http-server the request is OK, and what the GL_ID is
|
# Tell gitlab-git-http-server the request is OK, and what the GL_ID is
|
||||||
render_grack_auth_ok
|
render_grack_auth_ok
|
||||||
elsif @user.nil? && !@gitlab_ci
|
elsif @user.nil? && !@ci
|
||||||
unauthorized
|
unauthorized
|
||||||
else
|
else
|
||||||
render_not_found
|
render_not_found
|
||||||
|
@ -47,8 +47,8 @@ module Grack
|
||||||
|
|
||||||
# Allow authentication for GitLab CI service
|
# Allow authentication for GitLab CI service
|
||||||
# if valid token passed
|
# if valid token passed
|
||||||
if gitlab_ci_request?(login, password)
|
if ci_request?(login, password)
|
||||||
@gitlab_ci = true
|
@ci = true
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -60,12 +60,17 @@ module Grack
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def gitlab_ci_request?(login, password)
|
def ci_request?(login, password)
|
||||||
if login == "gitlab-ci-token" && project && project.gitlab_ci?
|
matched_login = /(?<s>^[a-zA-Z]*-ci)-token$/.match(login)
|
||||||
token = project.gitlab_ci_service.token
|
|
||||||
|
|
||||||
if token.present? && token == password && git_cmd == 'git-upload-pack'
|
if project && matched_login.present? && git_cmd == 'git-upload-pack'
|
||||||
return true
|
underscored_service = matched_login['s'].underscore
|
||||||
|
|
||||||
|
if Service.available_services_names.include?(underscored_service)
|
||||||
|
service_method = "#{underscored_service}_service"
|
||||||
|
service = project.send(service_method)
|
||||||
|
|
||||||
|
return service && service.activated? && service.valid_token?(password)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -124,7 +129,7 @@ module Grack
|
||||||
end
|
end
|
||||||
|
|
||||||
def authorized_request?
|
def authorized_request?
|
||||||
return true if @gitlab_ci
|
return true if @ci
|
||||||
|
|
||||||
case git_cmd
|
case git_cmd
|
||||||
when *Gitlab::GitAccess::DOWNLOAD_COMMANDS
|
when *Gitlab::GitAccess::DOWNLOAD_COMMANDS
|
||||||
|
|
89
lib/tasks/services.rake
Normal file
89
lib/tasks/services.rake
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
services_template = <<-ERB
|
||||||
|
# Services
|
||||||
|
|
||||||
|
<% services.each do |service| %>
|
||||||
|
## <%= service[:title] %>
|
||||||
|
|
||||||
|
|
||||||
|
<% unless service[:description].blank? %>
|
||||||
|
<%= service[:description] %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
|
||||||
|
### Create/Edit <%= service[:title] %> service
|
||||||
|
|
||||||
|
Set <%= service[:title] %> service for a project.
|
||||||
|
<% unless service[:help].blank? %>
|
||||||
|
|
||||||
|
> <%= service[:help].gsub("\n", ' ') %>
|
||||||
|
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /projects/:id/services/<%= service[:dashed_name] %>
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
<% service[:params].each do |param| %>
|
||||||
|
- `<%= param[:name] %>` <%= param[:required] ? "(**required**)" : "(optional)" %><%= [" -", param[:description]].join(" ").gsub("\n", '') unless param[:description].blank? %>
|
||||||
|
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
### Delete <%= service[:title] %> service
|
||||||
|
|
||||||
|
Delete <%= service[:title] %> service for a project.
|
||||||
|
|
||||||
|
```
|
||||||
|
DELETE /projects/:id/services/<%= service[:dashed_name] %>
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
<% end %>
|
||||||
|
ERB
|
||||||
|
|
||||||
|
namespace :services do
|
||||||
|
task :doc do
|
||||||
|
services = Service.available_services_names.map do |s|
|
||||||
|
service_start = Time.now
|
||||||
|
klass = "#{s}_service".classify.constantize
|
||||||
|
|
||||||
|
service = klass.new
|
||||||
|
|
||||||
|
service_hash = {}
|
||||||
|
|
||||||
|
service_hash[:title] = service.title
|
||||||
|
service_hash[:dashed_name] = s.dasherize
|
||||||
|
service_hash[:description] = service.description
|
||||||
|
service_hash[:help] = service.help
|
||||||
|
service_hash[:params] = service.fields.map do |p|
|
||||||
|
param_hash = {}
|
||||||
|
|
||||||
|
param_hash[:name] = p[:name]
|
||||||
|
param_hash[:description] = p[:placeholder] || p[:title]
|
||||||
|
param_hash[:required] = klass.validators_on(p[:name].to_sym).any? do |v|
|
||||||
|
v.class == ActiveRecord::Validations::PresenceValidator
|
||||||
|
end
|
||||||
|
|
||||||
|
param_hash
|
||||||
|
end.sort_by { |p| p[:required] ? 0 : 1 }
|
||||||
|
|
||||||
|
puts "Collected data for: #{service.title}, #{Time.now-service_start}"
|
||||||
|
service_hash
|
||||||
|
end
|
||||||
|
|
||||||
|
doc_start = Time.now
|
||||||
|
doc_path = File.join(Rails.root, 'doc', 'api', 'services.md')
|
||||||
|
|
||||||
|
result = ERB.new(services_template, 0 , '>')
|
||||||
|
.result(OpenStruct.new(services: services).instance_eval { binding })
|
||||||
|
|
||||||
|
File.open(doc_path, 'w') do |f|
|
||||||
|
f.write result
|
||||||
|
end
|
||||||
|
|
||||||
|
puts "write a new service.md to: #{doc_path.to_s}, #{Time.now-doc_start}"
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
107
spec/models/project_services/drone_ci_service_spec.rb
Normal file
107
spec/models/project_services/drone_ci_service_spec.rb
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
# == Schema Information
|
||||||
|
#
|
||||||
|
# Table name: services
|
||||||
|
#
|
||||||
|
# id :integer not null, primary key
|
||||||
|
# type :string(255)
|
||||||
|
# title :string(255)
|
||||||
|
# project_id :integer
|
||||||
|
# created_at :datetime
|
||||||
|
# updated_at :datetime
|
||||||
|
# active :boolean default(FALSE), not null
|
||||||
|
# properties :text
|
||||||
|
# template :boolean default(FALSE)
|
||||||
|
# push_events :boolean default(TRUE)
|
||||||
|
# issues_events :boolean default(TRUE)
|
||||||
|
# merge_requests_events :boolean default(TRUE)
|
||||||
|
# tag_push_events :boolean default(TRUE)
|
||||||
|
# note_events :boolean default(TRUE), not null
|
||||||
|
#
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe DroneCiService do
|
||||||
|
describe 'associations' do
|
||||||
|
it { is_expected.to belong_to(:project) }
|
||||||
|
it { is_expected.to have_one(:service_hook) }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'validations' do
|
||||||
|
context 'active' do
|
||||||
|
before { allow(subject).to receive(:activated?).and_return(true) }
|
||||||
|
|
||||||
|
it { is_expected.to validate_presence_of(:token) }
|
||||||
|
it { is_expected.to validate_presence_of(:drone_url) }
|
||||||
|
it { is_expected.to allow_value('ewf9843kdnfdfs89234n').for(:token) }
|
||||||
|
it { is_expected.to allow_value('http://ci.example.com').for(:drone_url) }
|
||||||
|
it { is_expected.not_to allow_value('token with spaces').for(:token) }
|
||||||
|
it { is_expected.not_to allow_value('token/with%spaces').for(:token) }
|
||||||
|
it { is_expected.not_to allow_value('this is not url').for(:drone_url) }
|
||||||
|
it { is_expected.not_to allow_value('http//noturl').for(:drone_url) }
|
||||||
|
it { is_expected.not_to allow_value('ftp://ci.example.com').for(:drone_url) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'inactive' do
|
||||||
|
before { allow(subject).to receive(:activated?).and_return(false) }
|
||||||
|
|
||||||
|
it { is_expected.not_to validate_presence_of(:token) }
|
||||||
|
it { is_expected.not_to validate_presence_of(:drone_url) }
|
||||||
|
it { is_expected.to allow_value('ewf9843kdnfdfs89234n').for(:token) }
|
||||||
|
it { is_expected.to allow_value('http://drone.example.com').for(:drone_url) }
|
||||||
|
it { is_expected.to allow_value('token with spaces').for(:token) }
|
||||||
|
it { is_expected.to allow_value('ftp://drone.example.com').for(:drone_url) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_context :drone_ci_service do
|
||||||
|
let(:drone) { DroneCiService.new }
|
||||||
|
let(:project) { create(:project, name: 'project') }
|
||||||
|
let(:path) { "#{project.namespace.path}/#{project.path}" }
|
||||||
|
let(:drone_url) { 'http://drone.example.com' }
|
||||||
|
let(:sha) { '2ab7834c' }
|
||||||
|
let(:branch) { 'dev' }
|
||||||
|
let(:token) { 'secret' }
|
||||||
|
let(:iid) { rand(1..9999) }
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
allow(drone).to receive_messages(
|
||||||
|
project_id: project.id,
|
||||||
|
project: project,
|
||||||
|
active: true,
|
||||||
|
drone_url: drone_url,
|
||||||
|
token: token
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "service page/path methods" do
|
||||||
|
include_context :drone_ci_service
|
||||||
|
|
||||||
|
# URL's
|
||||||
|
let(:commit_page) { "#{drone_url}/gitlab/#{path}/redirect/commits/#{sha}?branch=#{branch}" }
|
||||||
|
let(:merge_request_page) { "#{drone_url}/gitlab/#{path}/redirect/pulls/#{iid}" }
|
||||||
|
let(:commit_status_path) { "#{drone_url}/gitlab/#{path}/commits/#{sha}?branch=#{branch}&access_token=#{token}" }
|
||||||
|
let(:merge_request_status_path) { "#{drone_url}/gitlab/#{path}/pulls/#{iid}?access_token=#{token}" }
|
||||||
|
|
||||||
|
it { expect(drone.build_page(sha, branch)).to eq(commit_page) }
|
||||||
|
it { expect(drone.commit_page(sha, branch)).to eq(commit_page) }
|
||||||
|
it { expect(drone.merge_request_page(iid, sha, branch)).to eq(merge_request_page) }
|
||||||
|
it { expect(drone.commit_status_path(sha, branch)).to eq(commit_status_path) }
|
||||||
|
it { expect(drone.merge_request_status_path(iid, sha, branch)).to eq(merge_request_status_path) }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "execute" do
|
||||||
|
include_context :drone_ci_service
|
||||||
|
|
||||||
|
let(:user) { create(:user, username: 'username') }
|
||||||
|
let(:push_sample_data) { Gitlab::PushDataBuilder.build_sample(project, user) }
|
||||||
|
|
||||||
|
it do
|
||||||
|
service_hook = double
|
||||||
|
expect(service_hook).to receive(:execute)
|
||||||
|
expect(drone).to receive(:service_hook).and_return(service_hook)
|
||||||
|
|
||||||
|
drone.execute(push_sample_data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -5,64 +5,47 @@ describe API::API, api: true do
|
||||||
let(:user) { create(:user) }
|
let(:user) { create(:user) }
|
||||||
let(:project) {create(:project, creator_id: user.id, namespace: user.namespace) }
|
let(:project) {create(:project, creator_id: user.id, namespace: user.namespace) }
|
||||||
|
|
||||||
describe "POST /projects/:id/services/gitlab-ci" do
|
Service.available_services_names.each do |service|
|
||||||
it "should update gitlab-ci settings" do
|
describe "PUT /projects/:id/services/#{service.dasherize}" do
|
||||||
put api("/projects/#{project.id}/services/gitlab-ci", user), token: 'secrettoken', project_url: "http://ci.example.com/projects/1"
|
include_context service
|
||||||
|
|
||||||
|
it "should update #{service} settings" do
|
||||||
|
put api("/projects/#{project.id}/services/#{dashed_service}", user), service_attrs
|
||||||
|
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should return if required fields missing" do
|
it "should return if required fields missing" do
|
||||||
put api("/projects/#{project.id}/services/gitlab-ci", user), project_url: "http://ci.example.com/projects/1", active: true
|
attrs = service_attrs
|
||||||
|
|
||||||
expect(response.status).to eq(400)
|
required_attributes = service_attrs_list.select do |attr|
|
||||||
end
|
service_klass.validators_on(attr).any? do |v|
|
||||||
|
v.class == ActiveRecord::Validations::PresenceValidator
|
||||||
it "should return if the format of token is invalid" do
|
|
||||||
put api("/projects/#{project.id}/services/gitlab-ci", user), token: 'token-with dashes and spaces%', project_url: "http://ci.example.com/projects/1", active: true
|
|
||||||
|
|
||||||
expect(response.status).to eq(404)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "should return if the format of token is invalid" do
|
|
||||||
put api("/projects/#{project.id}/services/gitlab-ci", user), token: 'token-with dashes and spaces%', project_url: "ftp://ci.example/projects/1", active: true
|
|
||||||
|
|
||||||
expect(response.status).to eq(404)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "DELETE /projects/:id/services/gitlab-ci" do
|
if required_attributes.empty?
|
||||||
it "should update gitlab-ci settings" do
|
expected_code = 200
|
||||||
delete api("/projects/#{project.id}/services/gitlab-ci", user)
|
else
|
||||||
|
attrs.delete(required_attributes.shuffle.first)
|
||||||
|
expected_code = 400
|
||||||
|
end
|
||||||
|
|
||||||
|
put api("/projects/#{project.id}/services/#{dashed_service}", user), attrs
|
||||||
|
|
||||||
|
expect(response.status).to eq(expected_code)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "DELETE /projects/:id/services/#{service.dasherize}" do
|
||||||
|
include_context service
|
||||||
|
|
||||||
|
it "should delete #{service}" do
|
||||||
|
delete api("/projects/#{project.id}/services/#{dashed_service}", user)
|
||||||
|
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
expect(project.gitlab_ci_service).to be_nil
|
expect(project.send(service_method).activated?).to be_falsey
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
describe 'PUT /projects/:id/services/hipchat' do
|
|
||||||
it 'should update hipchat settings' do
|
|
||||||
put api("/projects/#{project.id}/services/hipchat", user),
|
|
||||||
token: 'secret-token', room: 'test'
|
|
||||||
|
|
||||||
expect(response.status).to eq(200)
|
|
||||||
expect(project.hipchat_service).not_to be_nil
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should return if required fields missing' do
|
|
||||||
put api("/projects/#{project.id}/services/gitlab-ci", user),
|
|
||||||
token: 'secret-token', active: true
|
|
||||||
|
|
||||||
expect(response.status).to eq(400)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe 'DELETE /projects/:id/services/hipchat' do
|
|
||||||
it 'should delete hipchat settings' do
|
|
||||||
delete api("/projects/#{project.id}/services/hipchat", user)
|
|
||||||
|
|
||||||
expect(response.status).to eq(200)
|
|
||||||
expect(project.hipchat_service).to be_nil
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
21
spec/support/services_shared_context.rb
Normal file
21
spec/support/services_shared_context.rb
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
Service.available_services_names.each do |service|
|
||||||
|
shared_context service do
|
||||||
|
let(:dashed_service) { service.dasherize }
|
||||||
|
let(:service_method) { "#{service}_service".to_sym }
|
||||||
|
let(:service_klass) { "#{service}_service".classify.constantize }
|
||||||
|
let(:service_attrs_list) { service_klass.new.fields.inject([]) {|arr, hash| arr << hash[:name].to_sym } }
|
||||||
|
let(:service_attrs) do
|
||||||
|
service_attrs_list.inject({}) do |hash, k|
|
||||||
|
if k =~ /^(token*|.*_token|.*_key)/
|
||||||
|
hash.merge!(k => 'secrettoken')
|
||||||
|
elsif k =~ /^(.*_url|url|webhook)/
|
||||||
|
hash.merge!(k => "http://example.com")
|
||||||
|
elsif service == 'irker' && k == :recipients
|
||||||
|
hash.merge!(k => 'irc://irc.network.net:666/#channel')
|
||||||
|
else
|
||||||
|
hash.merge!(k => "someword")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue