Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Léo-Paul Géneau
gitlab-ce
Commits
111748ea
Commit
111748ea
authored
Feb 22, 2017
by
Z.J. van de Weg
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Rename Builds to Jobs in the API
Fixes gitlab-org/gitlab-ce#28515 [ci skip]
parent
348dff0a
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
827 additions
and
69 deletions
+827
-69
lib/api/api.rb
lib/api/api.rb
+2
-1
lib/api/entities.rb
lib/api/entities.rb
+15
-9
lib/api/jobs.rb
lib/api/jobs.rb
+59
-58
lib/api/v3/builds.rb
lib/api/v3/builds.rb
+263
-0
lib/api/v3/entities.rb
lib/api/v3/entities.rb
+10
-0
spec/requests/api/jobs_spec.rb
spec/requests/api/jobs_spec.rb
+477
-0
spec/requests/api/v3/builds_spec.rb
spec/requests/api/v3/builds_spec.rb
+1
-1
No files found.
lib/api/api.rb
View file @
111748ea
...
...
@@ -9,6 +9,7 @@ module API
mount
::
API
::
V3
::
Boards
mount
::
API
::
V3
::
Branches
mount
::
API
::
V3
::
BroadcastMessages
mount
::
API
::
V3
::
Builds
mount
::
API
::
V3
::
Commits
mount
::
API
::
V3
::
DeployKeys
mount
::
API
::
V3
::
Environments
...
...
@@ -77,7 +78,6 @@ module API
mount
::
API
::
Boards
mount
::
API
::
Branches
mount
::
API
::
BroadcastMessages
mount
::
API
::
Builds
mount
::
API
::
Commits
mount
::
API
::
CommitStatuses
mount
::
API
::
DeployKeys
...
...
@@ -87,6 +87,7 @@ module API
mount
::
API
::
Groups
mount
::
API
::
Internal
mount
::
API
::
Issues
mount
::
API
::
Jobs
mount
::
API
::
Keys
mount
::
API
::
Labels
mount
::
API
::
Lint
...
...
lib/api/entities.rb
View file @
111748ea
...
...
@@ -49,7 +49,8 @@ module API
class
ProjectHook
<
Hook
expose
:project_id
,
:issues_events
,
:merge_requests_events
expose
:note_events
,
:build_events
,
:pipeline_events
,
:wiki_page_events
expose
:note_events
,
:pipeline_events
,
:wiki_page_events
expose
:job_events
,
as: :build_events
end
class
BasicProjectDetails
<
Grape
::
Entity
...
...
@@ -80,7 +81,7 @@ module API
expose
(
:issues_enabled
)
{
|
project
,
options
|
project
.
feature_available?
(
:issues
,
options
[
:current_user
])
}
expose
(
:merge_requests_enabled
)
{
|
project
,
options
|
project
.
feature_available?
(
:merge_requests
,
options
[
:current_user
])
}
expose
(
:wiki_enabled
)
{
|
project
,
options
|
project
.
feature_available?
(
:wiki
,
options
[
:current_user
])
}
expose
(
:
build
s_enabled
)
{
|
project
,
options
|
project
.
feature_available?
(
:builds
,
options
[
:current_user
])
}
expose
(
:
job
s_enabled
)
{
|
project
,
options
|
project
.
feature_available?
(
:builds
,
options
[
:current_user
])
}
expose
(
:snippets_enabled
)
{
|
project
,
options
|
project
.
feature_available?
(
:snippets
,
options
[
:current_user
])
}
expose
:created_at
,
:last_activity_at
...
...
@@ -93,7 +94,7 @@ module API
expose
:star_count
,
:forks_count
expose
:open_issues_count
,
if:
lambda
{
|
project
,
options
|
project
.
feature_available?
(
:issues
,
options
[
:current_user
])
&&
project
.
default_issues_tracker?
}
expose
:runners_token
,
if:
lambda
{
|
_project
,
options
|
options
[
:user_can_admin_project
]
}
expose
:public_builds
expose
:public_
jobs
,
as: :public_
builds
expose
:shared_with_groups
do
|
project
,
options
|
SharedGroup
.
represent
(
project
.
project_group_links
.
all
,
options
)
end
...
...
@@ -109,7 +110,7 @@ module API
expose
:storage_size
expose
:repository_size
expose
:lfs_objects_size
expose
:build_artifacts_size
expose
:
job_artifacts_size
,
as: :
build_artifacts_size
end
class
Member
<
UserBasic
...
...
@@ -144,7 +145,7 @@ module API
expose
:storage_size
expose
:repository_size
expose
:lfs_objects_size
expose
:build_artifacts_size
expose
:
job_artifacts_size
,
as: :
build_artifacts_size
end
end
end
...
...
@@ -448,7 +449,8 @@ module API
class
ProjectService
<
Grape
::
Entity
expose
:id
,
:title
,
:created_at
,
:updated_at
,
:active
expose
:push_events
,
:issues_events
,
:merge_requests_events
expose
:tag_push_events
,
:note_events
,
:build_events
,
:pipeline_events
expose
:tag_push_events
,
:note_events
,
:pipeline_events
expose
:job_events
,
as: :build_events
# Expose serialized properties
expose
:properties
do
|
service
,
options
|
field_names
=
service
.
fields
.
...
...
@@ -616,11 +618,15 @@ module API
end
end
<<<<<<<
HEAD
class
RunnerRegistrationDetails
<
Grape
::
Entity
expose
:id
,
:token
end
class
BuildArtifactFile
<
Grape
::
Entity
=======
class
JobArtifactFile
<
Grape
::
Entity
>>>>>>>
239
b5f49c5
...
Rename
Builds
to
Jobs
in
the
API
expose
:filename
,
:size
end
...
...
@@ -628,11 +634,11 @@ module API
expose
:id
,
:sha
,
:ref
,
:status
end
class
Build
<
Grape
::
Entity
class
Job
<
Grape
::
Entity
expose
:id
,
:status
,
:stage
,
:name
,
:ref
,
:tag
,
:coverage
expose
:created_at
,
:started_at
,
:finished_at
expose
:user
,
with:
User
expose
:artifacts_file
,
using:
Build
ArtifactFile
,
if:
->
(
build
,
opts
)
{
build
.
artifacts?
}
expose
:artifacts_file
,
using:
Job
ArtifactFile
,
if:
->
(
build
,
opts
)
{
build
.
artifacts?
}
expose
:commit
,
with:
RepoCommit
expose
:runner
,
with:
Runner
expose
:pipeline
,
with:
PipelineBasic
...
...
@@ -670,7 +676,7 @@ module API
expose
:id
,
:iid
,
:ref
,
:sha
,
:created_at
expose
:user
,
using:
Entities
::
UserBasic
expose
:environment
,
using:
Entities
::
EnvironmentBasic
expose
:deployable
,
using:
Entities
::
Build
expose
:deployable
,
using:
Entities
::
Job
end
class
RepoLicense
<
Grape
::
Entity
...
...
lib/api/
build
s.rb
→
lib/api/
job
s.rb
View file @
111748ea
module
API
class
Build
s
<
Grape
::
API
class
Job
s
<
Grape
::
API
include
PaginationParams
before
{
authenticate!
}
...
...
@@ -13,9 +13,10 @@ module API
optional
:scope
,
types:
[
String
,
Array
[
String
]],
desc:
'The scope of builds to show'
,
values:
::
CommitStatus
::
AVAILABLE_STATUSES
,
coerce_with:
->
(
scope
)
{
if
scope
.
is_a?
(
String
)
case
scope
when
String
[
scope
]
elsif
scope
.
is_a?
(
Hashie
::
Mash
)
when
Hashie
::
Mash
scope
.
values
else
[
'unknown'
]
...
...
@@ -24,30 +25,30 @@ module API
end
end
desc
'Get a project
build
s'
do
success
Entities
::
Build
desc
'Get a project
s job
s'
do
success
Entities
::
Job
end
params
do
use
:optional_scope
use
:pagination
end
get
':id/
build
s'
do
get
':id/
job
s'
do
builds
=
user_project
.
builds
.
order
(
'id DESC'
)
builds
=
filter_builds
(
builds
,
params
[
:scope
])
present
paginate
(
builds
),
with:
Entities
::
Build
,
present
paginate
(
builds
),
with:
Entities
::
Job
,
user_can_download_artifacts:
can?
(
current_user
,
:read_build
,
user_project
)
end
desc
'Get
build
s for a specific commit of a project'
do
success
Entities
::
Build
desc
'Get
job
s for a specific commit of a project'
do
success
Entities
::
Job
end
params
do
requires
:sha
,
type:
String
,
desc:
'The SHA id of a commit'
use
:optional_scope
use
:pagination
end
get
':id/repository/commits/:sha/
build
s'
do
get
':id/repository/commits/:sha/
job
s'
do
authorize_read_builds!
return
not_found!
unless
user_project
.
commit
(
params
[
:sha
])
...
...
@@ -56,47 +57,47 @@ module API
builds
=
user_project
.
builds
.
where
(
pipeline:
pipelines
).
order
(
'id DESC'
)
builds
=
filter_builds
(
builds
,
params
[
:scope
])
present
paginate
(
builds
),
with:
Entities
::
Build
,
present
paginate
(
builds
),
with:
Entities
::
Job
,
user_can_download_artifacts:
can?
(
current_user
,
:read_build
,
user_project
)
end
desc
'Get a specific
build
of a project'
do
success
Entities
::
Build
desc
'Get a specific
job
of a project'
do
success
Entities
::
Job
end
params
do
requires
:
build_id
,
type:
Integer
,
desc:
'The ID of a build
'
requires
:
job_id
,
type:
Integer
,
desc:
'The ID of a job
'
end
get
':id/
builds/:build
_id'
do
get
':id/
jobs/:job
_id'
do
authorize_read_builds!
build
=
get_build!
(
params
[
:
build
_id
])
build
=
get_build!
(
params
[
:
job
_id
])
present
build
,
with:
Entities
::
Build
,
present
build
,
with:
Entities
::
Job
,
user_can_download_artifacts:
can?
(
current_user
,
:read_build
,
user_project
)
end
desc
'Download the artifacts file from
build
'
do
desc
'Download the artifacts file from
a job
'
do
detail
'This feature was introduced in GitLab 8.5'
end
params
do
requires
:
build_id
,
type:
Integer
,
desc:
'The ID of a build
'
requires
:
job_id
,
type:
Integer
,
desc:
'The ID of a job
'
end
get
':id/
builds/:build
_id/artifacts'
do
get
':id/
jobs/:job
_id/artifacts'
do
authorize_read_builds!
build
=
get_build!
(
params
[
:
build
_id
])
build
=
get_build!
(
params
[
:
job
_id
])
present_artifacts!
(
build
.
artifacts_file
)
end
desc
'Download the artifacts file from
build
'
do
desc
'Download the artifacts file from
a job
'
do
detail
'This feature was introduced in GitLab 8.10'
end
params
do
requires
:ref_name
,
type:
String
,
desc:
'The ref from repository'
requires
:job
,
type:
String
,
desc:
'The name for the
build
'
requires
:job
,
type:
String
,
desc:
'The name for the
job
'
end
get
':id/
build
s/artifacts/:ref_name/download'
,
get
':id/
job
s/artifacts/:ref_name/download'
,
requirements:
{
ref_name:
/.+/
}
do
authorize_read_builds!
...
...
@@ -109,14 +110,14 @@ module API
# TODO: We should use `present_file!` and leave this implementation for backward compatibility (when build trace
# is saved in the DB instead of file). But before that, we need to consider how to replace the value of
# `runners_token` with some mask (like `xxxxxx`) when sending trace file directly by workhorse.
desc
'Get a trace of a specific
build
of a project'
desc
'Get a trace of a specific
job
of a project'
params
do
requires
:
build_id
,
type:
Integer
,
desc:
'The ID of a build
'
requires
:
job_id
,
type:
Integer
,
desc:
'The ID of a job
'
end
get
':id/
builds/:build
_id/trace'
do
get
':id/
jobs/:job
_id/trace'
do
authorize_read_builds!
build
=
get_build!
(
params
[
:
build
_id
])
build
=
get_build!
(
params
[
:
job
_id
])
header
'Content-Disposition'
,
"infile; filename=
\"
#{
build
.
id
}
.log
\"
"
content_type
'text/plain'
...
...
@@ -126,95 +127,95 @@ module API
body
trace
end
desc
'Cancel a specific
build
of a project'
do
success
Entities
::
Build
desc
'Cancel a specific
job
of a project'
do
success
Entities
::
Job
end
params
do
requires
:
build_id
,
type:
Integer
,
desc:
'The ID of a build
'
requires
:
job_id
,
type:
Integer
,
desc:
'The ID of a job
'
end
post
':id/
builds/:build
_id/cancel'
do
post
':id/
jobs/:job
_id/cancel'
do
authorize_update_builds!
build
=
get_build!
(
params
[
:
build
_id
])
build
=
get_build!
(
params
[
:
job
_id
])
build
.
cancel
present
build
,
with:
Entities
::
Build
,
present
build
,
with:
Entities
::
Job
,
user_can_download_artifacts:
can?
(
current_user
,
:read_build
,
user_project
)
end
desc
'Retry a specific build of a project'
do
success
Entities
::
Build
success
Entities
::
Job
end
params
do
requires
:
build
_id
,
type:
Integer
,
desc:
'The ID of a build'
requires
:
job
_id
,
type:
Integer
,
desc:
'The ID of a build'
end
post
':id/
builds/:build
_id/retry'
do
post
':id/
jobs/:job
_id/retry'
do
authorize_update_builds!
build
=
get_build!
(
params
[
:
build
_id
])
return
forbidden!
(
'
Build
is not retryable'
)
unless
build
.
retryable?
build
=
get_build!
(
params
[
:
job
_id
])
return
forbidden!
(
'
Job
is not retryable'
)
unless
build
.
retryable?
build
=
Ci
::
Build
.
retry
(
build
,
current_user
)
present
build
,
with:
Entities
::
Build
,
present
build
,
with:
Entities
::
Job
,
user_can_download_artifacts:
can?
(
current_user
,
:read_build
,
user_project
)
end
desc
'Erase
build (remove artifacts and build
trace)'
do
success
Entities
::
Build
desc
'Erase
job (remove artifacts and the
trace)'
do
success
Entities
::
Job
end
params
do
requires
:
build
_id
,
type:
Integer
,
desc:
'The ID of a build'
requires
:
job
_id
,
type:
Integer
,
desc:
'The ID of a build'
end
post
':id/
builds/:build
_id/erase'
do
post
':id/
jobs/:job
_id/erase'
do
authorize_update_builds!
build
=
get_build!
(
params
[
:
build
_id
])
return
forbidden!
(
'
Build
is not erasable!'
)
unless
build
.
erasable?
build
=
get_build!
(
params
[
:
job
_id
])
return
forbidden!
(
'
Job
is not erasable!'
)
unless
build
.
erasable?
build
.
erase
(
erased_by:
current_user
)
present
build
,
with:
Entities
::
Build
,
present
build
,
with:
Entities
::
Job
,
user_can_download_artifacts:
can?
(
current_user
,
:download_build_artifacts
,
user_project
)
end
desc
'Keep the artifacts to prevent them from being deleted'
do
success
Entities
::
Build
success
Entities
::
Job
end
params
do
requires
:
build_id
,
type:
Integer
,
desc:
'The ID of a build
'
requires
:
job_id
,
type:
Integer
,
desc:
'The ID of a job
'
end
post
':id/
builds/:build
_id/artifacts/keep'
do
post
':id/
jobs/:job
_id/artifacts/keep'
do
authorize_update_builds!
build
=
get_build!
(
params
[
:
build
_id
])
build
=
get_build!
(
params
[
:
job
_id
])
return
not_found!
(
build
)
unless
build
.
artifacts?
build
.
keep_artifacts!
status
200
present
build
,
with:
Entities
::
Build
,
present
build
,
with:
Entities
::
Job
,
user_can_download_artifacts:
can?
(
current_user
,
:read_build
,
user_project
)
end
desc
'Trigger a manual
build
'
do
success
Entities
::
Build
desc
'Trigger a manual
job
'
do
success
Entities
::
Job
detail
'This feature was added in GitLab 8.11'
end
params
do
requires
:
build_id
,
type:
Integer
,
desc:
'The ID of a Build
'
requires
:
job_id
,
type:
Integer
,
desc:
'The ID of a Job
'
end
post
":id/
builds/:build
_id/play"
do
post
":id/
jobs/:job
_id/play"
do
authorize_read_builds!
build
=
get_build!
(
params
[
:
build
_id
])
build
=
get_build!
(
params
[
:
job
_id
])
bad_request!
(
"Unplayable Job"
)
unless
build
.
playable?
build
.
play
(
current_user
)
status
200
present
build
,
with:
Entities
::
Build
,
present
build
,
with:
Entities
::
Job
,
user_can_download_artifacts:
can?
(
current_user
,
:read_build
,
user_project
)
end
end
...
...
lib/api/v3/builds.rb
0 → 100644
View file @
111748ea
module
API
module
V3
class
Builds
<
Grape
::
API
include
PaginationParams
before
{
authenticate!
}
params
do
requires
:id
,
type:
String
,
desc:
'The ID of a project'
end
resource
:projects
do
helpers
do
params
:optional_scope
do
optional
:scope
,
types:
[
String
,
Array
[
String
]],
desc:
'The scope of builds to show'
,
values:
[
'pending'
,
'running'
,
'failed'
,
'success'
,
'canceled'
],
coerce_with:
->
(
scope
)
{
if
scope
.
is_a?
(
String
)
[
scope
]
elsif
scope
.
is_a?
(
Hashie
::
Mash
)
scope
.
values
else
[
'unknown'
]
end
}
end
end
desc
'Get a project builds'
do
success
V3
::
Entities
::
Build
end
params
do
use
:optional_scope
use
:pagination
end
get
':id/builds'
do
builds
=
user_project
.
builds
.
order
(
'id DESC'
)
builds
=
filter_builds
(
builds
,
params
[
:scope
])
present
paginate
(
builds
),
with:
Entities
::
Build
,
user_can_download_artifacts:
can?
(
current_user
,
:read_build
,
user_project
)
end
desc
'Get builds for a specific commit of a project'
do
success
Entities
::
Build
end
params
do
requires
:sha
,
type:
String
,
desc:
'The SHA id of a commit'
use
:optional_scope
use
:pagination
end
get
':id/repository/commits/:sha/builds'
do
authorize_read_builds!
return
not_found!
unless
user_project
.
commit
(
params
[
:sha
])
pipelines
=
user_project
.
pipelines
.
where
(
sha:
params
[
:sha
])
builds
=
user_project
.
builds
.
where
(
pipeline:
pipelines
).
order
(
'id DESC'
)
builds
=
filter_builds
(
builds
,
params
[
:scope
])
present
paginate
(
builds
),
with:
Entities
::
Build
,
user_can_download_artifacts:
can?
(
current_user
,
:read_build
,
user_project
)
end
desc
'Get a specific build of a project'
do
success
Entities
::
Build
end
params
do
requires
:build_id
,
type:
Integer
,
desc:
'The ID of a build'
end
get
':id/builds/:build_id'
do
authorize_read_builds!
build
=
get_build!
(
params
[
:build_id
])
present
build
,
with:
Entities
::
Build
,
user_can_download_artifacts:
can?
(
current_user
,
:read_build
,
user_project
)
end
desc
'Download the artifacts file from build'
do
detail
'This feature was introduced in GitLab 8.5'
end
params
do
requires
:build_id
,
type:
Integer
,
desc:
'The ID of a build'
end
get
':id/builds/:build_id/artifacts'
do
authorize_read_builds!
build
=
get_build!
(
params
[
:build_id
])
present_artifacts!
(
build
.
artifacts_file
)
end
desc
'Download the artifacts file from build'
do
detail
'This feature was introduced in GitLab 8.10'
end
params
do
requires
:ref_name
,
type:
String
,
desc:
'The ref from repository'
requires
:job
,
type:
String
,
desc:
'The name for the build'
end
get
':id/builds/artifacts/:ref_name/download'
,
requirements:
{
ref_name:
/.+/
}
do
authorize_read_builds!
builds
=
user_project
.
latest_successful_builds_for
(
params
[
:ref_name
])
latest_build
=
builds
.
find_by!
(
name:
params
[
:job
])
present_artifacts!
(
latest_build
.
artifacts_file
)
end
# TODO: We should use `present_file!` and leave this implementation for backward compatibility (when build trace
# is saved in the DB instead of file). But before that, we need to consider how to replace the value of
# `runners_token` with some mask (like `xxxxxx`) when sending trace file directly by workhorse.
desc
'Get a trace of a specific build of a project'
params
do
requires
:build_id
,
type:
Integer
,
desc:
'The ID of a build'
end
get
':id/builds/:build_id/trace'
do
authorize_read_builds!
build
=
get_build!
(
params
[
:build_id
])
header
'Content-Disposition'
,
"infile; filename=
\"
#{
build
.
id
}
.log
\"
"
content_type
'text/plain'
env
[
'api.format'
]
=
:binary
trace
=
build
.
trace
body
trace
end
desc
'Cancel a specific build of a project'
do
success
Entities
::
Build
end
params
do
requires
:build_id
,
type:
Integer
,
desc:
'The ID of a build'
end
post
':id/builds/:build_id/cancel'
do
authorize_update_builds!
build
=
get_build!
(
params
[
:build_id
])
build
.
cancel
present
build
,
with:
Entities
::
Build
,
user_can_download_artifacts:
can?
(
current_user
,
:read_build
,
user_project
)
end
desc
'Retry a specific build of a project'
do
success
Entities
::
Build
end
params
do
requires
:build_id
,
type:
Integer
,
desc:
'The ID of a build'
end
post
':id/builds/:build_id/retry'
do
authorize_update_builds!
build
=
get_build!
(
params
[
:build_id
])
return
forbidden!
(
'Build is not retryable'
)
unless
build
.
retryable?
build
=
Ci
::
Build
.
retry
(
build
,
current_user
)
present
build
,
with:
Entities
::
Build
,
user_can_download_artifacts:
can?
(
current_user
,
:read_build
,
user_project
)
end
desc
'Erase build (remove artifacts and build trace)'
do
success
Entities
::
Build
end
params
do
requires
:build_id
,
type:
Integer
,
desc:
'The ID of a build'
end
post
':id/builds/:build_id/erase'
do
authorize_update_builds!
build
=
get_build!
(
params
[
:build_id
])
return
forbidden!
(
'Build is not erasable!'
)
unless
build
.
erasable?
build
.
erase
(
erased_by:
current_user
)
present
build
,
with:
Entities
::
Build
,
user_can_download_artifacts:
can?
(
current_user
,
:download_build_artifacts
,
user_project
)
end
desc
'Keep the artifacts to prevent them from being deleted'
do
success
Entities
::
Build
end
params
do
requires
:build_id
,
type:
Integer
,
desc:
'The ID of a build'
end
post
':id/builds/:build_id/artifacts/keep'
do
authorize_update_builds!
build
=
get_build!
(
params
[
:build_id
])
return
not_found!
(
build
)
unless
build
.
artifacts?
build
.
keep_artifacts!
status
200
present
build
,
with:
Entities
::
Build
,
user_can_download_artifacts:
can?
(
current_user
,
:read_build
,
user_project
)
end
desc
'Trigger a manual build'
do
success
Entities
::
Build
detail
'This feature was added in GitLab 8.11'
end
params
do
requires
:build_id
,
type:
Integer
,
desc:
'The ID of a Build'
end
post
":id/builds/:build_id/play"
do
authorize_read_builds!
build
=
get_build!
(
params
[
:build_id
])
bad_request!
(
"Unplayable Job"
)
unless
build
.
playable?
build
.
play
(
current_user
)
status
200
present
build
,
with:
Entities
::
Build
,
user_can_download_artifacts:
can?
(
current_user
,
:read_build
,
user_project
)
end
end
helpers
do
def
get_build
(
id
)
user_project
.
builds
.
find_by
(
id:
id
.
to_i
)
end
def
get_build!
(
id
)
get_build
(
id
)
||
not_found!
end
def
present_artifacts!
(
artifacts_file
)
if
!
artifacts_file
.
file_storage?
redirect_to
(
build
.
artifacts_file
.
url
)
elsif
artifacts_file
.
exists?
present_file!
(
artifacts_file
.
path
,
artifacts_file
.
filename
)
else
not_found!
end
end
def
filter_builds
(
builds
,
scope
)
return
builds
if
scope
.
nil?
||
scope
.
empty?
available_statuses
=
::
CommitStatus
::
AVAILABLE_STATUSES
unknown
=
scope
-
available_statuses
render_api_error!
(
'Scope contains invalid value(s)'
,
400
)
unless
unknown
.
empty?
builds
.
where
(
status:
available_statuses
&&
scope
)
end
def
authorize_read_builds!
authorize!
:read_build
,
user_project
end
def
authorize_update_builds!
authorize!
:update_build
,
user_project
end
end
end
end
end
lib/api/v3/entities.rb
View file @
111748ea
...
...
@@ -195,6 +195,16 @@ module API
class
TriggerRequest
<
Grape
::
Entity
expose
:id
,
:variables
end
class
Build
<
Grape
::
Entity
expose
:id
,
:status
,
:stage
,
:name
,
:ref
,
:tag
,
:coverage
expose
:created_at
,
:started_at
,
:finished_at
expose
:user
,
with:
::
API
::
Entities
::
User
expose
:artifacts_file
,
using:
::
API
::
Entities
::
JobArtifactFile
,
if:
->
(
build
,
opts
)
{
build
.
artifacts?
}
expose
:commit
,
with:
::
API
::
Entities
::
RepoCommit
expose
:runner
,
with:
::
API
::
Entities
::
Runner
expose
:pipeline
,
with:
::
API
::
Entities
::
PipelineBasic
end
end
end
end
spec/requests/api/jobs_spec.rb
0 → 100644
View file @
111748ea
require
'spec_helper'
describe
API
::
Jobs
,
api:
true
do
include
ApiHelpers
let
(
:user
)
{
create
(
:user
)
}
let
(
:api_user
)
{
user
}
let!
(
:project
)
{
create
(
:project
,
:repository
,
creator:
user
,
public_builds:
false
)
}
let!
(
:developer
)
{
create
(
:project_member
,
:developer
,
user:
user
,
project:
project
)
}
let
(
:reporter
)
{
create
(
:project_member
,
:reporter
,
project:
project
)
}
let
(
:guest
)
{
create
(
:project_member
,
:guest
,
project:
project
)
}
let!
(
:pipeline
)
{
create
(
:ci_empty_pipeline
,
project:
project
,
sha:
project
.
commit
.
id
,
ref:
project
.
default_branch
)
}
let!
(
:build
)
{
create
(
:ci_build
,
pipeline:
pipeline
)
}
describe
'GET /projects/:id/jobs'
do
let
(
:query
)
{
Hash
.
new
}
before
do
get
api
(
"/projects/
#{
project
.
id
}
/jobs"
,
api_user
),
query
end
context
'authorized user'
do
it
'returns project 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 project 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 project 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
end
context
'unauthorized user'
do
let
(
:api_user
)
{
nil
}
it
'does not return project builds'
do
expect
(
response
).
to
have_http_status
(
401
)
end
end
end
describe
'GET /projects/:id/repository/commits/:sha/jobs'
do
context
'when commit does not exist in repository'
do
before
do
get
api
(
"/projects/
#{
project
.
id
}
/repository/commits/1a271fd1/jobs"
,
api_user
)
end
it
'responds with 404'
do
expect
(
response
).
to
have_http_status
(
404
)
end
end
context
'when commit exists in repository'
do
context
'when user is authorized'
do
context
'when pipeline has jobs'
do
before
do
create
(
:ci_pipeline
,
project:
project
,
sha:
project
.
commit
.
id
)
create
(
:ci_build
,
pipeline:
pipeline
)
create
(
:ci_build
)
get
api
(
"/projects/
#{
project
.
id
}
/repository/commits/
#{
project
.
commit
.
id
}
/jobs"
,
api_user
)
end
it
'returns project jobs for specific commit'
do
expect
(
response
).
to
have_http_status
(
200
)
expect
(
response
).
to
include_pagination_headers
expect
(
json_response
).
to
be_an
Array
expect
(
json_response
.
size
).
to
eq
2
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
end
context
'when pipeline has no jobs'
do
before
do
branch_head
=
project
.
commit
(
'feature'
).
id
get
api
(
"/projects/
#{
project
.
id
}
/repository/commits/
#{
branch_head
}
/jobs"
,
api_user
)
end
it
'returns an empty array'
do
expect
(
response
).
to
have_http_status
(
200
)
expect
(
json_response
).
to
be_an
Array
expect
(
json_response
).
to
be_empty
end
end
end
context
'when user is not authorized'
do
before
do
create
(
:ci_pipeline
,
project:
project
,
sha:
project
.
commit
.
id
)
create
(
:ci_build
,
pipeline:
pipeline
)
get
api
(
"/projects/
#{
project
.
id
}
/repository/commits/
#{
project
.
commit
.
id
}
/jobs"
,
nil
)
end
it
'does not return project jobs'
do
expect
(
response
).
to
have_http_status
(
401
)
expect
(
json_response
.
except
(
'message'
)).
to
be_empty
end
end
end
end
describe
'GET /projects/:id/jobs/:job_id'
do
before
do
get
api
(
"/projects/
#{
project
.
id
}
/jobs/
#{
build
.
id
}
"
,
api_user
)
end
context
'authorized user'
do
it
'returns specific job data'
do
expect
(
response
).
to
have_http_status
(
200
)
expect
(
json_response
[
'name'
]).
to
eq
(
'test'
)
end
it
'returns pipeline data'
do
json_build
=
json_response
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
end
context
'unauthorized user'
do
let
(
:api_user
)
{
nil
}
it
'does not return specific job data'
do
expect
(
response
).
to
have_http_status
(
401
)
end
end
end
describe
'GET /projects/:id/jobs/:job_id/artifacts'
do
before
do
get
api
(
"/projects/
#{
project
.
id
}
/jobs/
#{
build
.
id
}
/artifacts"
,
api_user
)
end
context
'job with artifacts'
do
let
(
:build
)
{
create
(
:ci_build
,
:artifacts
,
pipeline:
pipeline
)
}
context
'authorized user'
do
let
(
:download_headers
)
do
{
'Content-Transfer-Encoding'
=>
'binary'
,
'Content-Disposition'
=>
'attachment; filename=ci_build_artifacts.zip'
}
end
it
'returns specific job artifacts'
do
expect
(
response
).
to
have_http_status
(
200
)
expect
(
response
.
headers
).
to
include
(
download_headers
)
expect
(
response
.
body
).
to
match_file
(
build
.
artifacts_file
.
file
.
file
)
end
end
context
'unauthorized user'
do
let
(
:api_user
)
{
nil
}
it
'does not return specific job artifacts'
do
expect
(
response
).
to
have_http_status
(
401
)
end
end
end
it
'does not return job artifacts if not uploaded'
do
expect
(
response
).
to
have_http_status
(
404
)
end
end
describe
'GET /projects/:id/artifacts/:ref_name/download?job=name'
do
let
(
:api_user
)
{
reporter
.
user
}
let
(
:build
)
{
create
(
:ci_build
,
:artifacts
,
pipeline:
pipeline
)
}
before
do
build
.
success
end
def
get_for_ref
(
ref
=
pipeline
.
ref
,
job
=
build
.
name
)
get
api
(
"/projects/
#{
project
.
id
}
/jobs/artifacts/
#{
ref
}
/download"
,
api_user
),
job:
job
end
context
'when not logged in'
do
let
(
:api_user
)
{
nil
}
before
do
get_for_ref
end
it
'gives 401'
do
expect
(
response
).
to
have_http_status
(
401
)
end
end
context
'when logging as guest'
do
let
(
:api_user
)
{
guest
.
user
}
before
do
get_for_ref
end
it
'gives 403'
do
expect
(
response
).
to
have_http_status
(
403
)
end
end
context
'non-existing job'
do
shared_examples
'not found'
do
it
{
expect
(
response
).
to
have_http_status
(
:not_found
)
}
end
context
'has no such ref'
do
before
do
get_for_ref
(
'TAIL'
)
end
it_behaves_like
'not found'
end
context
'has no such job'
do
before
do
get_for_ref
(
pipeline
.
ref
,
'NOBUILD'
)
end
it_behaves_like
'not found'
end
end
context
'find proper job'
do
shared_examples
'a valid file'
do
let
(
:download_headers
)
do
{
'Content-Transfer-Encoding'
=>
'binary'
,
'Content-Disposition'
=>
"attachment; filename=
#{
build
.
artifacts_file
.
filename
}
"
}
end
it
{
expect
(
response
).
to
have_http_status
(
200
)
}
it
{
expect
(
response
.
headers
).
to
include
(
download_headers
)
}
end
context
'with regular branch'
do
before
do
pipeline
.
reload
pipeline
.
update
(
ref:
'master'
,
sha:
project
.
commit
(
'master'
).
sha
)
get_for_ref
(
'master'
)
end
it_behaves_like
'a valid file'
end
context
'with branch name containing slash'
do
before
do
pipeline
.
reload
pipeline
.
update
(
ref:
'improve/awesome'
,
sha:
project
.
commit
(
'improve/awesome'
).
sha
)
end
before
do
get_for_ref
(
'improve/awesome'
)
end
it_behaves_like
'a valid file'
end
end
end
describe
'GET /projects/:id/jobs/:job_id/trace'
do
let
(
:build
)
{
create
(
:ci_build
,
:trace
,
pipeline:
pipeline
)
}
before
do
get
api
(
"/projects/
#{
project
.
id
}
/jobs/
#{
build
.
id
}
/trace"
,
api_user
)
end
context
'authorized user'
do
it
'returns specific job trace'
do
expect
(
response
).
to
have_http_status
(
200
)
expect
(
response
.
body
).
to
eq
(
build
.
trace
)
end
end
context
'unauthorized user'
do
let
(
:api_user
)
{
nil
}
it
'does not return specific job trace'
do
expect
(
response
).
to
have_http_status
(
401
)
end
end
end
describe
'POST /projects/:id/jobs/:job_id/cancel'
do
before
do
post
api
(
"/projects/
#{
project
.
id
}
/jobs/
#{
build
.
id
}
/cancel"
,
api_user
)
end
context
'authorized user'
do
context
'user with :update_build persmission'
do
it
'cancels running or pending job'
do
expect
(
response
).
to
have_http_status
(
201
)
expect
(
project
.
builds
.
first
.
status
).
to
eq
(
'canceled'
)
end
end
context
'user without :update_build permission'
do
let
(
:api_user
)
{
reporter
.
user
}
it
'does not cancel job'
do
expect
(
response
).
to
have_http_status
(
403
)
end
end
end
context
'unauthorized user'
do
let
(
:api_user
)
{
nil
}
it
'does not cancel job'
do
expect
(
response
).
to
have_http_status
(
401
)
end
end
end
describe
'POST /projects/:id/jobs/:job_id/retry'
do
let
(
:build
)
{
create
(
:ci_build
,
:canceled
,
pipeline:
pipeline
)
}
before
do
post
api
(
"/projects/
#{
project
.
id
}
/jobs/
#{
build
.
id
}
/retry"
,
api_user
)
end
context
'authorized user'
do
context
'user with :update_build permission'
do
it
'retries non-running job'
do
expect
(
response
).
to
have_http_status
(
201
)
expect
(
project
.
builds
.
first
.
status
).
to
eq
(
'canceled'
)
expect
(
json_response
[
'status'
]).
to
eq
(
'pending'
)
end
end
context
'user without :update_build permission'
do
let
(
:api_user
)
{
reporter
.
user
}
it
'does not retry job'
do
expect
(
response
).
to
have_http_status
(
403
)
end
end
end
context
'unauthorized user'
do
let
(
:api_user
)
{
nil
}
it
'does not retry job'
do
expect
(
response
).
to
have_http_status
(
401
)
end
end
end
describe
'POST /projects/:id/jobs/:job_id/erase'
do
before
do
post
api
(
"/projects/
#{
project
.
id
}
/jobs/
#{
build
.
id
}
/erase"
,
user
)
end
context
'job is erasable'
do
let
(
:build
)
{
create
(
:ci_build
,
:trace
,
:artifacts
,
:success
,
project:
project
,
pipeline:
pipeline
)
}
it
'erases job content'
do
expect
(
response
).
to
have_http_status
(
201
)
expect
(
build
.
trace
).
to
be_empty
expect
(
build
.
artifacts_file
.
exists?
).
to
be_falsy
expect
(
build
.
artifacts_metadata
.
exists?
).
to
be_falsy
end
it
'updates job'
do
build
.
reload
expect
(
build
.
erased_at
).
to
be_truthy
expect
(
build
.
erased_by
).
to
eq
(
user
)
end
end
context
'job is not erasable'
do
let
(
:build
)
{
create
(
:ci_build
,
:trace
,
project:
project
,
pipeline:
pipeline
)
}
it
'responds with forbidden'
do
expect
(
response
).
to
have_http_status
(
403
)
end
end
end
describe
'POST /projects/:id/jobs/:build_id/artifacts/keep'
do
before
do
post
api
(
"/projects/
#{
project
.
id
}
/jobs/
#{
build
.
id
}
/artifacts/keep"
,
user
)
end
context
'artifacts did not expire'
do
let
(
:build
)
do
create
(
:ci_build
,
:trace
,
:artifacts
,
:success
,
project:
project
,
pipeline:
pipeline
,
artifacts_expire_at:
Time
.
now
+
7
.
days
)
end
it
'keeps artifacts'
do
expect
(
response
).
to
have_http_status
(
200
)
expect
(
build
.
reload
.
artifacts_expire_at
).
to
be_nil
end
end
context
'no artifacts'
do
let
(
:build
)
{
create
(
:ci_build
,
project:
project
,
pipeline:
pipeline
)
}
it
'responds with not found'
do
expect
(
response
).
to
have_http_status
(
404
)
end
end
end
describe
'POST /projects/:id/jobs/:job_id/play'
do
before
do
post
api
(
"/projects/
#{
project
.
id
}
/jobs/
#{
build
.
id
}
/play"
,
user
)
end
context
'on an playable job'
do
let
(
:build
)
{
create
(
:ci_build
,
:manual
,
project:
project
,
pipeline:
pipeline
)
}
it
'plays the job'
do
expect
(
response
).
to
have_http_status
(
200
)
expect
(
json_response
[
'user'
][
'id'
]).
to
eq
(
user
.
id
)
expect
(
json_response
[
'id'
]).
to
eq
(
build
.
id
)
end
end
context
'on a non-playable job'
do
it
'returns a status code 400, Bad Request'
do
expect
(
response
).
to
have_http_status
400
expect
(
response
.
body
).
to
match
(
"Unplayable Job"
)
end
end
end
end
spec/requests/api/builds_spec.rb
→
spec/requests/api/
v3/
builds_spec.rb
View file @
111748ea
require
'spec_helper'
describe
API
::
Builds
,
api:
true
do
describe
API
::
V3
::
Builds
,
api:
true
do
include
ApiHelpers
let
(
:user
)
{
create
(
:user
)
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment