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
1
Merge Requests
1
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
nexedi
gitlab-ce
Commits
914cfbd2
Commit
914cfbd2
authored
Oct 06, 2015
by
Kamil Trzcinski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement Commit Status API
parent
5ffbf5fe
Changes
29
Hide whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
767 additions
and
262 deletions
+767
-262
CHANGELOG
CHANGELOG
+1
-0
app/models/ability.rb
app/models/ability.rb
+2
-0
app/models/ci/build.rb
app/models/ci/build.rb
+15
-72
app/models/ci/commit.rb
app/models/ci/commit.rb
+41
-47
app/models/commit.rb
app/models/commit.rb
+8
-0
app/models/commit_status.rb
app/models/commit_status.rb
+79
-0
app/models/generic_commit_status.rb
app/models/generic_commit_status.rb
+15
-0
app/services/ci/create_commit_service.rb
app/services/ci/create_commit_service.rb
+2
-0
app/views/projects/builds/show.html.haml
app/views/projects/builds/show.html.haml
+3
-3
app/views/projects/commit/ci.html.haml
app/views/projects/commit/ci.html.haml
+29
-7
app/views/projects/commit_statuses/_commit_status.html.haml
app/views/projects/commit_statuses/_commit_status.html.haml
+52
-0
db/migrate/20151008123042_add_type_and_description_to_builds.rb
...rate/20151008123042_add_type_and_description_to_builds.rb
+9
-0
db/migrate/20151008130321_migrate_name_to_description_for_builds.rb
.../20151008130321_migrate_name_to_description_for_builds.rb
+5
-0
db/schema.rb
db/schema.rb
+6
-1
doc/api/commits.md
doc/api/commits.md
+2
-1
lib/api/api.rb
lib/api/api.rb
+1
-0
lib/api/commit_statuses.rb
lib/api/commit_statuses.rb
+79
-0
lib/api/entities.rb
lib/api/entities.rb
+7
-1
lib/ci/api/entities.rb
lib/ci/api/entities.rb
+2
-2
spec/factories/ci/builds.rb
spec/factories/ci/builds.rb
+1
-0
spec/factories/commit_statuses.rb
spec/factories/commit_statuses.rb
+15
-0
spec/features/commits_spec.rb
spec/features/commits_spec.rb
+1
-0
spec/models/build_spec.rb
spec/models/build_spec.rb
+0
-111
spec/models/ci/commit_spec.rb
spec/models/ci/commit_spec.rb
+44
-13
spec/models/ci/project_services/mail_service_spec.rb
spec/models/ci/project_services/mail_service_spec.rb
+4
-4
spec/models/commit_status_spec.rb
spec/models/commit_status_spec.rb
+157
-0
spec/models/generic_commit_status_spec.rb
spec/models/generic_commit_status_spec.rb
+39
-0
spec/requests/api/commit_status_spec.rb
spec/requests/api/commit_status_spec.rb
+135
-0
spec/requests/api/commits_spec.rb
spec/requests/api/commits_spec.rb
+13
-0
No files found.
CHANGELOG
View file @
914cfbd2
...
...
@@ -16,6 +16,7 @@ v 8.1.0 (unreleased)
- Move CI charts to project graphs area
- Fix cases where Markdown did not render links in activity feed (Stan Hu)
- Add first and last to pagination (Zeger-Jan van de Weg)
- Added Commit Status API
- Show CI status on commit page
- Show CI status on Your projects page and Starred projects page
- Remove "Continuous Integration" page from dashboard
...
...
app/models/ability.rb
View file @
914cfbd2
...
...
@@ -135,6 +135,8 @@ class Ability
def
project_report_rules
project_guest_rules
+
[
:create_commit_status
,
:read_commit_statuses
,
:download_code
,
:fork_project
,
:create_project_snippet
,
...
...
app/models/ci/build.rb
View file @
914cfbd2
...
...
@@ -24,32 +24,19 @@
#
module
Ci
class
Build
<
ActiveRecord
::
Base
extend
Ci
::
Model
class
Build
<
CommitStatus
LAZY_ATTRIBUTES
=
[
'trace'
]
belongs_to
:commit
,
class_name:
'Ci::Commit'
belongs_to
:runner
,
class_name:
'Ci::Runner'
belongs_to
:trigger_request
,
class_name:
'Ci::TriggerRequest'
belongs_to
:user
serialize
:options
validates
:commit
,
presence:
true
validates
:status
,
presence:
true
validates
:coverage
,
numericality:
true
,
allow_blank:
true
validates_presence_of
:ref
scope
:running
,
->
()
{
where
(
status:
"running"
)
}
scope
:pending
,
->
()
{
where
(
status:
"pending"
)
}
scope
:success
,
->
()
{
where
(
status:
"success"
)
}
scope
:failed
,
->
()
{
where
(
status:
"failed"
)
}
scope
:unstarted
,
->
()
{
where
(
runner_id:
nil
)
}
scope
:running_or_pending
,
->
()
{
where
(
status
:[
:running
,
:pending
])
}
scope
:latest
,
->
()
{
where
(
id:
unscope
(
:select
).
select
(
'max(id)'
).
group
(
:name
,
:ref
)).
order
(
stage_idx: :asc
)
}
scope
:ignore_failures
,
->
()
{
where
(
allow_failure:
false
)
}
scope
:for_ref
,
->
(
ref
)
{
where
(
ref:
ref
)
}
scope
:similar
,
->
(
build
)
{
where
(
ref:
build
.
ref
,
tag:
build
.
tag
,
trigger_request_id:
build
.
trigger_request_id
)
}
acts_as_taggable
...
...
@@ -74,13 +61,14 @@ module Ci
def
create_from
(
build
)
new_build
=
build
.
dup
new_build
.
status
=
:pending
new_build
.
status
=
'pending'
new_build
.
runner_id
=
nil
new_build
.
trigger_request_id
=
nil
new_build
.
save
end
def
retry
(
build
)
new_build
=
Ci
::
Build
.
new
(
status:
:pending
)
new_build
=
Ci
::
Build
.
new
(
status:
'pending'
)
new_build
.
ref
=
build
.
ref
new_build
.
tag
=
build
.
tag
new_build
.
options
=
build
.
options
...
...
@@ -98,28 +86,7 @@ module Ci
end
state_machine
:status
,
initial: :pending
do
event
:run
do
transition
pending: :running
end
event
:drop
do
transition
running: :failed
end
event
:success
do
transition
running: :success
end
event
:cancel
do
transition
[
:pending
,
:running
]
=>
:canceled
end
after_transition
pending: :running
do
|
build
,
transition
|
build
.
update_attributes
started_at:
Time
.
now
end
after_transition
any
=>
[
:success
,
:failed
,
:canceled
]
do
|
build
,
transition
|
build
.
update_attributes
finished_at:
Time
.
now
project
=
build
.
project
if
project
.
web_hooks?
...
...
@@ -136,19 +103,10 @@ module Ci
build
.
update_coverage
end
end
state
:pending
,
value:
'pending'
state
:running
,
value:
'running'
state
:failed
,
value:
'failed'
state
:success
,
value:
'success'
state
:canceled
,
value:
'canceled'
end
delegate
:sha
,
:short_sha
,
:project
,
:gl_project
,
to: :commit
,
prefix:
false
def
before_sha
Gitlab
::
Git
::
BLANK_SHA
def
ignored?
failed?
&&
allow_failure?
end
def
trace_html
...
...
@@ -156,22 +114,6 @@ module Ci
html
||
''
end
def
started?
!
pending?
&&
!
canceled?
&&
started_at
end
def
active?
running?
||
pending?
end
def
complete?
canceled?
||
success?
||
failed?
end
def
ignored?
failed?
&&
allow_failure?
end
def
timeout
project
.
timeout
end
...
...
@@ -180,14 +122,6 @@ module Ci
yaml_variables
+
project_variables
+
trigger_variables
end
def
duration
if
started_at
&&
finished_at
finished_at
-
started_at
elsif
started_at
Time
.
now
-
started_at
end
end
def
project
commit
.
project
end
...
...
@@ -278,6 +212,15 @@ module Ci
"
#{
dir_to_trace
}
/
#{
id
}
.log"
end
def
description
name
end
def
target_url
Gitlab
::
Application
.
routes
.
url_helpers
.
namespace_project_build_url
(
gl_project
.
namespace
,
gl_project
,
self
)
end
private
def
yaml_variables
...
...
app/models/ci/commit.rb
View file @
914cfbd2
...
...
@@ -20,7 +20,8 @@ module Ci
extend
Ci
::
Model
belongs_to
:gl_project
,
class_name:
'::Project'
,
foreign_key: :gl_project_id
has_many
:builds
,
dependent: :destroy
,
class_name:
'Ci::Build'
has_many
:statuses
,
dependent: :destroy
,
class_name:
'CommitStatus'
has_many
:builds
,
class_name:
'Ci::Build'
has_many
:trigger_requests
,
dependent: :destroy
,
class_name:
'Ci::TriggerRequest'
validates_presence_of
:sha
...
...
@@ -81,12 +82,11 @@ module Ci
end
def
stage
running_or_pending
=
builds_without_retry
.
running_or_pending
running_or_pending
.
limit
(
1
).
pluck
(
:stage
).
first
running_or_pending
=
statuses
.
latest
.
running_or_pending
running_or_pending
.
first
.
try
(
:stage
)
end
def
create_builds
(
ref
,
tag
,
user
,
trigger_request
=
nil
)
return
if
skip_ci?
&&
trigger_request
.
blank?
return
unless
config_processor
config_processor
.
stages
.
any?
do
|
stage
|
CreateBuildsService
.
new
.
execute
(
self
,
stage
,
ref
,
tag
,
user
,
trigger_request
).
present?
...
...
@@ -94,7 +94,6 @@ module Ci
end
def
create_next_builds
(
ref
,
tag
,
user
,
trigger_request
)
return
if
skip_ci?
&&
trigger_request
.
blank?
return
unless
config_processor
stages
=
builds
.
where
(
ref:
ref
,
tag:
tag
,
trigger_request:
trigger_request
).
group_by
(
&
:stage
)
...
...
@@ -107,39 +106,47 @@ module Ci
end
def
refs
builds
.
group
(
:ref
).
pluck
(
:ref
)
statuses
.
pluck
(
:ref
).
compact
.
uniq
end
def
last_ref
builds
.
latest
.
first
.
try
(
:ref
)
end
def
builds_without_retry
builds
.
latest
def
statuses_for_ref
(
ref
=
nil
)
if
ref
statuses
.
for_ref
(
ref
)
else
statuses
end
end
def
builds_without_retry_for_ref
(
ref
)
builds
.
for_ref
(
ref
).
latest
def
builds_without_retry
(
ref
=
nil
)
if
ref
builds
.
for_ref
(
ref
).
latest
else
builds
.
latest
end
end
def
retried
_builds
@retried
_builds
||=
(
builds
.
order
(
id: :desc
)
-
builds_without_retry
)
def
retried
@retried
||=
(
statuses
.
order
(
id: :desc
)
-
statuses
.
latest
)
end
def
status
if
skip_ci?
return
'skipped'
elsif
yaml_errors
.
present?
def
status
(
ref
=
nil
)
if
yaml_errors
.
present?
return
'failed'
elsif
builds
.
none?
end
latest_statuses
=
statuses
.
latest
.
to_a
latest_statuses
.
reject!
{
|
status
|
status
.
try
(
&
:allow_failure?
)
}
latest_statuses
.
select!
{
|
status
|
status
.
ref
==
nil
||
status
.
ref
==
ref
}
if
ref
if
latest_statuses
.
none?
return
'skipped'
elsif
success?
elsif
latest_statuses
.
all?
(
&
:success?
)
'success'
elsif
pending?
elsif
latest_statuses
.
all?
(
&
:pending?
)
'pending'
elsif
running?
elsif
latest_statuses
.
any?
(
&
:running?
)
||
latest_statuses
.
any?
(
&
:pending?
)
'running'
elsif
canceled?
elsif
latest_statuses
.
all?
(
&
:canceled?
)
'canceled'
else
'failed'
...
...
@@ -147,21 +154,15 @@ module Ci
end
def
pending?
builds_without_retry
.
all?
do
|
build
|
build
.
pending?
end
status
==
'pending'
end
def
running?
builds_without_retry
.
any?
do
|
build
|
build
.
running?
||
build
.
pending?
end
status
==
'running'
end
def
success?
builds_without_retry
.
all?
do
|
build
|
build
.
success?
||
build
.
ignored?
end
status
==
'success'
end
def
failed?
...
...
@@ -169,21 +170,15 @@ module Ci
end
def
canceled?
builds_without_retry
.
all?
do
|
build
|
build
.
canceled?
end
end
def
duration
@duration
||=
builds_without_retry
.
select
(
&
:duration
).
sum
(
&
:duration
).
to_i
status
==
'canceled'
end
def
duration
_for_ref
(
ref
)
builds_without_retry_for_ref
(
ref
)
.
select
(
&
:duration
).
sum
(
&
:duration
).
to_i
def
duration
(
ref
=
nil
)
statuses_for_ref
(
ref
).
latest
.
select
(
&
:duration
).
sum
(
&
:duration
).
to_i
end
def
finished_at
@finished_at
||=
build
s
.
order
(
'finished_at DESC'
).
first
.
try
(
:finished_at
)
@finished_at
||=
statuse
s
.
order
(
'finished_at DESC'
).
first
.
try
(
:finished_at
)
end
def
coverage
...
...
@@ -195,8 +190,8 @@ module Ci
end
end
def
matrix
_for_ref
?
(
ref
)
builds_without_retry
_for_ref
(
ref
).
pluck
(
:id
).
size
>
1
def
matrix?
(
ref
)
builds_without_retry
(
ref
).
pluck
(
:id
).
size
>
1
end
def
config_processor
...
...
@@ -217,7 +212,6 @@ module Ci
end
def
skip_ci?
return
false
if
builds
.
any?
git_commit_message
=~
/(\[ci skip\])/
if
git_commit_message
end
...
...
app/models/commit.rb
View file @
914cfbd2
...
...
@@ -184,4 +184,12 @@ class Commit
def
parents
@parents
||=
Commit
.
decorate
(
super
,
project
)
end
def
ci_commit
project
.
ci_commit
(
sha
)
end
def
status
ci_commit
.
try
(
:status
)
||
:not_found
end
end
app/models/commit_status.rb
0 → 100644
View file @
914cfbd2
class
CommitStatus
<
ActiveRecord
::
Base
self
.
table_name
=
'ci_builds'
belongs_to
:commit
,
class_name:
'Ci::Commit'
belongs_to
:user
validates
:commit
,
presence:
true
validates
:status
,
inclusion:
{
in:
%w(pending running failed success canceled)
}
validates_presence_of
:name
scope
:running
,
->
()
{
where
(
status:
'running'
)
}
scope
:pending
,
->
()
{
where
(
status:
'pending'
)
}
scope
:success
,
->
()
{
where
(
status:
'success'
)
}
scope
:failed
,
->
()
{
where
(
status:
'failed'
)
}
scope
:running_or_pending
,
->
()
{
where
(
status
:[
:running
,
:pending
])
}
scope
:latest
,
->
()
{
where
(
id:
unscope
(
:select
).
select
(
'max(id)'
).
group
(
:name
,
:ref
)).
order
(
stage_idx: :asc
)
}
scope
:for_ref
,
->
(
ref
)
{
where
(
ref:
[
ref
,
nil
])
}
scope
:running_or_pending
,
->
()
{
where
(
status:
[
:running
,
:pending
])
}
state_machine
:status
,
initial: :pending
do
event
:run
do
transition
pending: :running
end
event
:drop
do
transition
running: :failed
end
event
:success
do
transition
[
:pending
,
:running
]
=>
:success
end
event
:cancel
do
transition
[
:pending
,
:running
]
=>
:canceled
end
after_transition
pending: :running
do
|
build
,
transition
|
build
.
update_attributes
started_at:
Time
.
now
end
after_transition
any
=>
[
:success
,
:failed
,
:canceled
]
do
|
build
,
transition
|
build
.
update_attributes
finished_at:
Time
.
now
end
state
:pending
,
value:
'pending'
state
:running
,
value:
'running'
state
:failed
,
value:
'failed'
state
:success
,
value:
'success'
state
:canceled
,
value:
'canceled'
end
delegate
:sha
,
:short_sha
,
:gl_project
,
to: :commit
,
prefix:
false
def
before_sha
Gitlab
::
Git
::
BLANK_SHA
end
def
started?
!
pending?
&&
!
canceled?
&&
started_at
end
def
active?
running?
||
pending?
end
def
complete?
canceled?
||
success?
||
failed?
end
def
duration
if
started_at
&&
finished_at
finished_at
-
started_at
elsif
started_at
Time
.
now
-
started_at
end
end
end
app/models/generic_commit_status.rb
0 → 100644
View file @
914cfbd2
class
GenericCommitStatus
<
CommitStatus
before_validation
:set_default_values
# GitHub compatible API
alias_attribute
:context
,
:name
def
set_default_values
self
.
context
||=
'default'
self
.
stage
||=
'external'
end
def
tags
[
:external
]
end
end
app/services/ci/create_commit_service.rb
View file @
914cfbd2
...
...
@@ -17,6 +17,8 @@ module Ci
tag
=
origin_ref
.
start_with?
(
'refs/tags/'
)
commit
=
project
.
gl_project
.
ensure_ci_commit
(
sha
)
return
false
if
commit
.
skip_ci?
commit
.
update_committed!
commit
.
create_builds
(
ref
,
tag
,
user
)
...
...
app/views/projects/builds/show.html.haml
View file @
914cfbd2
...
...
@@ -7,9 +7,9 @@
%code
#{
@build
.
ref
}
#up-build-trace
-
if
@commit
.
matrix
_for_ref
?
(
@build
.
ref
)
-
if
@commit
.
matrix?
(
@build
.
ref
)
%ul
.center-top-menu.build-top-menu
-
@commit
.
builds_without_retry
_for_ref
(
@build
.
ref
).
each
do
|
build
|
-
@commit
.
builds_without_retry
(
@build
.
ref
).
each
do
|
build
|
%li
{
class:
(
'active'
if
build
==
@build
)
}
=
link_to
namespace_project_build_path
(
@project
.
namespace
,
@project
,
build
)
do
=
ci_icon_for_status
(
build
.
status
)
...
...
@@ -20,7 +20,7 @@
=
build
.
id
-
unless
@commit
.
builds_without_retry
_for_ref
(
@build
.
ref
).
include?
(
@build
)
-
unless
@commit
.
builds_without_retry
(
@build
.
ref
).
include?
(
@build
)
%li
.active
%a
Build ##{@build.id}
...
...
app/views/projects/commit/ci.html.haml
View file @
914cfbd2
...
...
@@ -20,13 +20,35 @@
.bs-callout.bs-callout-warning
\.gitlab-ci.yml not found in this commit
-
@ci_commit
.
refs
.
each
do
|
ref
|
-
if
@ci_commit
.
refs
.
blank?
.gray-content-block.second-block
Latest builds
-
if
@ci_commit
.
duration
>
0
%small
.pull-right
%i
.fa.fa-time
#{
time_interval_in_words
@ci_commit
.
duration
}
%table
.table.builds
%thead
%tr
%th
Status
%th
Build ID
%th
Stage
%th
Name
%th
Duration
%th
Finished at
-
if
@ci_project
&&
@ci_project
.
coverage_enabled?
%th
Coverage
%th
=
render
partial:
"projects/commit_statuses/commit_status"
,
collection:
@ci_commit
.
statuses
.
latest
,
coverage:
@ci_project
.
try
(
:coverage_enabled?
),
controls:
true
-
@ci_commit
.
refs
.
sort
.
each
do
|
ref
|
.gray-content-block.second-block
Builds for
#{
ref
}
-
if
@ci_commit
.
duration
_for_ref
(
ref
)
>
0
-
if
@ci_commit
.
duration
(
ref
)
>
0
%small
.pull-right
%i
.fa.fa-time
#{
time_interval_in_words
@ci_commit
.
duration
_for_ref
(
ref
)
}
#{
time_interval_in_words
@ci_commit
.
duration
(
ref
)
}
%table
.table.builds
%thead
...
...
@@ -40,10 +62,10 @@
-
if
@ci_project
&&
@ci_project
.
coverage_enabled?
%th
Coverage
%th
=
render
partial:
"projects/
builds/build"
,
collection:
@ci_commit
.
builds_without_retry
.
for_ref
(
ref
),
controls:
true
=
render
partial:
"projects/
commit_statuses/commit_status"
,
collection:
@ci_commit
.
statuses
.
for_ref
(
ref
).
latest
,
coverage:
@ci_project
.
try
(
:coverage_enabled?
),
controls:
true
-
if
@ci_commit
.
retried
_builds
.
any?
%h3
-
if
@ci_commit
.
retried
.
any?
.gray-content-block.second-block
Retried builds
%table
.table.builds
...
...
@@ -59,4 +81,4 @@
-
if
@ci_project
&&
@ci_project
.
coverage_enabled?
%th
Coverage
%th
=
render
partial:
"projects/
builds/build"
,
collection:
@ci_commit
.
retried_builds
,
ref:
true
=
render
partial:
"projects/
commit_statuses/commit_status"
,
collection:
@ci_commit
.
retried
,
coverage:
@ci_project
.
try
(
:coverage_enabled?
)
,
ref:
true
app/views/projects/
builds/_build
.html.haml
→
app/views/projects/
commit_statuses/_commit_status
.html.haml
View file @
914cfbd2
-
gl_project
=
build
.
project
.
gl_project
%tr
.build
%tr
.commit_status
%td
.status
=
ci_status_with_icon
(
build
.
status
)
=
ci_status_with_icon
(
commit_status
.
status
)
%td
.build-link
=
link_to
namespace_project_build_path
(
gl_project
.
namespace
,
gl_project
,
build
)
do
%strong
Build ##{build.id}
%td
.commit_status-link
-
if
commit_status
.
target_url
=
link_to
commit_status
.
target_url
do
%strong
Build ##{commit_status.id}
-
else
%strong
Build ##{commit_status.id}
-
if
defined?
(
ref
)
%td
=
build
.
ref
=
commit_status
.
ref
%td
=
build
.
stage
=
commit_status
.
stage
%td
=
build
.
name
=
commit_status
.
description
.pull-right
-
if
build
.
tags
.
any?
-
build
.
tag_list
.
each
do
|
tag
|
-
if
commit_status
.
tags
.
any?
-
commit_status
.
tags
.
each
do
|
tag
|
%span
.label.label-primary
=
tag
-
if
build
.
trigger_request
-
if
commit_status
.
try
(
:trigger_request
)
%span
.label.label-info
triggered
-
if
build
.
allow_failure
-
if
commit_status
.
try
(
:allow_failure
)
%span
.label.label-danger
allowed to fail
%td
.duration
-
if
build
.
duration
#{
duration_in_words
(
build
.
finished_at
,
build
.
started_at
)
}
-
if
commit_status
.
duration
#{
duration_in_words
(
commit_status
.
finished_at
,
commit_status
.
started_at
)
}
%td
.timestamp
-
if
build
.
finished_at
%span
#{
time_ago_in_words
build
.
finished_at
}
ago
-
if
commit_status
.
finished_at
%span
#{
time_ago_in_words
commit_status
.
finished_at
}
ago
-
if
build
.
project
.
coverage_enabled?
-
if
defined?
(
coverage
)
%td
.coverage
-
if
build
.
coverage
#{
build
.
coverage
}
%
-
if
commit_status
.
try
(
:coverage
)
#{
commit_status
.
coverage
}
%
%td
-
if
defined?
(
controls
)
&&
current_user
&&
can?
(
current_user
,
:manage_builds
,
gl_project
)
.pull-right
-
if
build
.
active?
=
link_to
cancel_namespace_project_build_path
(
gl_project
.
namespace
,
gl_project
,
build
,
return_to:
request
.
original_url
),
title:
'Cancel build
'
do
-
if
commit_status
.
active?
=
link_to
cancel_namespace_project_build_path
(
gl_project
.
namespace
,
gl_project
,
commit_status
,
return_to:
request
.
original_url
),
title:
'Cancel commit_status
'
do
%i
.fa.fa-remove.cred
-
elsif
build
.
commands
.
present?
=
link_to
retry_namespace_project_build_path
(
gl_project
.
namespace
,
gl_project
,
build
,
return_to:
request
.
original_url
),
method: :post
,
title:
'Retry build
'
do
-
elsif
commit_status
.
commands
.
present?
=
link_to
retry_namespace_project_build_path
(
gl_project
.
namespace
,
gl_project
,
commit_status
,
return_to:
request
.
original_url
),
method: :post
,
title:
'Retry commit_status
'
do
%i
.fa.fa-repeat
db/migrate/20151008123042_add_type_and_description_to_builds.rb
0 → 100644
View file @
914cfbd2
class
AddTypeAndDescriptionToBuilds
<
ActiveRecord
::
Migration
def
change
add_column
:ci_builds
,
:type
,
:string
add_column
:ci_builds
,
:target_url
,
:string
add_column
:ci_builds
,
:description
,
:string
add_index
:ci_builds
,
[
:commit_id
,
:type
,
:ref
]
add_index
:ci_builds
,
[
:commit_id
,
:type
,
:name
,
:ref
]
end
end
db/migrate/20151008130321_migrate_name_to_description_for_builds.rb
0 → 100644
View file @
914cfbd2
class
MigrateNameToDescriptionForBuilds
<
ActiveRecord
::
Migration
def
change
execute
(
"UPDATE ci_builds SET type='Ci::Build' WHERE type IS NULL"
)
end
end
db/schema.rb
View file @
914cfbd2
...
...
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord
::
Schema
.
define
(
version:
2015100
712051
1
)
do
ActiveRecord
::
Schema
.
define
(
version:
2015100
813032
1
)
do
# These are extensions that must be enabled in order to support this database
enable_extension
"plpgsql"
...
...
@@ -103,9 +103,14 @@ ActiveRecord::Schema.define(version: 20151007120511) do
t
.
boolean
"tag"
t
.
string
"ref"
t
.
integer
"user_id"
t
.
string
"type"
t
.
string
"target_url"
t
.
string
"description"
end
add_index
"ci_builds"
,
[
"commit_id"
,
"stage_idx"
,
"created_at"
],
name:
"index_ci_builds_on_commit_id_and_stage_idx_and_created_at"
,
using: :btree
add_index
"ci_builds"
,
[
"commit_id"
,
"type"
,
"name"
,
"ref"
],
name:
"index_ci_builds_on_commit_id_and_type_and_name_and_ref"
,
using: :btree
add_index
"ci_builds"
,
[
"commit_id"
,
"type"
,
"ref"
],
name:
"index_ci_builds_on_commit_id_and_type_and_ref"
,
using: :btree
add_index
"ci_builds"
,
[
"commit_id"
],
name:
"index_ci_builds_on_commit_id"
,
using: :btree
add_index
"ci_builds"
,
[
"project_id"
,
"commit_id"
],
name:
"index_ci_builds_on_project_id_and_commit_id"
,
using: :btree
add_index
"ci_builds"
,
[
"project_id"
],
name:
"index_ci_builds_on_project_id"
,
using: :btree
...
...
doc/api/commits.md
View file @
914cfbd2
...
...
@@ -62,7 +62,8 @@ Parameters:
"authored_date"
:
"2012-09-20T09:06:12+03:00"
,
"parent_ids"
:
[
"ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba"
]
],
"status"
:
"running"
}
```
...
...
lib/api/api.rb
View file @
914cfbd2
...
...
@@ -46,6 +46,7 @@ module API
mount
Services
mount
Files
mount
Commits
mount
CommitStatus
mount
Namespaces
mount
Branches
mount
Labels
...
...
lib/api/commit_statuses.rb
0 → 100644
View file @
914cfbd2
require
'mime/types'
module
API
# Project commit statuses API
class
CommitStatus
<
Grape
::
API
resource
:projects
do
before
{
authenticate!
}
before
{
authorize!
:read_commit_statuses
,
user_project
}
# Get a commit's statuses
#
# Parameters:
# id (required) - The ID of a project
# sha (required) - The commit hash
# ref (optional) - The ref
# stage (optional) - The stage
# name (optional) - The name
# all (optional) - Show all statuses, default: false
# Examples:
# GET /projects/:id/repository/commits/:sha/statuses
get
':id/repository/commits/:sha/statuses'
do
sha
=
params
[
:sha
]
ci_commit
=
user_project
.
ci_commit
(
sha
)
not_found!
'Commit'
unless
ci_commit
statuses
=
ci_commit
.
statuses
statuses
=
statuses
.
latest
unless
parse_boolean
(
params
[
:all
])
statuses
=
statuses
.
where
(
ref:
params
[
:ref
])
if
params
[
:ref
].
present?
statuses
=
statuses
.
where
(
name:
params
[
:stage
])
if
params
[
:stage
].
present?
statuses
=
statuses
.
where
(
name:
params
[
:name
])
if
params
[
:name
].
present?
present
paginate
(
statuses
),
with:
Entities
::
CommitStatus
end
# Post status to commit
#
# Parameters:
# id (required) - The ID of a project
# sha (required) - The commit hash
# ref (optional) - The ref
# state (required) - The state of the status. Can be: pending, running, success, error or failure
# target_url (optional) - The target URL to associate with this status
# description (optional) - A short description of the status
# name or context (optional) - A string label to differentiate this status from the status of other systems. Default: "default"
# Examples:
# POST /projects/:id/repository/commits/:sha/status
post
':id/statuses/:sha'
do
required_attributes!
[
:state
]
attrs
=
attributes_for_keys
[
:ref
,
:target_url
,
:description
,
:context
,
:name
]
commit
=
@project
.
commit
(
params
[
:sha
])
not_found!
'Commit'
unless
commit
ci_commit
=
@project
.
ensure_ci_commit
(
commit
.
sha
)
name
=
params
[
:name
]
||
params
[
:context
]
status
=
GenericCommitStatus
.
running_or_pending
.
find_by
(
commit:
ci_commit
,
name:
name
,
ref:
params
[
:ref
])
status
=
GenericCommitStatus
.
new
(
commit:
ci_commit
)
unless
status
status
.
update
(
attrs
)
case
params
[
:state
].
to_s
when
'running'
status
.
run
when
'success'
status
.
success
when
'failed'
status
.
drop
when
'canceled'
status
.
cancel
else
status
.
status
=
params
[
:state
].
to_s
end
if
status
.
save
present
status
,
with:
Entities
::
CommitStatus
else
render_validation_error!
(
status
)
end
end
end
end
end
lib/api/entities.rb
View file @
914cfbd2
...
...
@@ -65,7 +65,7 @@ module API
expose
:issues_enabled
,
:merge_requests_enabled
,
:wiki_enabled
,
:snippets_enabled
,
:created_at
,
:last_activity_at
expose
:creator_id
expose
:namespace
expose
:forked_from_project
,
using:
Entities
::
ForkedFromProject
,
if:
lambda
{
|
project
,
options
|
project
.
forked?
}
expose
:forked_from_project
,
using:
Entities
::
ForkedFromProject
,
if:
lambda
{
|
project
,
options
|
project
.
forked?
}
expose
:avatar_url
expose
:star_count
,
:forks_count
end
...
...
@@ -149,6 +149,7 @@ module API
class
RepoCommitDetail
<
RepoCommit
expose
:parent_ids
,
:committed_date
,
:authored_date
expose
:status
end
class
ProjectSnippet
<
Grape
::
Entity
...
...
@@ -228,6 +229,11 @@ module API
expose
:created_at
end
class
CommitStatus
<
Grape
::
Entity
expose
:id
,
:sha
,
:ref
,
:status
,
:name
,
:target_url
,
:description
,
:created_at
,
:started_at
,
:finished_at
end
class
Event
<
Grape
::
Entity
expose
:title
,
:project_id
,
:action_name
expose
:target_id
,
:target_type
,
:author_id
...
...
lib/ci/api/entities.rb
View file @
914cfbd2
...
...
@@ -2,7 +2,7 @@ module Ci
module
API
module
Entities
class
Commit
<
Grape
::
Entity
expose
:id
,
:
ref
,
:sha
,
:project_id
,
:before_sha
,
:created_at
expose
:id
,
:
sha
,
:project_id
,
:created_at
expose
:status
,
:finished_at
,
:duration
expose
:git_commit_message
,
:git_author_name
,
:git_author_email
end
...
...
@@ -12,7 +12,7 @@ module Ci
end
class
Build
<
Grape
::
Entity
expose
:id
,
:commands
,
:ref
,
:sha
,
:project_id
,
:repo_url
,
expose
:id
,
:commands
,
:ref
,
:sha
,
:
status
,
:
project_id
,
:repo_url
,
:before_sha
,
:allow_git_fetch
,
:project_name
expose
:options
do
|
model
|
...
...
spec/factories/ci/builds.rb
View file @
914cfbd2
...
...
@@ -27,6 +27,7 @@
FactoryGirl
.
define
do
factory
:ci_build
,
class:
Ci
::
Build
do
name
'test'
ref
'master'
tag
false
started_at
'Di 29. Okt 09:51:28 CET 2013'
...
...
spec/factories/commit_statuses.rb
0 → 100644
View file @
914cfbd2
FactoryGirl
.
define
do
factory
:commit_status
,
class:
CommitStatus
do
started_at
'Di 29. Okt 09:51:28 CET 2013'
finished_at
'Di 29. Okt 09:53:28 CET 2013'
name
'default'
status
'success'
description
'commit status'
commit
factory: :ci_commit
factory
:generic_commit_status
,
class:
GenericCommitStatus
do
name
'generic'
description
'external commit status'
end
end
end
spec/features/commits_spec.rb
View file @
914cfbd2
...
...
@@ -12,6 +12,7 @@ describe "Commits" do
@ci_project
=
project
.
ensure_gitlab_ci_project
@commit
=
FactoryGirl
.
create
:ci_commit
,
gl_project:
project
,
sha:
project
.
commit
.
sha
@build
=
FactoryGirl
.
create
:ci_build
,
commit:
@commit
@generic_status
=
FactoryGirl
.
create
:generic_commit_status
,
commit:
@commit
end
before
do
...
...
spec/models/
ci/
build_spec.rb
→
spec/models/build_spec.rb
View file @
914cfbd2
...
...
@@ -30,17 +30,9 @@ describe Ci::Build do
let
(
:gl_project
)
{
FactoryGirl
.
create
:empty_project
,
gitlab_ci_project:
project
}
let
(
:commit
)
{
FactoryGirl
.
create
:ci_commit
,
gl_project:
gl_project
}
let
(
:build
)
{
FactoryGirl
.
create
:ci_build
,
commit:
commit
}
subject
{
build
}
it
{
is_expected
.
to
belong_to
(
:commit
)
}
it
{
is_expected
.
to
belong_to
(
:user
)
}
it
{
is_expected
.
to
validate_presence_of
:status
}
it
{
is_expected
.
to
validate_presence_of
:ref
}
it
{
is_expected
.
to
respond_to
:success?
}
it
{
is_expected
.
to
respond_to
:failed?
}
it
{
is_expected
.
to
respond_to
:running?
}
it
{
is_expected
.
to
respond_to
:pending?
}
it
{
is_expected
.
to
respond_to
:trace_html
}
describe
:first_pending
do
...
...
@@ -67,72 +59,6 @@ describe Ci::Build do
end
end
describe
:started?
do
subject
{
build
.
started?
}
context
'without started_at'
do
before
{
build
.
started_at
=
nil
}
it
{
is_expected
.
to
be_falsey
}
end
%w(running success failed)
.
each
do
|
status
|
context
"if build status is
#{
status
}
"
do
before
{
build
.
status
=
status
}
it
{
is_expected
.
to
be_truthy
}
end
end
%w(pending canceled)
.
each
do
|
status
|
context
"if build status is
#{
status
}
"
do
before
{
build
.
status
=
status
}
it
{
is_expected
.
to
be_falsey
}
end
end
end
describe
:active?
do
subject
{
build
.
active?
}
%w(pending running)
.
each
do
|
state
|
context
"if build.status is
#{
state
}
"
do
before
{
build
.
status
=
state
}
it
{
is_expected
.
to
be_truthy
}
end
end
%w(success failed canceled)
.
each
do
|
state
|
context
"if build.status is
#{
state
}
"
do
before
{
build
.
status
=
state
}
it
{
is_expected
.
to
be_falsey
}
end
end
end
describe
:complete?
do
subject
{
build
.
complete?
}
%w(success failed canceled)
.
each
do
|
state
|
context
"if build.status is
#{
state
}
"
do
before
{
build
.
status
=
state
}
it
{
is_expected
.
to
be_truthy
}
end
end
%w(pending running)
.
each
do
|
state
|
context
"if build.status is
#{
state
}
"
do
before
{
build
.
status
=
state
}
it
{
is_expected
.
to
be_falsey
}
end
end
end
describe
:ignored?
do
subject
{
build
.
ignored?
}
...
...
@@ -200,31 +126,6 @@ describe Ci::Build do
it
{
is_expected
.
to
eq
(
commit
.
project
.
timeout
)
}
end
describe
:duration
do
subject
{
build
.
duration
}
it
{
is_expected
.
to
eq
(
120.0
)
}
context
'if the building process has not started yet'
do
before
do
build
.
started_at
=
nil
build
.
finished_at
=
nil
end
it
{
is_expected
.
to
be_nil
}
end
context
'if the building process has started'
do
before
do
build
.
started_at
=
Time
.
now
-
1
.
minute
build
.
finished_at
=
nil
end
it
{
is_expected
.
to
be_a
(
Float
)
}
it
{
is_expected
.
to
be
>
0.0
}
end
end
describe
:options
do
let
(
:options
)
do
{
...
...
@@ -239,18 +140,6 @@ describe Ci::Build do
it
{
is_expected
.
to
eq
(
options
)
}
end
describe
:sha
do
subject
{
build
.
sha
}
it
{
is_expected
.
to
eq
(
commit
.
sha
)
}
end
describe
:short_sha
do
subject
{
build
.
short_sha
}
it
{
is_expected
.
to
eq
(
commit
.
short_sha
)
}
end
describe
:allow_git_fetch
do
subject
{
build
.
allow_git_fetch
}
...
...
spec/models/ci/commit_spec.rb
View file @
914cfbd2
...
...
@@ -23,6 +23,8 @@ describe Ci::Commit do
let
(
:commit
)
{
FactoryGirl
.
create
:ci_commit
,
gl_project:
gl_project
}
it
{
is_expected
.
to
belong_to
(
:gl_project
)
}
it
{
is_expected
.
to
have_many
(
:statuses
)
}
it
{
is_expected
.
to
have_many
(
:trigger_requests
)
}
it
{
is_expected
.
to
have_many
(
:builds
)
}
it
{
is_expected
.
to
validate_presence_of
:sha
}
...
...
@@ -47,10 +49,12 @@ describe Ci::Commit do
@second
=
FactoryGirl
.
create
:ci_build
,
commit:
commit
end
it
"creates new build"
do
it
"creates
only a
new build"
do
expect
(
commit
.
builds
.
count
(
:all
)).
to
eq
2
expect
(
commit
.
statuses
.
count
(
:all
)).
to
eq
2
commit
.
retry
expect
(
commit
.
builds
.
count
(
:all
)).
to
eq
3
expect
(
commit
.
statuses
.
count
(
:all
)).
to
eq
3
end
end
...
...
@@ -78,8 +82,8 @@ describe Ci::Commit do
subject
{
commit
.
stage
}
before
do
@second
=
FactoryGirl
.
create
:c
i_build
,
commit:
commit
,
name:
'deploy'
,
stage:
'deploy'
,
stage_idx:
1
,
status: :pending
@first
=
FactoryGirl
.
create
:c
i_build
,
commit:
commit
,
name:
'test'
,
stage:
'test'
,
stage_idx:
0
,
status: :pending
@second
=
FactoryGirl
.
create
:c
ommit_status
,
commit:
commit
,
name:
'deploy'
,
stage:
'deploy'
,
stage_idx:
1
,
status:
'pending'
@first
=
FactoryGirl
.
create
:c
ommit_status
,
commit:
commit
,
name:
'test'
,
stage:
'test'
,
stage_idx:
0
,
status:
'pending'
end
it
'returns first running stage'
do
...
...
@@ -88,7 +92,7 @@ describe Ci::Commit do
context
'first build succeeded'
do
before
do
@first
.
update_attributes
(
status: :success
)
@first
.
success
end
it
'returns last running stage'
do
...
...
@@ -98,8 +102,8 @@ describe Ci::Commit do
context
'all builds succeeded'
do
before
do
@first
.
update_attributes
(
status: :success
)
@second
.
update_attributes
(
status: :success
)
@first
.
success
@second
.
success
end
it
'returns nil'
do
...
...
@@ -111,6 +115,33 @@ describe Ci::Commit do
describe
:create_next_builds
do
end
describe
:refs
do
subject
{
commit
.
refs
}
before
do
FactoryGirl
.
create
:commit_status
,
commit:
commit
,
name:
'deploy'
FactoryGirl
.
create
:commit_status
,
commit:
commit
,
name:
'deploy'
,
ref:
'develop'
FactoryGirl
.
create
:commit_status
,
commit:
commit
,
name:
'deploy'
,
ref:
'master'
end
it
'returns all refs'
do
is_expected
.
to
contain_exactly
(
'master'
,
'develop'
)
end
end
describe
:retried
do
subject
{
commit
.
retried
}
before
do
@commit1
=
FactoryGirl
.
create
:ci_build
,
commit:
commit
,
name:
'deploy'
@commit2
=
FactoryGirl
.
create
:ci_build
,
commit:
commit
,
name:
'deploy'
end
it
'returns old builds'
do
is_expected
.
to
contain_exactly
(
@commit1
)
end
end
describe
:create_builds
do
let
(
:commit
)
{
FactoryGirl
.
create
:ci_commit
,
gl_project:
gl_project
}
...
...
@@ -252,10 +283,10 @@ describe Ci::Commit do
describe
:should_create_next_builds?
do
before
do
@build1
=
FactoryGirl
.
create
:ci_build
,
commit:
commit
,
name:
'build1'
,
ref:
'master'
,
tag:
false
,
status:
:success
@build2
=
FactoryGirl
.
create
:ci_build
,
commit:
commit
,
name:
'build1'
,
ref:
'develop'
,
tag:
false
,
status:
:failed
@build3
=
FactoryGirl
.
create
:ci_build
,
commit:
commit
,
name:
'build1'
,
ref:
'master'
,
tag:
true
,
status:
:failed
@build4
=
FactoryGirl
.
create
:ci_build
,
commit:
commit
,
name:
'build4'
,
ref:
'master'
,
tag:
false
,
status:
:success
@build1
=
FactoryGirl
.
create
:ci_build
,
commit:
commit
,
name:
'build1'
,
ref:
'master'
,
tag:
false
,
status:
'success'
@build2
=
FactoryGirl
.
create
:ci_build
,
commit:
commit
,
name:
'build1'
,
ref:
'develop'
,
tag:
false
,
status:
'failed'
@build3
=
FactoryGirl
.
create
:ci_build
,
commit:
commit
,
name:
'build1'
,
ref:
'master'
,
tag:
true
,
status:
'failed'
@build4
=
FactoryGirl
.
create
:ci_build
,
commit:
commit
,
name:
'build4'
,
ref:
'master'
,
tag:
false
,
status:
'success'
end
context
'for success'
do
...
...
@@ -266,7 +297,7 @@ describe Ci::Commit do
context
'for failed'
do
before
do
@build4
.
update_attributes
(
status:
:failed
)
@build4
.
update_attributes
(
status:
'failed'
)
end
it
'to not create'
do
...
...
@@ -286,7 +317,7 @@ describe Ci::Commit do
context
'for running'
do
before
do
@build4
.
update_attributes
(
status:
:running
)
@build4
.
update_attributes
(
status:
'running'
)
end
it
'to not create'
do
...
...
@@ -296,7 +327,7 @@ describe Ci::Commit do
context
'for retried'
do
before
do
@build5
=
FactoryGirl
.
create
:ci_build
,
commit:
commit
,
name:
'build4'
,
ref:
'master'
,
tag:
false
,
status:
:failed
@build5
=
FactoryGirl
.
create
:ci_build
,
commit:
commit
,
name:
'build4'
,
ref:
'master'
,
tag:
false
,
status:
'failed'
end
it
'to not create'
do
...
...
spec/models/ci/project_services/mail_service_spec.rb
View file @
914cfbd2
...
...
@@ -58,7 +58,7 @@ describe Ci::MailService do
let
(
:project
)
{
FactoryGirl
.
create
(
:ci_project
,
email_add_pusher:
true
,
email_only_broken_builds:
false
)
}
let
(
:gl_project
)
{
FactoryGirl
.
create
(
:empty_project
,
gitlab_ci_project:
project
)
}
let
(
:commit
)
{
FactoryGirl
.
create
(
:ci_commit
,
gl_project:
gl_project
)
}
let
(
:build
)
{
FactoryGirl
.
create
(
:ci_build
,
status:
:success
,
commit:
commit
,
user:
user
)
}
let
(
:build
)
{
FactoryGirl
.
create
(
:ci_build
,
status:
'success'
,
commit:
commit
,
user:
user
)
}
before
do
allow
(
mail
).
to
receive_messages
(
...
...
@@ -86,7 +86,7 @@ describe Ci::MailService do
end
let
(
:gl_project
)
{
FactoryGirl
.
create
(
:empty_project
,
gitlab_ci_project:
project
)
}
let
(
:commit
)
{
FactoryGirl
.
create
(
:ci_commit
,
gl_project:
gl_project
)
}
let
(
:build
)
{
FactoryGirl
.
create
(
:ci_build
,
status:
:success
,
commit:
commit
,
user:
user
)
}
let
(
:build
)
{
FactoryGirl
.
create
(
:ci_build
,
status:
'success'
,
commit:
commit
,
user:
user
)
}
before
do
allow
(
mail
).
to
receive_messages
(
...
...
@@ -115,7 +115,7 @@ describe Ci::MailService do
end
let
(
:gl_project
)
{
FactoryGirl
.
create
(
:empty_project
,
gitlab_ci_project:
project
)
}
let
(
:commit
)
{
FactoryGirl
.
create
(
:ci_commit
,
gl_project:
gl_project
)
}
let
(
:build
)
{
FactoryGirl
.
create
(
:ci_build
,
status:
:success
,
commit:
commit
,
user:
user
)
}
let
(
:build
)
{
FactoryGirl
.
create
(
:ci_build
,
status:
'success'
,
commit:
commit
,
user:
user
)
}
before
do
allow
(
mail
).
to
receive_messages
(
...
...
@@ -144,7 +144,7 @@ describe Ci::MailService do
end
let
(
:gl_project
)
{
FactoryGirl
.
create
(
:empty_project
,
gitlab_ci_project:
project
)
}
let
(
:commit
)
{
FactoryGirl
.
create
(
:ci_commit
,
gl_project:
gl_project
)
}
let
(
:build
)
{
FactoryGirl
.
create
(
:ci_build
,
status:
:success
,
commit:
commit
,
user:
user
)
}
let
(
:build
)
{
FactoryGirl
.
create
(
:ci_build
,
status:
'success'
,
commit:
commit
,
user:
user
)
}
before
do
allow
(
mail
).
to
receive_messages
(
...
...
spec/models/commit_status_spec.rb
0 → 100644
View file @
914cfbd2
require
'spec_helper'
describe
CommitStatus
do
let
(
:commit
)
{
FactoryGirl
.
create
:ci_commit
}
let
(
:commit_status
)
{
FactoryGirl
.
create
:commit_status
,
commit:
commit
}
it
{
is_expected
.
to
belong_to
(
:commit
)
}
it
{
is_expected
.
to
belong_to
(
:user
)
}
it
{
is_expected
.
to
validate_presence_of
(
:name
)
}
it
{
is_expected
.
to
validate_inclusion_of
(
:status
).
in_array
(
%w(pending running failed success canceled)
)
}
it
{
is_expected
.
to
delegate_method
(
:sha
).
to
(
:commit
)
}
it
{
is_expected
.
to
delegate_method
(
:short_sha
).
to
(
:commit
)
}
it
{
is_expected
.
to
delegate_method
(
:gl_project
).
to
(
:commit
)
}
it
{
is_expected
.
to
respond_to
:success?
}
it
{
is_expected
.
to
respond_to
:failed?
}
it
{
is_expected
.
to
respond_to
:running?
}
it
{
is_expected
.
to
respond_to
:pending?
}
describe
:started?
do
subject
{
commit_status
.
started?
}
context
'without started_at'
do
before
{
commit_status
.
started_at
=
nil
}
it
{
is_expected
.
to
be_falsey
}
end
%w(running success failed)
.
each
do
|
status
|
context
"if commit status is
#{
status
}
"
do
before
{
commit_status
.
status
=
status
}
it
{
is_expected
.
to
be_truthy
}
end
end
%w(pending canceled)
.
each
do
|
status
|
context
"if commit status is
#{
status
}
"
do
before
{
commit_status
.
status
=
status
}
it
{
is_expected
.
to
be_falsey
}
end
end
end
describe
:active?
do
subject
{
commit_status
.
active?
}
%w(pending running)
.
each
do
|
state
|
context
"if commit_status.status is
#{
state
}
"
do
before
{
commit_status
.
status
=
state
}
it
{
is_expected
.
to
be_truthy
}
end
end
%w(success failed canceled)
.
each
do
|
state
|
context
"if commit_status.status is
#{
state
}
"
do
before
{
commit_status
.
status
=
state
}
it
{
is_expected
.
to
be_falsey
}
end
end
end
describe
:complete?
do
subject
{
commit_status
.
complete?
}
%w(success failed canceled)
.
each
do
|
state
|
context
"if commit_status.status is
#{
state
}
"
do
before
{
commit_status
.
status
=
state
}
it
{
is_expected
.
to
be_truthy
}
end
end
%w(pending running)
.
each
do
|
state
|
context
"if commit_status.status is
#{
state
}
"
do
before
{
commit_status
.
status
=
state
}
it
{
is_expected
.
to
be_falsey
}
end
end
end
describe
:duration
do
subject
{
commit_status
.
duration
}
it
{
is_expected
.
to
eq
(
120.0
)
}
context
'if the building process has not started yet'
do
before
do
commit_status
.
started_at
=
nil
commit_status
.
finished_at
=
nil
end
it
{
is_expected
.
to
be_nil
}
end
context
'if the building process has started'
do
before
do
commit_status
.
started_at
=
Time
.
now
-
1
.
minute
commit_status
.
finished_at
=
nil
end
it
{
is_expected
.
to
be_a
(
Float
)
}
it
{
is_expected
.
to
be
>
0.0
}
end
end
describe
:latest
do
subject
{
CommitStatus
.
latest
.
order
(
:id
)
}
before
do
@commit1
=
FactoryGirl
.
create
:commit_status
,
commit:
commit
,
name:
'aa'
,
ref:
'bb'
,
status:
'running'
@commit2
=
FactoryGirl
.
create
:commit_status
,
commit:
commit
,
name:
'cc'
,
ref:
'cc'
,
status:
'pending'
@commit3
=
FactoryGirl
.
create
:commit_status
,
commit:
commit
,
name:
'aa'
,
ref:
'cc'
,
status:
'success'
@commit4
=
FactoryGirl
.
create
:commit_status
,
commit:
commit
,
name:
'cc'
,
ref:
'bb'
,
status:
'success'
@commit5
=
FactoryGirl
.
create
:commit_status
,
commit:
commit
,
name:
'aa'
,
ref:
'bb'
,
status:
'success'
end
it
'return unique statuses'
do
is_expected
.
to
eq
([
@commit2
,
@commit3
,
@commit4
,
@commit5
])
end
end
describe
:for_ref
do
subject
{
CommitStatus
.
for_ref
(
'bb'
).
order
(
:id
)
}
before
do
@commit1
=
FactoryGirl
.
create
:commit_status
,
commit:
commit
,
name:
'aa'
,
ref:
'bb'
,
status:
'running'
@commit2
=
FactoryGirl
.
create
:commit_status
,
commit:
commit
,
name:
'cc'
,
ref:
'cc'
,
status:
'pending'
@commit3
=
FactoryGirl
.
create
:commit_status
,
commit:
commit
,
name:
'aa'
,
ref:
nil
,
status:
'success'
end
it
'return statuses with equal and nil ref set'
do
is_expected
.
to
eq
([
@commit1
,
@commit3
])
end
end
describe
:running_or_pending
do
subject
{
CommitStatus
.
running_or_pending
.
order
(
:id
)
}
before
do
@commit1
=
FactoryGirl
.
create
:commit_status
,
commit:
commit
,
name:
'aa'
,
ref:
'bb'
,
status:
'running'
@commit2
=
FactoryGirl
.
create
:commit_status
,
commit:
commit
,
name:
'cc'
,
ref:
'cc'
,
status:
'pending'
@commit3
=
FactoryGirl
.
create
:commit_status
,
commit:
commit
,
name:
'aa'
,
ref:
nil
,
status:
'success'
@commit4
=
FactoryGirl
.
create
:commit_status
,
commit:
commit
,
name:
'dd'
,
ref:
nil
,
status:
'failed'
@commit5
=
FactoryGirl
.
create
:commit_status
,
commit:
commit
,
name:
'ee'
,
ref:
nil
,
status:
'canceled'
end
it
'return statuses that are running or pending'
do
is_expected
.
to
eq
([
@commit1
,
@commit2
])
end
end
end
spec/models/generic_commit_status_spec.rb
0 → 100644
View file @
914cfbd2
require
'spec_helper'
describe
GenericCommitStatus
do
let
(
:commit
)
{
FactoryGirl
.
create
:ci_commit
}
let
(
:generic_commit_status
)
{
FactoryGirl
.
create
:generic_commit_status
,
commit:
commit
}
describe
:context
do
subject
{
generic_commit_status
.
context
}
before
{
generic_commit_status
.
context
=
'my_context'
}
it
{
is_expected
.
to
eq
(
generic_commit_status
.
name
)
}
end
describe
:tags
do
subject
{
generic_commit_status
.
tags
}
it
{
is_expected
.
to
eq
([
:external
])
}
end
describe
:set_default_values
do
before
do
generic_commit_status
.
context
=
nil
generic_commit_status
.
stage
=
nil
generic_commit_status
.
save
end
describe
:context
do
subject
{
generic_commit_status
.
context
}
it
{
is_expected
.
to_not
be_nil
}
end
describe
:stage
do
subject
{
generic_commit_status
.
stage
}
it
{
is_expected
.
to_not
be_nil
}
end
end
end
spec/requests/api/commit_status_spec.rb
0 → 100644
View file @
914cfbd2
require
'spec_helper'
describe
API
::
API
,
api:
true
do
include
ApiHelpers
let
(
:user
)
{
create
(
:user
)
}
let
(
:user2
)
{
create
(
:user
)
}
let!
(
:project
)
{
create
(
:project
,
creator_id:
user
.
id
)
}
let!
(
:reporter
)
{
create
(
:project_member
,
user:
user
,
project:
project
,
access_level:
ProjectMember
::
REPORTER
)
}
let!
(
:guest
)
{
create
(
:project_member
,
user:
user2
,
project:
project
,
access_level:
ProjectMember
::
GUEST
)
}
let
(
:commit
)
{
project
.
repository
.
commit
}
let!
(
:ci_commit
)
{
project
.
ensure_ci_commit
(
commit
.
id
)
}
let
(
:commit_status
)
{
create
(
:commit_status
,
commit:
ci_commit
)
}
describe
"GET /projects/:id/repository/commits/:sha/statuses"
do
context
"reporter user"
do
let
(
:statuses_id
)
{
json_response
.
map
{
|
status
|
status
[
'id'
]
}
}
before
do
@status1
=
create
(
:commit_status
,
commit:
ci_commit
,
status:
'running'
)
@status2
=
create
(
:commit_status
,
commit:
ci_commit
,
name:
'coverage'
,
status:
'pending'
)
@status3
=
create
(
:commit_status
,
commit:
ci_commit
,
name:
'coverage'
,
ref:
'develop'
,
status:
'running'
)
@status4
=
create
(
:commit_status
,
commit:
ci_commit
,
name:
'coverage'
,
status:
'success'
)
@status5
=
create
(
:commit_status
,
commit:
ci_commit
,
ref:
'develop'
,
status:
'success'
)
@status6
=
create
(
:commit_status
,
commit:
ci_commit
,
status:
'success'
)
end
it
"should return latest commit statuses"
do
get
api
(
"/projects/
#{
project
.
id
}
/repository/commits/
#{
commit
.
id
}
/statuses"
,
user
)
expect
(
response
.
status
).
to
eq
(
200
)
expect
(
json_response
).
to
be_an
Array
expect
(
statuses_id
).
to
contain_exactly
(
@status3
.
id
,
@status4
.
id
,
@status5
.
id
,
@status6
.
id
)
end
it
"should return all commit statuses"
do
get
api
(
"/projects/
#{
project
.
id
}
/repository/commits/
#{
commit
.
id
}
/statuses?all=1"
,
user
)
expect
(
response
.
status
).
to
eq
(
200
)
expect
(
json_response
).
to
be_an
Array
expect
(
statuses_id
).
to
contain_exactly
(
@status1
.
id
,
@status2
.
id
,
@status3
.
id
,
@status4
.
id
,
@status5
.
id
,
@status6
.
id
)
end
it
"should return latest commit statuses for specific ref"
do
get
api
(
"/projects/
#{
project
.
id
}
/repository/commits/
#{
commit
.
id
}
/statuses?ref=develop"
,
user
)
expect
(
response
.
status
).
to
eq
(
200
)
expect
(
json_response
).
to
be_an
Array
expect
(
statuses_id
).
to
contain_exactly
(
@status3
.
id
,
@status5
.
id
)
end
it
"should return latest commit statuses for specific name"
do
get
api
(
"/projects/
#{
project
.
id
}
/repository/commits/
#{
commit
.
id
}
/statuses?name=coverage"
,
user
)
expect
(
response
.
status
).
to
eq
(
200
)
expect
(
json_response
).
to
be_an
Array
expect
(
statuses_id
).
to
contain_exactly
(
@status3
.
id
,
@status4
.
id
)
end
end
context
"guest user"
do
it
"should not return project commits"
do
get
api
(
"/projects/
#{
project
.
id
}
/repository/commits/
#{
commit
.
id
}
/statuses"
,
user2
)
expect
(
response
.
status
).
to
eq
(
403
)
end
end
context
"unauthorized user"
do
it
"should not return project commits"
do
get
api
(
"/projects/
#{
project
.
id
}
/repository/commits/
#{
commit
.
id
}
/statuses"
)
expect
(
response
.
status
).
to
eq
(
401
)
end
end
end
describe
'POST /projects/:id/repository/commits/:sha/status'
do
let
(
:post_url
)
{
"/projects/
#{
project
.
id
}
/repository/commits/
#{
commit
.
id
}
/status"
}
context
'reporter user'
do
context
'should create commit status'
do
it
'with only required parameters'
do
post
api
(
post_url
,
user
),
state:
'success'
expect
(
response
.
status
).
to
eq
(
201
)
expect
(
json_response
[
'sha'
]).
to
eq
(
commit
.
id
)
expect
(
json_response
[
'status'
]).
to
eq
(
'success'
)
expect
(
json_response
[
'name'
]).
to
eq
(
'default'
)
expect
(
json_response
[
'ref'
]).
to
be_nil
expect
(
json_response
[
'target_url'
]).
to
be_nil
expect
(
json_response
[
'description'
]).
to
be_nil
end
it
'with all optional parameters'
do
post
api
(
post_url
,
user
),
state:
'success'
,
context:
'coverage'
,
ref:
'develop'
,
target_url:
'url'
,
description:
'test'
expect
(
response
.
status
).
to
eq
(
201
)
expect
(
json_response
[
'sha'
]).
to
eq
(
commit
.
id
)
expect
(
json_response
[
'status'
]).
to
eq
(
'success'
)
expect
(
json_response
[
'name'
]).
to
eq
(
'coverage'
)
expect
(
json_response
[
'ref'
]).
to
eq
(
'develop'
)
expect
(
json_response
[
'target_url'
]).
to
eq
(
'url'
)
expect
(
json_response
[
'description'
]).
to
eq
(
'test'
)
end
end
context
'should not create commit status'
do
it
'with invalid state'
do
post
api
(
post_url
,
user
),
state:
'invalid'
expect
(
response
.
status
).
to
eq
(
400
)
end
it
'without state'
do
post
api
(
post_url
,
user
)
expect
(
response
.
status
).
to
eq
(
400
)
end
it
'invalid commit'
do
post
api
(
"/projects/
#{
project
.
id
}
/repository/commits/invalid_sha/status"
,
user
),
state:
'running'
expect
(
response
.
status
).
to
eq
(
404
)
end
end
end
context
'guest user'
do
it
'should not create commit status'
do
post
api
(
post_url
,
user2
)
expect
(
response
.
status
).
to
eq
(
403
)
end
end
context
'unauthorized user'
do
it
'should not create commit status'
do
post
api
(
post_url
)
expect
(
response
.
status
).
to
eq
(
401
)
end
end
end
end
spec/requests/api/commits_spec.rb
View file @
914cfbd2
...
...
@@ -47,6 +47,19 @@ describe API::API, api: true do
get
api
(
"/projects/
#{
project
.
id
}
/repository/commits/invalid_sha"
,
user
)
expect
(
response
.
status
).
to
eq
(
404
)
end
it
"should return not_found for CI status"
do
get
api
(
"/projects/
#{
project
.
id
}
/repository/commits/
#{
project
.
repository
.
commit
.
id
}
"
,
user
)
expect
(
response
.
status
).
to
eq
(
200
)
expect
(
json_response
[
'status'
]).
to
eq
(
'not_found'
)
end
it
"should return status for CI"
do
ci_commit
=
project
.
ensure_ci_commit
(
project
.
repository
.
commit
.
sha
)
get
api
(
"/projects/
#{
project
.
id
}
/repository/commits/
#{
project
.
repository
.
commit
.
id
}
"
,
user
)
expect
(
response
.
status
).
to
eq
(
200
)
expect
(
json_response
[
'status'
]).
to
eq
(
ci_commit
.
status
)
end
end
context
"unauthorized user"
do
...
...
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