Commit 948bb655 authored by Kamil Trzciński's avatar Kamil Trzciński

Merge branch 'ci/api-triggers' into 'master'

Add triggers API

References #4264

See merge request !2286
parents 0192903b 96aeaeaf
......@@ -50,8 +50,9 @@ v 8.4.0 (unreleased)
- Allow subsequent validations in CI Linter
- Show referenced MRs & Issues only when the current viewer can access them
- Fix Encoding::CompatibilityError bug when markdown content has some complex URL (Jason Lee)
- Add API support for managing builds of a project
- Add API support for managing build variables of project
- Add API support for managing project's builds
- Add API support for managing project's build triggers
- Add API support for managing project's build variables
- Allow broadcast messages to be edited
- Autosize Markdown textareas
- Import GitHub wiki into GitLab
......
......@@ -33,6 +33,10 @@ module Ci
trigger_requests.last
end
def last_used
last_trigger_request.try(:created_at)
end
def short_token
token[0...10]
end
......
......@@ -24,6 +24,7 @@
- [Settings](settings.md)
- [Keys](keys.md)
- [Builds](builds.md)
- [Build triggers](build_triggers.md)
- [Build Variables](build_variables.md)
## Clients
......
# Build triggers
You can read more about [triggering builds through the API](../ci/triggers/README.md).
## List project triggers
Get a list of project's build triggers.
```
GET /projects/:id/triggers
```
| Attribute | Type | required | Description |
|-----------|---------|----------|---------------------|
| `id` | integer | yes | The ID of a project |
```
curl -H "PRIVATE_TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/triggers"
```
```json
[
{
"created_at": "2015-12-23T16:24:34.716Z",
"deleted_at": null,
"last_used": "2016-01-04T15:41:21.986Z",
"token": "fbdb730c2fbdb095a0862dbd8ab88b",
"updated_at": "2015-12-23T16:24:34.716Z"
},
{
"created_at": "2015-12-23T16:25:56.760Z",
"deleted_at": null,
"last_used": null,
"token": "7b9148c158980bbd9bcea92c17522d",
"updated_at": "2015-12-23T16:25:56.760Z"
}
]
```
## Get trigger details
Get details of project's build trigger.
```
GET /projects/:id/triggers/:token
```
| Attribute | Type | required | Description |
|-----------|---------|----------|--------------------------|
| `id` | integer | yes | The ID of a project |
| `token` | string | yes | The `token` of a trigger |
```
curl -H "PRIVATE_TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/triggers/7b9148c158980bbd9bcea92c17522d"
```
```json
{
"created_at": "2015-12-23T16:25:56.760Z",
"deleted_at": null,
"last_used": null,
"token": "7b9148c158980bbd9bcea92c17522d",
"updated_at": "2015-12-23T16:25:56.760Z"
}
```
## Create a project trigger
Create a build trigger for a project.
```
POST /projects/:id/triggers
```
| Attribute | Type | required | Description |
|-----------|---------|----------|--------------------------|
| `id` | integer | yes | The ID of a project |
```
curl -X POST -H "PRIVATE_TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/triggers"
```
```json
{
"created_at": "2016-01-07T09:53:58.235Z",
"deleted_at": null,
"last_used": null,
"token": "6d056f63e50fe6f8c5f8f4aa10edb7",
"updated_at": "2016-01-07T09:53:58.235Z"
}
```
## Remove a project trigger
Remove a project's build trigger.
```
DELETE /projects/:id/triggers/:token
```
| Attribute | Type | required | Description |
|-----------|---------|----------|--------------------------|
| `id` | integer | yes | The ID of a project |
| `token` | string | yes | The `token` of a project |
```
curl -X DELETE -H "PRIVATE_TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/triggers/7b9148c158980bbd9bcea92c17522d"
```
......@@ -394,6 +394,10 @@ module API
expose :runner, with: Runner
end
class Trigger < Grape::Entity
expose :token, :created_at, :updated_at, :deleted_at, :last_used
end
class Variable < Grape::Entity
expose :key, :value
end
......
......@@ -43,6 +43,75 @@ module API
render_api_error!(errors, 400)
end
end
# Get triggers list
#
# Parameters:
# id (required) - The ID of a project
# page (optional) - The page number for pagination
# per_page (optional) - The value of items per page to show
# Example Request:
# GET /projects/:id/triggers
get ':id/triggers' do
authenticate!
authorize_admin_project
triggers = user_project.triggers.includes(:trigger_requests)
triggers = paginate(triggers)
present triggers, with: Entities::Trigger
end
# Get specific trigger of a project
#
# Parameters:
# id (required) - The ID of a project
# token (required) - The `token` of a trigger
# Example Request:
# GET /projects/:id/triggers/:token
get ':id/triggers/:token' do
authenticate!
authorize_admin_project
trigger = user_project.triggers.find_by(token: params[:token].to_s)
return not_found!('Trigger') unless trigger
present trigger, with: Entities::Trigger
end
# Create trigger
#
# Parameters:
# id (required) - The ID of a project
# Example Request:
# POST /projects/:id/triggers
post ':id/triggers' do
authenticate!
authorize_admin_project
trigger = user_project.triggers.create
present trigger, with: Entities::Trigger
end
# Delete trigger
#
# Parameters:
# id (required) - The ID of a project
# token (required) - The `token` of a trigger
# Example Request:
# DELETE /projects/:id/triggers/:token
delete ':id/triggers/:token' do
authenticate!
authorize_admin_project
trigger = user_project.triggers.find_by(token: params[:token].to_s)
return not_found!('Trigger') unless trigger
trigger.destroy
present trigger, with: Entities::Trigger
end
end
end
end
......@@ -3,6 +3,8 @@
FactoryGirl.define do
factory :ci_trigger_request, class: Ci::TriggerRequest do
factory :ci_trigger_request_with_variables do
trigger factory: :ci_trigger
variables do
{
TRIGGER_KEY: 'TRIGGER_VALUE'
......
......@@ -3,11 +3,19 @@ require 'spec_helper'
describe API::API do
include ApiHelpers
let(:user) { create(:user) }
let(:user2) { create(:user) }
let!(:trigger_token) { 'secure_token' }
let!(:trigger_token_2) { 'secure_token_2' }
let!(:project) { create(:project, creator_id: user.id) }
let!(:master) { create(:project_member, user: user, project: project, access_level: ProjectMember::MASTER) }
let!(:developer) { create(:project_member, user: user2, project: project, access_level: ProjectMember::DEVELOPER) }
let!(:trigger) { create(:ci_trigger, project: project, token: trigger_token) }
let!(:trigger2) { create(:ci_trigger, project: project, token: trigger_token_2) }
let!(:trigger_request) { create(:ci_trigger_request, trigger: trigger, created_at: '2015-01-01 12:13:14') }
describe 'POST /projects/:project_id/trigger' do
let!(:trigger_token) { 'secure token' }
let!(:project) { FactoryGirl.create(:project) }
let!(:project2) { FactoryGirl.create(:empty_project) }
let!(:trigger) { FactoryGirl.create(:ci_trigger, project: project, token: trigger_token) }
let!(:project2) { create(:empty_project) }
let(:options) do
{
token: trigger_token
......@@ -77,4 +85,127 @@ describe API::API do
end
end
end
describe 'GET /projects/:id/triggers' do
context 'authenticated user with valid permissions' do
it 'should return list of triggers' do
get api("/projects/#{project.id}/triggers", user)
expect(response.status).to eq(200)
expect(json_response).to be_a(Array)
expect(json_response[0]).to have_key('token')
end
end
context 'authenticated user with invalid permissions' do
it 'should not return triggers list' do
get api("/projects/#{project.id}/triggers", user2)
expect(response.status).to eq(403)
end
end
context 'unauthenticated user' do
it 'should not return triggers list' do
get api("/projects/#{project.id}/triggers")
expect(response.status).to eq(401)
end
end
end
describe 'GET /projects/:id/triggers/:token' do
context 'authenticated user with valid permissions' do
it 'should return trigger details' do
get api("/projects/#{project.id}/triggers/#{trigger.token}", user)
expect(response.status).to eq(200)
expect(json_response).to be_a(Hash)
end
it 'should respond with 404 Not Found if requesting non-existing trigger' do
get api("/projects/#{project.id}/triggers/abcdef012345", user)
expect(response.status).to eq(404)
end
end
context 'authenticated user with invalid permissions' do
it 'should not return triggers list' do
get api("/projects/#{project.id}/triggers/#{trigger.token}", user2)
expect(response.status).to eq(403)
end
end
context 'unauthenticated user' do
it 'should not return triggers list' do
get api("/projects/#{project.id}/triggers/#{trigger.token}")
expect(response.status).to eq(401)
end
end
end
describe 'POST /projects/:id/triggers' do
context 'authenticated user with valid permissions' do
it 'should create trigger' do
expect do
post api("/projects/#{project.id}/triggers", user)
end.to change{project.triggers.count}.by(1)
expect(response.status).to eq(201)
expect(json_response).to be_a(Hash)
end
end
context 'authenticated user with invalid permissions' do
it 'should not create trigger' do
post api("/projects/#{project.id}/triggers", user2)
expect(response.status).to eq(403)
end
end
context 'unauthenticated user' do
it 'should not create trigger' do
post api("/projects/#{project.id}/triggers")
expect(response.status).to eq(401)
end
end
end
describe 'DELETE /projects/:id/triggers/:token' do
context 'authenticated user with valid permissions' do
it 'should delete trigger' do
expect do
delete api("/projects/#{project.id}/triggers/#{trigger.token}", user)
end.to change{project.triggers.count}.by(-1)
expect(response.status).to eq(200)
end
it 'should respond with 404 Not Found if requesting non-existing trigger' do
delete api("/projects/#{project.id}/triggers/abcdef012345", user)
expect(response.status).to eq(404)
end
end
context 'authenticated user with invalid permissions' do
it 'should not delete trigger' do
delete api("/projects/#{project.id}/triggers/#{trigger.token}", user2)
expect(response.status).to eq(403)
end
end
context 'unauthenticated user' do
it 'should not delete trigger' do
delete api("/projects/#{project.id}/triggers/#{trigger.token}")
expect(response.status).to eq(401)
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment