Add GET /projects/:id/pipelines/:pipeline_id/jobs endpoint
Add endpoint to get the jobs scoped to a pipeline.
This commit is contained in:
parent
7f2819b778
commit
f372400673
4 changed files with 210 additions and 1 deletions
4
changelogs/unreleased/tc-api-pipeline-jobs.yml
Normal file
4
changelogs/unreleased/tc-api-pipeline-jobs.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Add GET /projects/:id/pipelines/:pipeline_id/jobs endpoint
|
||||
merge_request: 9727
|
||||
author:
|
118
doc/api/jobs.md
118
doc/api/jobs.md
|
@ -1,6 +1,6 @@
|
|||
# Jobs API
|
||||
|
||||
## List project jobs
|
||||
## List project jobs
|
||||
|
||||
Get a list of jobs in a project.
|
||||
|
||||
|
@ -115,6 +115,122 @@ Example of response
|
|||
]
|
||||
```
|
||||
|
||||
## List pipeline jobs
|
||||
|
||||
Get a list of jobs for a pipeline.
|
||||
|
||||
```
|
||||
GET /projects/:id/pipeline/:pipeline_id/jobs
|
||||
```
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
|--------------|--------------------------------|----------|----------------------|
|
||||
| `id` | integer | yes | The ID of a project |
|
||||
| `pipelin_id` | integer | yes | The ID of a pipeline |
|
||||
| `scope` | string **or** array of strings | no | The scope of jobs to show, one or array of: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`; showing all jobs if none provided |
|
||||
|
||||
```
|
||||
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" 'https://gitlab.example.com/api/v4/projects/1/pipelines/6/jobs?scope%5B0%5D=pending&scope%5B1%5D=running'
|
||||
```
|
||||
|
||||
Example of response
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"commit": {
|
||||
"author_email": "admin@example.com",
|
||||
"author_name": "Administrator",
|
||||
"created_at": "2015-12-24T16:51:14.000+01:00",
|
||||
"id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
|
||||
"message": "Test the CI integration.",
|
||||
"short_id": "0ff3ae19",
|
||||
"title": "Test the CI integration."
|
||||
},
|
||||
"coverage": null,
|
||||
"created_at": "2015-12-24T15:51:21.802Z",
|
||||
"artifacts_file": {
|
||||
"filename": "artifacts.zip",
|
||||
"size": 1000
|
||||
},
|
||||
"finished_at": "2015-12-24T17:54:27.895Z",
|
||||
"id": 7,
|
||||
"name": "teaspoon",
|
||||
"pipeline": {
|
||||
"id": 6,
|
||||
"ref": "master",
|
||||
"sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
|
||||
"status": "pending"
|
||||
},
|
||||
"ref": "master",
|
||||
"runner": null,
|
||||
"stage": "test",
|
||||
"started_at": "2015-12-24T17:54:27.722Z",
|
||||
"status": "failed",
|
||||
"tag": false,
|
||||
"user": {
|
||||
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
|
||||
"bio": null,
|
||||
"created_at": "2015-12-21T13:14:24.077Z",
|
||||
"id": 1,
|
||||
"is_admin": true,
|
||||
"linkedin": "",
|
||||
"name": "Administrator",
|
||||
"skype": "",
|
||||
"state": "active",
|
||||
"twitter": "",
|
||||
"username": "root",
|
||||
"web_url": "http://gitlab.dev/root",
|
||||
"website_url": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"commit": {
|
||||
"author_email": "admin@example.com",
|
||||
"author_name": "Administrator",
|
||||
"created_at": "2015-12-24T16:51:14.000+01:00",
|
||||
"id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
|
||||
"message": "Test the CI integration.",
|
||||
"short_id": "0ff3ae19",
|
||||
"title": "Test the CI integration."
|
||||
},
|
||||
"coverage": null,
|
||||
"created_at": "2015-12-24T15:51:21.727Z",
|
||||
"artifacts_file": null,
|
||||
"finished_at": "2015-12-24T17:54:24.921Z",
|
||||
"id": 6,
|
||||
"name": "spinach:other",
|
||||
"pipeline": {
|
||||
"id": 6,
|
||||
"ref": "master",
|
||||
"sha": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd",
|
||||
"status": "pending"
|
||||
},
|
||||
"ref": "master",
|
||||
"runner": null,
|
||||
"stage": "test",
|
||||
"started_at": "2015-12-24T17:54:24.729Z",
|
||||
"status": "failed",
|
||||
"tag": false,
|
||||
"user": {
|
||||
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
|
||||
"bio": null,
|
||||
"created_at": "2015-12-21T13:14:24.077Z",
|
||||
"id": 1,
|
||||
"is_admin": true,
|
||||
"linkedin": "",
|
||||
"name": "Administrator",
|
||||
"skype": "",
|
||||
"state": "active",
|
||||
"twitter": "",
|
||||
"username": "root",
|
||||
"web_url": "http://gitlab.dev/root",
|
||||
"website_url": ""
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Get a single job
|
||||
|
||||
Get a single job of a project
|
||||
|
|
|
@ -40,6 +40,23 @@ module API
|
|||
user_can_download_artifacts: can?(current_user, :read_build, user_project)
|
||||
end
|
||||
|
||||
desc 'Get pipeline jobs' do
|
||||
success Entities::Job
|
||||
end
|
||||
params do
|
||||
requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
|
||||
use :optional_scope
|
||||
use :pagination
|
||||
end
|
||||
get ':id/pipelines/:pipeline_id/jobs' do
|
||||
pipeline = user_project.pipelines.find(params[:pipeline_id])
|
||||
builds = pipeline.builds
|
||||
builds = filter_builds(builds, params[:scope])
|
||||
|
||||
present paginate(builds), with: Entities::Job,
|
||||
user_can_download_artifacts: can?(current_user, :read_build, user_project)
|
||||
end
|
||||
|
||||
desc 'Get a specific job of a project' do
|
||||
success Entities::Job
|
||||
end
|
||||
|
|
|
@ -75,6 +75,78 @@ describe API::Jobs, api: true do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'GET /projects/:id/pipelines/:pipeline_id/jobs' do
|
||||
let(:query) { Hash.new }
|
||||
|
||||
before do
|
||||
get api("/projects/#{project.id}/pipelines/#{pipeline.id}/jobs", api_user), query
|
||||
end
|
||||
|
||||
context 'authorized user' do
|
||||
it 'returns pipeline jobs' do
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response).to include_pagination_headers
|
||||
expect(json_response).to be_an Array
|
||||
end
|
||||
|
||||
it 'returns correct values' do
|
||||
expect(json_response).not_to be_empty
|
||||
expect(json_response.first['commit']['id']).to eq project.commit.id
|
||||
end
|
||||
|
||||
it 'returns pipeline data' do
|
||||
json_build = json_response.first
|
||||
|
||||
expect(json_build['pipeline']).not_to be_empty
|
||||
expect(json_build['pipeline']['id']).to eq build.pipeline.id
|
||||
expect(json_build['pipeline']['ref']).to eq build.pipeline.ref
|
||||
expect(json_build['pipeline']['sha']).to eq build.pipeline.sha
|
||||
expect(json_build['pipeline']['status']).to eq build.pipeline.status
|
||||
end
|
||||
|
||||
context 'filter jobs with one scope element' do
|
||||
let(:query) { { 'scope' => 'pending' } }
|
||||
|
||||
it do
|
||||
expect(response).to have_http_status(200)
|
||||
expect(json_response).to be_an Array
|
||||
end
|
||||
end
|
||||
|
||||
context 'filter jobs with array of scope elements' do
|
||||
let(:query) { { 'scope[0]' => 'pending', 'scope[1]' => 'running' } }
|
||||
|
||||
it do
|
||||
expect(response).to have_http_status(200)
|
||||
expect(json_response).to be_an Array
|
||||
end
|
||||
end
|
||||
|
||||
context 'respond 400 when scope contains invalid state' do
|
||||
let(:query) { { 'scope[0]' => 'unknown', 'scope[1]' => 'running' } }
|
||||
|
||||
it { expect(response).to have_http_status(400) }
|
||||
end
|
||||
|
||||
context 'jobs in different pipelines' do
|
||||
let!(:pipeline2) { create(:ci_empty_pipeline, project: project) }
|
||||
let!(:build2) { create(:ci_build, pipeline: pipeline2) }
|
||||
|
||||
it 'excludes jobs from other pipelines' do
|
||||
json_response.each { |job| expect(job['pipeline']['id']).to eq(pipeline.id) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'unauthorized user' do
|
||||
let(:api_user) { nil }
|
||||
|
||||
it 'does not return jobs' do
|
||||
expect(response).to have_http_status(401)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /projects/:id/jobs/:job_id' do
|
||||
before do
|
||||
get api("/projects/#{project.id}/jobs/#{build.id}", api_user)
|
||||
|
|
Loading…
Reference in a new issue