BigW Consortium Gitlab
Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
gitlab-ce
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Forest Godfrey
gitlab-ce
Commits
c2eb5476
Unverified
Commit
c2eb5476
authored
Feb 28, 2017
by
Tomasz Maczukin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add artifacts uploading API
parent
2a7f555c
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
252 additions
and
0 deletions
+252
-0
runner.rb
lib/api/runner.rb
+47
-0
runner_spec.rb
spec/requests/api/runner_spec.rb
+205
-0
No files found.
lib/api/runner.rb
View file @
c2eb5476
...
...
@@ -174,6 +174,53 @@ module API
content_type
Gitlab
::
Workhorse
::
INTERNAL_API_CONTENT_TYPE
Gitlab
::
Workhorse
.
artifact_upload_ok
end
desc
'Upload artifacts for job'
do
http_codes
[[
201
,
'Artifact uploaded'
],
[
400
,
'Bad request'
],
[
403
,
'Forbidden'
],
[
405
,
'Artifacts support not enabled'
],
[
413
,
'File too large'
]]
end
params
do
requires
:id
,
type:
Fixnum
,
desc:
%q(Job's ID)
optional
:token
,
type:
String
,
desc:
%q(Job's authentication token)
optional
:expire_in
,
type:
String
,
desc:
%q(Specify when artifacts should expire)
optional
'file'
,
type:
File
,
desc:
%q(Artifact's file)
optional
'file.path'
,
type:
String
,
desc:
%q(path to locally stored body (generated by Workhorse))
optional
'file.name'
,
type:
String
,
desc:
%q(real filename as send in Content-Disposition (generated by Workhorse))
optional
'file.type'
,
type:
String
,
desc:
%q(real content type as send in Content-Type (generated by Workhorse))
optional
'metadata.path'
,
type:
String
,
desc:
%q(path to locally stored body (generated by Workhorse))
optional
'metadata.name'
,
type:
String
,
desc:
%q(filename (generated by Workhorse))
end
post
'/:id/artifacts'
do
not_allowed!
unless
Gitlab
.
config
.
artifacts
.
enabled
require_gitlab_workhorse!
job
=
Ci
::
Build
.
find_by_id
(
params
[
:id
])
authenticate_job!
(
job
)
forbidden!
(
'Job is not running!'
)
unless
job
.
running?
artifacts_upload_path
=
ArtifactUploader
.
artifacts_upload_path
artifacts
=
uploaded_file
(
:file
,
artifacts_upload_path
)
metadata
=
uploaded_file
(
:metadata
,
artifacts_upload_path
)
bad_request!
(
'Missing artifacts file!'
)
unless
artifacts
file_to_large!
unless
artifacts
.
size
<
max_artifacts_size
job
.
artifacts_file
=
artifacts
job
.
artifacts_metadata
=
metadata
job
.
artifacts_expire_in
=
params
[
'expire_in'
]
||
Gitlab
::
CurrentSettings
.
current_application_settings
.
default_artifacts_expire_in
if
job
.
save
present
job
,
with:
Entities
::
JobRequest
::
Response
else
render_validation_error!
(
job
)
end
end
end
end
end
spec/requests/api/runner_spec.rb
View file @
c2eb5476
...
...
@@ -616,9 +616,12 @@ describe API::Runner do
end
describe
'artifacts'
do
let
(
:job
)
{
create
(
:ci_build
,
:pending
,
pipeline:
pipeline
,
runner_id:
runner
.
id
)
}
let
(
:jwt_token
)
{
JWT
.
encode
({
'iss'
=>
'gitlab-workhorse'
},
Gitlab
::
Workhorse
.
secret
,
'HS256'
)
}
let
(
:headers
)
{
{
'GitLab-Workhorse'
=>
'1.0'
,
Gitlab
::
Workhorse
::
INTERNAL_API_REQUEST_HEADER
=>
jwt_token
}
}
let
(
:headers_with_token
)
{
headers
.
merge
(
API
::
Helpers
::
Runner
::
JOB_TOKEN_HEADER
=>
job
.
token
)
}
let
(
:file_upload
)
{
fixture_file_upload
(
Rails
.
root
+
'spec/fixtures/banana_sample.gif'
,
'image/gif'
)
}
let
(
:file_upload2
)
{
fixture_file_upload
(
Rails
.
root
+
'spec/fixtures/dk.png'
,
'image/gif'
)
}
before
{
job
.
run!
}
...
...
@@ -690,6 +693,208 @@ describe API::Runner do
authorize_artifacts
(
params
,
request_headers
)
end
end
describe
'POST /api/v4/jobs/:id/artifacts'
do
context
'when artifacts are being stored inside of tmp path'
do
before
do
# by configuring this path we allow to pass temp file from any path
allow
(
ArtifactUploader
).
to
receive
(
:artifacts_upload_path
).
and_return
(
'/'
)
end
context
'when job has been erased'
do
let
(
:job
)
{
create
(
:ci_build
,
erased_at:
Time
.
now
)
}
before
do
upload_artifacts
(
file_upload
,
headers_with_token
)
end
it
'responds with forbidden'
do
upload_artifacts
(
file_upload
,
headers_with_token
)
expect
(
response
).
to
have_http_status
(
403
)
end
end
context
'when job is running'
do
shared_examples
'successful artifacts upload'
do
it
'updates successfully'
do
expect
(
response
).
to
have_http_status
(
201
)
end
end
context
'when uses regular file post'
do
before
{
upload_artifacts
(
file_upload
,
headers_with_token
,
false
)
}
it_behaves_like
'successful artifacts upload'
end
context
'when uses accelerated file post'
do
before
{
upload_artifacts
(
file_upload
,
headers_with_token
,
true
)
}
it_behaves_like
'successful artifacts upload'
end
context
'when updates artifact'
do
before
do
upload_artifacts
(
file_upload2
,
headers_with_token
)
upload_artifacts
(
file_upload
,
headers_with_token
)
end
it_behaves_like
'successful artifacts upload'
end
context
'when using runners token'
do
it
'responds with forbidden'
do
upload_artifacts
(
file_upload
,
headers
.
merge
(
API
::
Helpers
::
Runner
::
JOB_TOKEN_HEADER
=>
job
.
project
.
runners_token
))
expect
(
response
).
to
have_http_status
(
403
)
end
end
end
context
'when artifacts file is too large'
do
it
'fails to post too large artifact'
do
stub_application_setting
(
max_artifacts_size:
0
)
upload_artifacts
(
file_upload
,
headers_with_token
)
expect
(
response
).
to
have_http_status
(
413
)
end
end
context
'when artifacts post request does not contain file'
do
it
'fails to post artifacts without file'
do
post
api
(
"/jobs/
#{
job
.
id
}
/artifacts"
),
{},
headers_with_token
expect
(
response
).
to
have_http_status
(
400
)
end
end
context
'GitLab Workhorse is not configured'
do
it
'fails to post artifacts without GitLab-Workhorse'
do
post
api
(
"/jobs/
#{
job
.
id
}
/artifacts"
),
{
token:
job
.
token
},
{}
expect
(
response
).
to
have_http_status
(
403
)
end
end
context
'when setting an expire date'
do
let
(
:default_artifacts_expire_in
)
{}
let
(
:post_data
)
do
{
'file.path'
=>
file_upload
.
path
,
'file.name'
=>
file_upload
.
original_filename
,
'expire_in'
=>
expire_in
}
end
before
do
stub_application_setting
(
default_artifacts_expire_in:
default_artifacts_expire_in
)
post
(
api
(
"/jobs/
#{
job
.
id
}
/artifacts"
),
post_data
,
headers_with_token
)
end
context
'when an expire_in is given'
do
let
(
:expire_in
)
{
'7 days'
}
it
'updates when specified'
do
job
.
reload
expect
(
response
).
to
have_http_status
(
201
)
expect
(
job
.
artifacts_expire_at
).
to
be_within
(
5
.
minutes
).
of
(
7
.
days
.
from_now
)
end
end
context
'when no expire_in is given'
do
let
(
:expire_in
)
{
nil
}
it
'ignores if not specified'
do
job
.
reload
expect
(
response
).
to
have_http_status
(
201
)
expect
(
job
.
artifacts_expire_at
).
to
be_nil
end
context
'with application default'
do
context
'when default is 5 days'
do
let
(
:default_artifacts_expire_in
)
{
'5 days'
}
it
'sets to application default'
do
job
.
reload
expect
(
response
).
to
have_http_status
(
201
)
expect
(
job
.
artifacts_expire_at
).
to
be_within
(
5
.
minutes
).
of
(
5
.
days
.
from_now
)
end
end
context
'when default is 0'
do
let
(
:default_artifacts_expire_in
)
{
'0'
}
it
'does not set expire_in'
do
job
.
reload
expect
(
response
).
to
have_http_status
(
201
)
expect
(
job
.
artifacts_expire_at
).
to
be_nil
end
end
end
end
end
context
'posts artifacts file and metadata file'
do
let!
(
:artifacts
)
{
file_upload
}
let!
(
:metadata
)
{
file_upload2
}
let
(
:stored_artifacts_file
)
{
job
.
reload
.
artifacts_file
.
file
}
let
(
:stored_metadata_file
)
{
job
.
reload
.
artifacts_metadata
.
file
}
let
(
:stored_artifacts_size
)
{
job
.
reload
.
artifacts_size
}
before
do
post
(
api
(
"/jobs/
#{
job
.
id
}
/artifacts"
),
post_data
,
headers_with_token
)
end
context
'when posts data accelerated by workhorse is correct'
do
let
(
:post_data
)
do
{
'file.path'
=>
artifacts
.
path
,
'file.name'
=>
artifacts
.
original_filename
,
'metadata.path'
=>
metadata
.
path
,
'metadata.name'
=>
metadata
.
original_filename
}
end
it
'stores artifacts and artifacts metadata'
do
expect
(
response
).
to
have_http_status
(
201
)
expect
(
stored_artifacts_file
.
original_filename
).
to
eq
(
artifacts
.
original_filename
)
expect
(
stored_metadata_file
.
original_filename
).
to
eq
(
metadata
.
original_filename
)
expect
(
stored_artifacts_size
).
to
eq
(
71759
)
end
end
context
'when there is no artifacts file in post data'
do
let
(
:post_data
)
do
{
'metadata'
=>
metadata
}
end
it
'is expected to respond with bad request'
do
expect
(
response
).
to
have_http_status
(
400
)
end
it
'does not store metadata'
do
expect
(
stored_metadata_file
).
to
be_nil
end
end
end
end
context
'when artifacts are being stored outside of tmp path'
do
before
do
# by configuring this path we allow to pass file from @tmpdir only
# but all temporary files are stored in system tmp directory
@tmpdir
=
Dir
.
mktmpdir
allow
(
ArtifactUploader
).
to
receive
(
:artifacts_upload_path
).
and_return
(
@tmpdir
)
end
after
{
FileUtils
.
remove_entry
@tmpdir
}
it
' "fails to post artifacts for outside of tmp path"'
do
upload_artifacts
(
file_upload
,
headers_with_token
)
expect
(
response
).
to
have_http_status
(
400
)
end
end
def
upload_artifacts
(
file
,
headers
=
{},
accelerated
=
true
)
params
=
accelerated
?
{
'file.path'
=>
file
.
path
,
'file.name'
=>
file
.
original_filename
}
:
{
'file'
=>
file
}
post
api
(
"/jobs/
#{
job
.
id
}
/artifacts"
),
params
,
headers
end
end
end
end
end
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