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
Boxiang Sun
gitlab-ce
Commits
7e46db0f
Commit
7e46db0f
authored
Feb 28, 2017
by
Tomasz Maczukin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add job patch trace API
parent
d5f7e542
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
178 additions
and
1 deletion
+178
-1
lib/api/helpers/runner.rb
lib/api/helpers/runner.rb
+13
-0
lib/api/runner.rb
lib/api/runner.rb
+31
-1
spec/requests/api/runner_spec.rb
spec/requests/api/runner_spec.rb
+134
-0
No files found.
lib/api/helpers/runner.rb
View file @
7e46db0f
module
API
module
Helpers
module
Runner
JOB_TOKEN_HEADER
=
'HTTP_JOB_TOKEN'
JOB_TOKEN_PARAM
=
:token
UPDATE_RUNNER_EVERY
=
10
*
60
def
runner_registration_token_valid?
...
...
@@ -55,6 +57,17 @@ module API
forbidden!
(
'Project has been deleted!'
)
unless
job
.
project
forbidden!
(
'Job has been erased!'
)
if
job
.
erased?
end
def
authenticate_job!
(
job
)
validate_job!
(
job
)
do
forbidden!
unless
job_token_valid?
(
job
)
end
end
def
job_token_valid?
(
job
)
token
=
(
params
[
JOB_TOKEN_PARAM
]
||
env
[
JOB_TOKEN_HEADER
]).
to_s
token
&&
job
.
valid_token?
(
token
)
end
end
end
end
lib/api/runner.rb
View file @
7e46db0f
...
...
@@ -93,7 +93,7 @@ module API
http_codes
[[
200
,
'Job was updated'
],
[
403
,
'Forbidden'
]]
end
params
do
requires
:token
,
type:
String
,
desc:
%q(
Job
's authentication token)
requires
:token
,
type:
String
,
desc:
%q(
Runners
's authentication token)
requires
:id
,
type:
Fixnum
,
desc:
%q(Job's ID)
optional
:trace
,
type:
String
,
desc:
%q(Job's full trace)
optional
:state
,
type:
String
,
desc:
%q(Job's status: success, failed)
...
...
@@ -114,6 +114,36 @@ module API
job
.
drop
end
end
desc
'Appends a patch to the job.trace'
do
http_codes
[[
202
,
'Trace was patched'
],
[
400
,
'Missing Content-Range header'
],
[
403
,
'Forbidden'
],
[
416
,
'Range not satisfiable'
]]
end
params
do
requires
:id
,
type:
Fixnum
,
desc:
%q(Job's ID)
optional
:token
,
type:
String
,
desc:
%q(Job's authentication token)
end
patch
'/:id/trace'
do
job
=
Ci
::
Build
.
find_by_id
(
params
[
:id
])
authenticate_job!
(
job
)
error!
(
'400 Missing header Content-Range'
,
400
)
unless
request
.
headers
.
has_key?
(
'Content-Range'
)
content_range
=
request
.
headers
[
'Content-Range'
]
content_range
=
content_range
.
split
(
'-'
)
current_length
=
job
.
trace_length
unless
current_length
==
content_range
[
0
].
to_i
return
error!
(
'416 Range Not Satisfiable'
,
416
,
{
'Range'
=>
"0-
#{
current_length
}
"
})
end
job
.
append_trace
(
request
.
body
.
read
,
content_range
[
0
].
to_i
)
status
202
header
'Job-Status'
,
job
.
status
header
'Range'
,
"0-
#{
job
.
trace_length
}
"
end
end
end
end
spec/requests/api/runner_spec.rb
View file @
7e46db0f
...
...
@@ -480,5 +480,139 @@ describe API::Runner do
put
api
(
"/jobs/
#{
job
.
id
}
"
),
new_params
end
end
describe
'PATCH /api/v4/jobs/:id/trace'
do
let
(
:job
)
{
create
(
:ci_build
,
:running
,
:trace
,
runner_id:
runner
.
id
,
pipeline:
pipeline
)
}
let
(
:headers
)
{
{
API
::
Helpers
::
Runner
::
JOB_TOKEN_HEADER
=>
job
.
token
,
'Content-Type'
=>
'text/plain'
}
}
let
(
:headers_with_range
)
{
headers
.
merge
({
'Content-Range'
=>
'11-20'
})
}
let
(
:update_interval
)
{
10
.
seconds
.
to_i
}
before
{
initial_patch_the_trace
}
context
'when request is valid'
do
it
'gets correct response'
do
expect
(
response
.
status
).
to
eq
202
expect
(
job
.
reload
.
trace
).
to
eq
'BUILD TRACE appended'
expect
(
response
.
header
).
to
have_key
'Range'
expect
(
response
.
header
).
to
have_key
'Job-Status'
end
context
'when job has been updated recently'
do
it
{
expect
{
patch_the_trace
}.
not_to
change
{
job
.
updated_at
}}
it
"changes the job's trace"
do
patch_the_trace
expect
(
job
.
reload
.
trace
).
to
eq
'BUILD TRACE appended appended'
end
context
'when Runner makes a force-patch'
do
it
{
expect
{
force_patch_the_trace
}.
not_to
change
{
job
.
updated_at
}}
it
"doesn't change the build.trace"
do
force_patch_the_trace
expect
(
job
.
reload
.
trace
).
to
eq
'BUILD TRACE appended'
end
end
end
context
'when job was not updated recently'
do
let
(
:update_interval
)
{
15
.
minutes
.
to_i
}
it
{
expect
{
patch_the_trace
}.
to
change
{
job
.
updated_at
}
}
it
'changes the job.trace'
do
patch_the_trace
expect
(
job
.
reload
.
trace
).
to
eq
'BUILD TRACE appended appended'
end
context
'when Runner makes a force-patch'
do
it
{
expect
{
force_patch_the_trace
}.
to
change
{
job
.
updated_at
}
}
it
"doesn't change the job.trace"
do
force_patch_the_trace
expect
(
job
.
reload
.
trace
).
to
eq
'BUILD TRACE appended'
end
end
end
context
'when project for the build has been deleted'
do
let
(
:job
)
do
create
(
:ci_build
,
:running
,
:trace
,
runner_id:
runner
.
id
,
pipeline:
pipeline
)
do
|
job
|
job
.
project
.
update
(
pending_delete:
true
)
end
end
it
'responds with forbidden'
do
expect
(
response
.
status
).
to
eq
(
403
)
end
end
end
context
'when Runner makes a force-patch'
do
before
do
force_patch_the_trace
end
it
'gets correct response'
do
expect
(
response
.
status
).
to
eq
202
expect
(
job
.
reload
.
trace
).
to
eq
'BUILD TRACE appended'
expect
(
response
.
header
).
to
have_key
'Range'
expect
(
response
.
header
).
to
have_key
'Job-Status'
end
end
context
'when content-range start is too big'
do
let
(
:headers_with_range
)
{
headers
.
merge
({
'Content-Range'
=>
'15-20'
})
}
it
'gets 416 error response with range headers'
do
expect
(
response
.
status
).
to
eq
416
expect
(
response
.
header
).
to
have_key
'Range'
expect
(
response
.
header
[
'Range'
]).
to
eq
'0-11'
end
end
context
'when content-range start is too small'
do
let
(
:headers_with_range
)
{
headers
.
merge
({
'Content-Range'
=>
'8-20'
})
}
it
'gets 416 error response with range headers'
do
expect
(
response
.
status
).
to
eq
416
expect
(
response
.
header
).
to
have_key
'Range'
expect
(
response
.
header
[
'Range'
]).
to
eq
'0-11'
end
end
context
'when Content-Range header is missing'
do
let
(
:headers_with_range
)
{
headers
}
it
{
expect
(
response
.
status
).
to
eq
400
}
end
context
'when job has been errased'
do
let
(
:job
)
{
create
(
:ci_build
,
runner_id:
runner
.
id
,
erased_at:
Time
.
now
)
}
it
{
expect
(
response
.
status
).
to
eq
403
}
end
def
patch_the_trace
(
content
=
' appended'
,
request_headers
=
nil
)
unless
request_headers
offset
=
job
.
trace_length
limit
=
offset
+
content
.
length
-
1
request_headers
=
headers
.
merge
({
'Content-Range'
=>
"
#{
offset
}
-
#{
limit
}
"
})
end
Timecop
.
travel
(
job
.
updated_at
+
update_interval
)
do
patch
api
(
"/jobs/
#{
job
.
id
}
/trace"
),
content
,
request_headers
job
.
reload
end
end
def
initial_patch_the_trace
patch_the_trace
(
' appended'
,
headers_with_range
)
end
def
force_patch_the_trace
2
.
times
{
patch_the_trace
(
''
)
}
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