2013-10-29 10:39:46 -04:00
module API
class Services < Grape :: API
2016-12-05 09:40:53 -05:00
services = {
'asana' = > [
{
required : true ,
name : :api_key ,
type : String ,
desc : 'User API token'
} ,
{
required : false ,
name : :restrict_to_branch ,
type : String ,
desc : 'Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches'
}
] ,
'assembla' = > [
{
required : true ,
name : :token ,
type : String ,
desc : 'The authentication token'
} ,
{
required : false ,
name : :subdomain ,
type : String ,
desc : 'Subdomain setting'
}
] ,
'bamboo' = > [
{
required : true ,
name : :bamboo_url ,
type : String ,
desc : 'Bamboo root URL like https://bamboo.example.com'
} ,
{
required : true ,
name : :build_key ,
type : String ,
desc : 'Bamboo build plan key like'
} ,
{
required : true ,
name : :username ,
type : String ,
desc : 'A user with API access, if applicable'
} ,
{
required : true ,
name : :password ,
type : String ,
desc : 'Passord of the user'
}
] ,
'bugzilla' = > [
{
required : true ,
name : :new_issue_url ,
type : String ,
desc : 'New issue URL'
} ,
{
required : true ,
name : :issues_url ,
type : String ,
desc : 'Issues URL'
} ,
{
required : true ,
name : :project_url ,
type : String ,
desc : 'Project URL'
} ,
{
required : false ,
name : :description ,
type : String ,
desc : 'Description'
} ,
{
required : false ,
name : :title ,
type : String ,
desc : 'Title'
}
] ,
'buildkite' = > [
{
required : true ,
name : :token ,
type : String ,
desc : 'Buildkite project GitLab token'
} ,
{
required : true ,
name : :project_url ,
type : String ,
desc : 'The buildkite project URL'
} ,
{
required : false ,
name : :enable_ssl_verification ,
type : Boolean ,
desc : 'Enable SSL verification for communication'
}
] ,
'campfire' = > [
{
required : true ,
name : :token ,
type : String ,
desc : 'Campfire token'
} ,
{
required : false ,
name : :subdomain ,
type : String ,
desc : 'Campfire subdomain'
} ,
{
required : false ,
name : :room ,
type : String ,
desc : 'Campfire room'
2016-12-27 07:44:24 -05:00
}
2016-12-05 09:40:53 -05:00
] ,
'custom-issue-tracker' = > [
{
required : true ,
name : :new_issue_url ,
type : String ,
desc : 'New issue URL'
} ,
{
required : true ,
name : :issues_url ,
type : String ,
desc : 'Issues URL'
} ,
{
required : true ,
name : :project_url ,
type : String ,
desc : 'Project URL'
} ,
{
required : false ,
name : :description ,
type : String ,
desc : 'Description'
} ,
{
required : false ,
name : :title ,
type : String ,
desc : 'Title'
}
] ,
'drone-ci' = > [
{
required : true ,
name : :token ,
type : String ,
desc : 'Drone CI token'
} ,
{
required : true ,
name : :drone_url ,
type : String ,
desc : 'Drone CI URL'
} ,
{
required : false ,
name : :enable_ssl_verification ,
type : Boolean ,
desc : 'Enable SSL verification for communication'
}
] ,
'emails-on-push' = > [
{
required : true ,
name : :recipients ,
type : String ,
desc : 'Comma-separated list of recipient email addresses'
} ,
{
required : false ,
name : :disable_diffs ,
type : Boolean ,
desc : 'Disable code diffs'
} ,
{
required : false ,
name : :send_from_committer_email ,
type : Boolean ,
desc : 'Send from committer'
}
] ,
'external-wiki' = > [
{
required : true ,
name : :external_wiki_url ,
type : String ,
desc : 'The URL of the external Wiki'
}
] ,
'flowdock' = > [
{
required : true ,
name : :token ,
type : String ,
desc : 'Flowdock token'
}
] ,
'gemnasium' = > [
{
required : true ,
name : :api_key ,
type : String ,
desc : 'Your personal API key on gemnasium.com'
} ,
{
required : true ,
name : :token ,
type : String ,
desc : " The project's slug on gemnasium.com "
}
] ,
'hipchat' = > [
{
required : true ,
name : :token ,
type : String ,
desc : 'The room token'
} ,
{
required : false ,
name : :room ,
type : String ,
desc : 'The room name or ID'
} ,
{
required : false ,
name : :color ,
type : String ,
desc : 'The room color'
} ,
{
required : false ,
name : :notify ,
type : Boolean ,
desc : 'Enable notifications'
} ,
{
required : false ,
name : :api_version ,
type : String ,
desc : 'Leave blank for default (v2)'
} ,
{
required : false ,
name : :server ,
type : String ,
desc : 'Leave blank for default. https://hipchat.example.com'
}
] ,
'irker' = > [
{
required : true ,
name : :recipients ,
type : String ,
desc : 'Recipients/channels separated by whitespaces'
} ,
{
required : false ,
name : :default_irc_uri ,
type : String ,
desc : 'Default: irc://irc.network.net:6697'
} ,
{
required : false ,
name : :server_host ,
type : String ,
desc : 'Server host. Default localhost'
} ,
{
required : false ,
name : :server_port ,
type : Integer ,
desc : 'Server port. Default 6659'
} ,
{
required : false ,
name : :colorize_messages ,
type : Boolean ,
desc : 'Colorize messages'
}
] ,
'jira' = > [
{
required : true ,
name : :url ,
type : String ,
2017-05-23 05:14:43 -04:00
desc : 'The base URL to the JIRA instance web interface which is being linked to this GitLab project. E.g., https://jira.example.com'
} ,
{
required : false ,
name : :api_url ,
type : String ,
desc : 'The base URL to the JIRA instance API. Web URL value will be used if not set. E.g., https://jira-api.example.com'
2016-12-05 09:40:53 -05:00
} ,
{
required : true ,
name : :project_key ,
type : String ,
desc : 'The short identifier for your JIRA project, all uppercase, e.g., PROJ'
} ,
{
required : false ,
name : :username ,
type : String ,
desc : 'The username of the user created to be used with GitLab/JIRA'
} ,
{
required : false ,
name : :password ,
type : String ,
desc : 'The password of the user created to be used with GitLab/JIRA'
} ,
{
required : false ,
name : :jira_issue_transition_id ,
type : Integer ,
desc : 'The ID of a transition that moves issues to a closed state. You can find this number under the JIRA workflow administration (**Administration > Issues > Workflows**) by selecting **View** under **Operations** of the desired workflow of your project. The ID of each state can be found inside the parenthesis of each transition name under the **Transitions (id)** column ([see screenshot][trans]). By default, this ID is set to `2`'
}
] ,
2016-12-08 11:36:26 -05:00
'kubernetes' = > [
{
required : true ,
name : :namespace ,
type : String ,
desc : 'The Kubernetes namespace to use'
} ,
{
required : true ,
name : :api_url ,
type : String ,
desc : 'The URL to the Kubernetes cluster API, e.g., https://kubernetes.example.com'
} ,
{
required : true ,
name : :token ,
type : String ,
desc : 'The service token to authenticate against the Kubernetes cluster with'
} ,
{
required : false ,
name : :ca_pem ,
type : String ,
desc : 'A custom certificate authority bundle to verify the Kubernetes cluster with (PEM format)'
2017-05-03 07:22:03 -04:00
}
2016-12-08 11:36:26 -05:00
] ,
2016-12-05 09:40:53 -05:00
'mattermost-slash-commands' = > [
{
required : true ,
name : :token ,
type : String ,
desc : 'The Mattermost token'
}
] ,
2016-12-19 09:40:06 -05:00
'slack-slash-commands' = > [
{
required : true ,
name : :token ,
type : String ,
desc : 'The Slack token'
}
] ,
2016-12-05 09:40:53 -05:00
'pipelines-email' = > [
{
required : true ,
name : :recipients ,
type : String ,
desc : 'Comma-separated list of recipient email addresses'
} ,
{
required : false ,
2017-03-17 19:06:11 -04:00
name : :notify_only_broken_pipelines ,
2016-12-05 09:40:53 -05:00
type : Boolean ,
2017-03-17 19:06:11 -04:00
desc : 'Notify only broken pipelines'
2016-12-05 09:40:53 -05:00
}
] ,
'pivotaltracker' = > [
{
required : true ,
name : :token ,
type : String ,
desc : 'The Pivotaltracker token'
} ,
{
required : false ,
name : :restrict_to_branch ,
type : String ,
desc : 'Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches.'
}
] ,
2017-03-07 11:57:42 -05:00
'prometheus' = > [
{
required : true ,
name : :api_url ,
type : String ,
desc : 'Prometheus API Base URL, like http://prometheus.example.com/'
}
] ,
2016-12-05 09:40:53 -05:00
'pushover' = > [
{
required : true ,
name : :api_key ,
type : String ,
desc : 'The application key'
} ,
{
required : true ,
name : :user_key ,
type : String ,
desc : 'The user key'
} ,
{
required : true ,
name : :priority ,
type : String ,
desc : 'The priority'
} ,
{
required : true ,
name : :device ,
type : String ,
desc : 'Leave blank for all active devices'
} ,
{
required : true ,
name : :sound ,
type : String ,
desc : 'The sound of the notification'
}
] ,
'redmine' = > [
{
required : true ,
name : :new_issue_url ,
type : String ,
desc : 'The new issue URL'
} ,
{
required : true ,
name : :project_url ,
type : String ,
desc : 'The project URL'
} ,
{
required : true ,
name : :issues_url ,
type : String ,
desc : 'The issues URL'
} ,
{
required : false ,
name : :description ,
type : String ,
desc : 'The description of the tracker'
}
] ,
2016-12-20 16:14:33 -05:00
'slack' = > [
2016-12-05 09:40:53 -05:00
{
required : true ,
name : :webhook ,
type : String ,
desc : 'The Slack webhook. e.g. https://hooks.slack.com/services/...'
} ,
{
required : false ,
name : :new_issue_url ,
type : String ,
desc : 'The user name'
} ,
{
required : false ,
name : :channel ,
type : String ,
desc : 'The channel name'
}
] ,
2017-04-04 11:10:21 -04:00
'microsoft-teams' = > [
{
required : true ,
name : :webhook ,
type : String ,
desc : 'The Microsoft Teams webhook. e.g. https://outlook.office.com/webhook/…'
}
] ,
2016-12-20 16:29:39 -05:00
'mattermost' = > [
2016-12-06 12:59:03 -05:00
{
required : true ,
name : :webhook ,
type : String ,
desc : 'The Mattermost webhook. e.g. http://mattermost_host/hooks/...'
}
] ,
2016-12-05 09:40:53 -05:00
'teamcity' = > [
{
required : true ,
name : :teamcity_url ,
type : String ,
desc : 'TeamCity root URL like https://teamcity.example.com'
} ,
{
required : true ,
name : :build_type ,
type : String ,
desc : 'Build configuration ID'
} ,
{
required : true ,
name : :username ,
type : String ,
desc : 'A user with permissions to trigger a manual build'
} ,
{
required : true ,
name : :password ,
type : String ,
desc : 'The password of the user'
}
]
2016-12-27 07:44:24 -05:00
}
service_classes = [
AsanaService ,
AssemblaService ,
BambooService ,
BugzillaService ,
BuildkiteService ,
CampfireService ,
CustomIssueTrackerService ,
DroneCiService ,
EmailsOnPushService ,
ExternalWikiService ,
FlowdockService ,
GemnasiumService ,
HipchatService ,
IrkerService ,
JiraService ,
KubernetesService ,
MattermostSlashCommandsService ,
SlackSlashCommandsService ,
PipelinesEmailService ,
PivotaltrackerService ,
2017-03-07 11:57:42 -05:00
PrometheusService ,
2016-12-27 07:44:24 -05:00
PushoverService ,
RedmineService ,
SlackService ,
MattermostService ,
2017-04-04 11:10:21 -04:00
MicrosoftTeamsService ,
2017-05-03 07:22:03 -04:00
TeamcityService
2017-02-14 20:52:44 -05:00
]
if Rails . env . development?
services [ 'mock-ci' ] = [
{
required : true ,
name : :mock_service_url ,
type : String ,
desc : 'URL to the mock service'
}
]
2017-04-05 07:04:34 -04:00
services [ 'mock-deployment' ] = [ ]
services [ 'mock-monitoring' ] = [ ]
2017-02-14 20:52:44 -05:00
2017-04-05 07:04:34 -04:00
service_classes += [
MockCiService ,
MockDeploymentService ,
2017-05-03 07:22:03 -04:00
MockMonitoringService
2017-04-05 07:04:34 -04:00
]
2017-02-14 20:52:44 -05:00
end
2016-12-05 09:40:53 -05:00
trigger_services = {
'mattermost-slash-commands' = > [
{
name : :token ,
type : String ,
desc : 'The Mattermost token'
}
2016-12-29 04:48:18 -05:00
] ,
'slack-slash-commands' = > [
{
name : :token ,
type : String ,
desc : 'The Slack token'
}
2016-12-05 09:40:53 -05:00
]
} . freeze
2017-03-15 14:09:24 -04:00
params do
requires :id , type : String , desc : 'The ID of a project'
end
resource :projects , requirements : { id : %r{ [^/]+ } } do
2016-11-14 09:10:35 -05:00
before { authenticate! }
before { authorize_admin_project }
2016-12-05 09:40:53 -05:00
helpers do
def service_attributes ( service )
service . fields . inject ( [ ] ) do | arr , hash |
arr << hash [ :name ] . to_sym
2015-08-26 19:58:49 -04:00
end
2016-12-05 09:40:53 -05:00
end
end
2014-10-14 13:07:34 -04:00
2016-12-05 09:40:53 -05:00
services . each do | service_slug , settings |
desc " Set #{ service_slug } service for project "
params do
2016-12-27 07:44:24 -05:00
service_classes . each do | service |
2017-03-06 04:24:03 -05:00
event_names = service . try ( :event_names ) || next
2016-12-27 07:44:24 -05:00
event_names . each do | event_name |
2017-01-12 17:33:04 -05:00
services [ service . to_param . tr ( " _ " , " - " ) ] << {
2016-12-27 07:44:24 -05:00
required : false ,
name : event_name . to_sym ,
type : String ,
2017-01-12 17:33:04 -05:00
desc : ServicesHelper . service_event_description ( event_name )
2016-12-27 07:44:24 -05:00
}
end
end
services . freeze
2016-12-05 09:40:53 -05:00
settings . each do | setting |
if setting [ :required ]
requires setting [ :name ] , type : setting [ :type ] , desc : setting [ :desc ]
else
optional setting [ :name ] , type : setting [ :type ] , desc : setting [ :desc ]
end
end
end
put " :id/services/ #{ service_slug } " do
service = user_project . find_or_initialize_service ( service_slug . underscore )
service_params = declared_params ( include_missing : false ) . merge ( active : true )
2014-10-14 13:07:34 -04:00
2016-12-05 09:40:53 -05:00
if service . update_attributes ( service_params )
2017-04-08 22:20:57 -04:00
present service , with : Entities :: ProjectService , include_passwords : current_user . admin?
2015-08-26 19:58:49 -04:00
else
2016-12-05 09:40:53 -05:00
render_api_error! ( '400 Bad Request' , 400 )
2015-08-26 19:58:49 -04:00
end
2014-10-14 13:07:34 -04:00
end
end
2016-12-05 09:40:53 -05:00
desc " Delete a service for project "
params do
requires :service_slug , type : String , values : services . keys , desc : 'The name of the service'
end
delete " :id/services/:service_slug " do
service = user_project . find_or_initialize_service ( params [ :service_slug ] . underscore )
2015-09-11 07:38:37 -04:00
2016-12-05 09:40:53 -05:00
attrs = service_attributes ( service ) . inject ( { } ) do | hash , key |
hash . merge! ( key = > nil )
end
2017-02-20 13:18:12 -05:00
unless service . update_attributes ( attrs . merge ( active : false ) )
2016-12-05 09:40:53 -05:00
render_api_error! ( '400 Bad Request' , 400 )
2014-10-14 13:07:34 -04:00
end
end
2015-09-03 09:38:54 -04:00
2016-12-05 09:40:53 -05:00
desc 'Get the service settings for project' do
success Entities :: ProjectService
end
params do
requires :service_slug , type : String , values : services . keys , desc : 'The name of the service'
end
get " :id/services/:service_slug " do
service = user_project . find_or_initialize_service ( params [ :service_slug ] . underscore )
2017-04-08 22:20:57 -04:00
present service , with : Entities :: ProjectService , include_passwords : current_user . admin?
2015-09-03 09:38:54 -04:00
end
2013-10-29 10:39:46 -04:00
end
2016-11-14 09:10:35 -05:00
2016-12-05 09:40:53 -05:00
trigger_services . each do | service_slug , settings |
2017-01-30 06:29:55 -05:00
helpers do
def chat_command_service ( project , service_slug , params )
project . services . active . where ( template : false ) . find do | service |
service . try ( :token ) == params [ :token ] && service . to_param == service_slug . underscore
end
end
end
2016-12-05 09:40:53 -05:00
params do
requires :id , type : String , desc : 'The ID of a project'
2016-11-17 06:06:45 -05:00
end
2017-03-15 14:09:24 -04:00
resource :projects , requirements : { id : %r{ [^/]+ } } do
2016-12-05 09:40:53 -05:00
desc " Trigger a slash command for #{ service_slug } " do
detail 'Added in GitLab 8.13'
end
params do
settings . each do | setting |
requires setting [ :name ] , type : setting [ :type ] , desc : setting [ :desc ]
end
end
post " :id/services/ #{ service_slug . underscore } /trigger " do
project = find_project ( params [ :id ] )
2016-11-14 09:10:35 -05:00
2016-12-05 09:40:53 -05:00
# This is not accurate, but done to prevent leakage of the project names
not_found! ( 'Service' ) unless project
2016-11-18 05:38:54 -05:00
2017-01-30 06:29:55 -05:00
service = chat_command_service ( project , service_slug , params )
result = service . try ( :trigger , params )
2016-11-14 09:10:35 -05:00
2016-12-05 09:40:53 -05:00
if result
status result [ :status ] || 200
present result
else
not_found! ( 'Service' )
end
2016-11-14 09:10:35 -05:00
end
end
end
2013-10-29 10:39:46 -04:00
end
end