Skip to content
Snippets Groups Projects
Commit 914cfbd2 authored by Kamil Trzcinski's avatar Kamil Trzcinski
Browse files

Implement Commit Status API

parent 5ffbf5fe
No related branches found
No related tags found
No related merge requests found
Showing
with 359 additions and 134 deletions
Loading
@@ -16,6 +16,7 @@ v 8.1.0 (unreleased)
Loading
@@ -16,6 +16,7 @@ v 8.1.0 (unreleased)
- Move CI charts to project graphs area - Move CI charts to project graphs area
- Fix cases where Markdown did not render links in activity feed (Stan Hu) - Fix cases where Markdown did not render links in activity feed (Stan Hu)
- Add first and last to pagination (Zeger-Jan van de Weg) - 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 commit page
- Show CI status on Your projects page and Starred projects page - Show CI status on Your projects page and Starred projects page
- Remove "Continuous Integration" page from dashboard - Remove "Continuous Integration" page from dashboard
Loading
Loading
Loading
@@ -135,6 +135,8 @@ class Ability
Loading
@@ -135,6 +135,8 @@ class Ability
   
def project_report_rules def project_report_rules
project_guest_rules + [ project_guest_rules + [
:create_commit_status,
:read_commit_statuses,
:download_code, :download_code,
:fork_project, :fork_project,
:create_project_snippet, :create_project_snippet,
Loading
Loading
Loading
@@ -24,32 +24,19 @@
Loading
@@ -24,32 +24,19 @@
# #
   
module Ci module Ci
class Build < ActiveRecord::Base class Build < CommitStatus
extend Ci::Model
LAZY_ATTRIBUTES = ['trace'] LAZY_ATTRIBUTES = ['trace']
   
belongs_to :commit, class_name: 'Ci::Commit'
belongs_to :runner, class_name: 'Ci::Runner' belongs_to :runner, class_name: 'Ci::Runner'
belongs_to :trigger_request, class_name: 'Ci::TriggerRequest' belongs_to :trigger_request, class_name: 'Ci::TriggerRequest'
belongs_to :user
   
serialize :options serialize :options
   
validates :commit, presence: true
validates :status, presence: true
validates :coverage, numericality: true, allow_blank: true validates :coverage, numericality: true, allow_blank: true
validates_presence_of :ref 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 :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 :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) } scope :similar, ->(build) { where(ref: build.ref, tag: build.tag, trigger_request_id: build.trigger_request_id) }
   
acts_as_taggable acts_as_taggable
Loading
@@ -74,13 +61,14 @@ module Ci
Loading
@@ -74,13 +61,14 @@ module Ci
   
def create_from(build) def create_from(build)
new_build = build.dup new_build = build.dup
new_build.status = :pending new_build.status = 'pending'
new_build.runner_id = nil new_build.runner_id = nil
new_build.trigger_request_id = nil
new_build.save new_build.save
end end
   
def retry(build) def retry(build)
new_build = Ci::Build.new(status: :pending) new_build = Ci::Build.new(status: 'pending')
new_build.ref = build.ref new_build.ref = build.ref
new_build.tag = build.tag new_build.tag = build.tag
new_build.options = build.options new_build.options = build.options
Loading
@@ -98,28 +86,7 @@ module Ci
Loading
@@ -98,28 +86,7 @@ module Ci
end end
   
state_machine :status, initial: :pending do 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| after_transition any => [:success, :failed, :canceled] do |build, transition|
build.update_attributes finished_at: Time.now
project = build.project project = build.project
   
if project.web_hooks? if project.web_hooks?
Loading
@@ -136,19 +103,10 @@ module Ci
Loading
@@ -136,19 +103,10 @@ module Ci
build.update_coverage build.update_coverage
end end
end end
state :pending, value: 'pending'
state :running, value: 'running'
state :failed, value: 'failed'
state :success, value: 'success'
state :canceled, value: 'canceled'
end end
   
delegate :sha, :short_sha, :project, :gl_project, def ignored?
to: :commit, prefix: false failed? && allow_failure?
def before_sha
Gitlab::Git::BLANK_SHA
end end
   
def trace_html def trace_html
Loading
@@ -156,22 +114,6 @@ module Ci
Loading
@@ -156,22 +114,6 @@ module Ci
html || '' html || ''
end 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 def timeout
project.timeout project.timeout
end end
Loading
@@ -180,14 +122,6 @@ module Ci
Loading
@@ -180,14 +122,6 @@ module Ci
yaml_variables + project_variables + trigger_variables yaml_variables + project_variables + trigger_variables
end end
   
def duration
if started_at && finished_at
finished_at - started_at
elsif started_at
Time.now - started_at
end
end
def project def project
commit.project commit.project
end end
Loading
@@ -278,6 +212,15 @@ module Ci
Loading
@@ -278,6 +212,15 @@ module Ci
"#{dir_to_trace}/#{id}.log" "#{dir_to_trace}/#{id}.log"
end 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 private
   
def yaml_variables def yaml_variables
Loading
Loading
Loading
@@ -20,7 +20,8 @@ module Ci
Loading
@@ -20,7 +20,8 @@ module Ci
extend Ci::Model extend Ci::Model
   
belongs_to :gl_project, class_name: '::Project', foreign_key: :gl_project_id 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' has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest'
   
validates_presence_of :sha validates_presence_of :sha
Loading
@@ -81,12 +82,11 @@ module Ci
Loading
@@ -81,12 +82,11 @@ module Ci
end end
   
def stage def stage
running_or_pending = builds_without_retry.running_or_pending running_or_pending = statuses.latest.running_or_pending
running_or_pending.limit(1).pluck(:stage).first running_or_pending.first.try(:stage)
end end
   
def create_builds(ref, tag, user, trigger_request = nil) def create_builds(ref, tag, user, trigger_request = nil)
return if skip_ci? && trigger_request.blank?
return unless config_processor return unless config_processor
config_processor.stages.any? do |stage| config_processor.stages.any? do |stage|
CreateBuildsService.new.execute(self, stage, ref, tag, user, trigger_request).present? CreateBuildsService.new.execute(self, stage, ref, tag, user, trigger_request).present?
Loading
@@ -94,7 +94,6 @@ module Ci
Loading
@@ -94,7 +94,6 @@ module Ci
end end
   
def create_next_builds(ref, tag, user, trigger_request) def create_next_builds(ref, tag, user, trigger_request)
return if skip_ci? && trigger_request.blank?
return unless config_processor return unless config_processor
   
stages = builds.where(ref: ref, tag: tag, trigger_request: trigger_request).group_by(&:stage) stages = builds.where(ref: ref, tag: tag, trigger_request: trigger_request).group_by(&:stage)
Loading
@@ -107,39 +106,47 @@ module Ci
Loading
@@ -107,39 +106,47 @@ module Ci
end end
   
def refs def refs
builds.group(:ref).pluck(:ref) statuses.pluck(:ref).compact.uniq
end end
   
def last_ref def statuses_for_ref(ref = nil)
builds.latest.first.try(:ref) if ref
end statuses.for_ref(ref)
else
def builds_without_retry statuses
builds.latest end
end end
   
def builds_without_retry_for_ref(ref) def builds_without_retry(ref = nil)
builds.for_ref(ref).latest if ref
builds.for_ref(ref).latest
else
builds.latest
end
end end
   
def retried_builds def retried
@retried_builds ||= (builds.order(id: :desc) - builds_without_retry) @retried ||= (statuses.order(id: :desc) - statuses.latest)
end end
   
def status def status(ref = nil)
if skip_ci? if yaml_errors.present?
return 'skipped'
elsif yaml_errors.present?
return 'failed' 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' return 'skipped'
elsif success? elsif latest_statuses.all?(&:success?)
'success' 'success'
elsif pending? elsif latest_statuses.all?(&:pending?)
'pending' 'pending'
elsif running? elsif latest_statuses.any?(&:running?) || latest_statuses.any?(&:pending?)
'running' 'running'
elsif canceled? elsif latest_statuses.all?(&:canceled?)
'canceled' 'canceled'
else else
'failed' 'failed'
Loading
@@ -147,21 +154,15 @@ module Ci
Loading
@@ -147,21 +154,15 @@ module Ci
end end
   
def pending? def pending?
builds_without_retry.all? do |build| status == 'pending'
build.pending?
end
end end
   
def running? def running?
builds_without_retry.any? do |build| status == 'running'
build.running? || build.pending?
end
end end
   
def success? def success?
builds_without_retry.all? do |build| status == 'success'
build.success? || build.ignored?
end
end end
   
def failed? def failed?
Loading
@@ -169,21 +170,15 @@ module Ci
Loading
@@ -169,21 +170,15 @@ module Ci
end end
   
def canceled? def canceled?
builds_without_retry.all? do |build| status == 'canceled'
build.canceled?
end
end
def duration
@duration ||= builds_without_retry.select(&:duration).sum(&:duration).to_i
end end
   
def duration_for_ref(ref) def duration(ref = nil)
builds_without_retry_for_ref(ref).select(&:duration).sum(&:duration).to_i statuses_for_ref(ref).latest.select(&:duration).sum(&:duration).to_i
end end
   
def finished_at def finished_at
@finished_at ||= builds.order('finished_at DESC').first.try(:finished_at) @finished_at ||= statuses.order('finished_at DESC').first.try(:finished_at)
end end
   
def coverage def coverage
Loading
@@ -195,8 +190,8 @@ module Ci
Loading
@@ -195,8 +190,8 @@ module Ci
end end
end end
   
def matrix_for_ref?(ref) def matrix?(ref)
builds_without_retry_for_ref(ref).pluck(:id).size > 1 builds_without_retry(ref).pluck(:id).size > 1
end end
   
def config_processor def config_processor
Loading
@@ -217,7 +212,6 @@ module Ci
Loading
@@ -217,7 +212,6 @@ module Ci
end end
   
def skip_ci? def skip_ci?
return false if builds.any?
git_commit_message =~ /(\[ci skip\])/ if git_commit_message git_commit_message =~ /(\[ci skip\])/ if git_commit_message
end end
   
Loading
Loading
Loading
@@ -184,4 +184,12 @@ class Commit
Loading
@@ -184,4 +184,12 @@ class Commit
def parents def parents
@parents ||= Commit.decorate(super, project) @parents ||= Commit.decorate(super, project)
end end
def ci_commit
project.ci_commit(sha)
end
def status
ci_commit.try(:status) || :not_found
end
end end
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
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
Loading
@@ -17,6 +17,8 @@ module Ci
Loading
@@ -17,6 +17,8 @@ module Ci
   
tag = origin_ref.start_with?('refs/tags/') tag = origin_ref.start_with?('refs/tags/')
commit = project.gl_project.ensure_ci_commit(sha) commit = project.gl_project.ensure_ci_commit(sha)
return false if commit.skip_ci?
commit.update_committed! commit.update_committed!
commit.create_builds(ref, tag, user) commit.create_builds(ref, tag, user)
   
Loading
Loading
Loading
@@ -7,9 +7,9 @@
Loading
@@ -7,9 +7,9 @@
%code #{@build.ref} %code #{@build.ref}
   
#up-build-trace #up-build-trace
- if @commit.matrix_for_ref?(@build.ref) - if @commit.matrix?(@build.ref)
%ul.center-top-menu.build-top-menu %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) } %li{class: ('active' if build == @build) }
= link_to namespace_project_build_path(@project.namespace, @project, build) do = link_to namespace_project_build_path(@project.namespace, @project, build) do
= ci_icon_for_status(build.status) = ci_icon_for_status(build.status)
Loading
@@ -20,7 +20,7 @@
Loading
@@ -20,7 +20,7 @@
= build.id = build.id
   
   
- unless @commit.builds_without_retry_for_ref(@build.ref).include?(@build) - unless @commit.builds_without_retry(@build.ref).include?(@build)
%li.active %li.active
%a %a
Build ##{@build.id} Build ##{@build.id}
Loading
Loading
Loading
@@ -20,13 +20,35 @@
Loading
@@ -20,13 +20,35 @@
.bs-callout.bs-callout-warning .bs-callout.bs-callout-warning
\.gitlab-ci.yml not found in this commit \.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 .gray-content-block.second-block
Builds for #{ref} Builds for #{ref}
- if @ci_commit.duration_for_ref(ref) > 0 - if @ci_commit.duration(ref) > 0
%small.pull-right %small.pull-right
%i.fa.fa-time %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 %table.table.builds
%thead %thead
Loading
@@ -40,10 +62,10 @@
Loading
@@ -40,10 +62,10 @@
- if @ci_project && @ci_project.coverage_enabled? - if @ci_project && @ci_project.coverage_enabled?
%th Coverage %th Coverage
%th %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? - if @ci_commit.retried.any?
%h3 .gray-content-block.second-block
Retried builds Retried builds
   
%table.table.builds %table.table.builds
Loading
@@ -59,4 +81,4 @@
Loading
@@ -59,4 +81,4 @@
- if @ci_project && @ci_project.coverage_enabled? - if @ci_project && @ci_project.coverage_enabled?
%th Coverage %th Coverage
%th %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
- gl_project = build.project.gl_project %tr.commit_status
%tr.build
%td.status %td.status
= ci_status_with_icon(build.status) = ci_status_with_icon(commit_status.status)
   
%td.build-link %td.commit_status-link
= link_to namespace_project_build_path(gl_project.namespace, gl_project, build) do - if commit_status.target_url
%strong Build ##{build.id} = link_to commit_status.target_url do
%strong Build ##{commit_status.id}
- else
%strong Build ##{commit_status.id}
   
- if defined?(ref) - if defined?(ref)
%td %td
= build.ref = commit_status.ref
   
%td %td
= build.stage = commit_status.stage
   
%td %td
= build.name = commit_status.description
.pull-right .pull-right
- if build.tags.any? - if commit_status.tags.any?
- build.tag_list.each do |tag| - commit_status.tags.each do |tag|
%span.label.label-primary %span.label.label-primary
= tag = tag
- if build.trigger_request - if commit_status.try(:trigger_request)
%span.label.label-info triggered %span.label.label-info triggered
- if build.allow_failure - if commit_status.try(:allow_failure)
%span.label.label-danger allowed to fail %span.label.label-danger allowed to fail
   
%td.duration %td.duration
- if build.duration - if commit_status.duration
#{duration_in_words(build.finished_at, build.started_at)} #{duration_in_words(commit_status.finished_at, commit_status.started_at)}
   
%td.timestamp %td.timestamp
- if build.finished_at - if commit_status.finished_at
%span #{time_ago_in_words build.finished_at} ago %span #{time_ago_in_words commit_status.finished_at} ago
   
- if build.project.coverage_enabled? - if defined?(coverage)
%td.coverage %td.coverage
- if build.coverage - if commit_status.try(:coverage)
#{build.coverage}% #{commit_status.coverage}%
   
%td %td
- if defined?(controls) && current_user && can?(current_user, :manage_builds, gl_project) - if defined?(controls) && current_user && can?(current_user, :manage_builds, gl_project)
.pull-right .pull-right
- if build.active? - if commit_status.active?
= link_to cancel_namespace_project_build_path(gl_project.namespace, gl_project, build, return_to: request.original_url), title: 'Cancel build' do = 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 %i.fa.fa-remove.cred
- elsif build.commands.present? - elsif commit_status.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 = 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 %i.fa.fa-repeat
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
class MigrateNameToDescriptionForBuilds < ActiveRecord::Migration
def change
execute("UPDATE ci_builds SET type='Ci::Build' WHERE type IS NULL")
end
end
Loading
@@ -11,7 +11,7 @@
Loading
@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
   
ActiveRecord::Schema.define(version: 20151007120511) do ActiveRecord::Schema.define(version: 20151008130321) do
   
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
Loading
@@ -103,9 +103,14 @@ ActiveRecord::Schema.define(version: 20151007120511) do
Loading
@@ -103,9 +103,14 @@ ActiveRecord::Schema.define(version: 20151007120511) do
t.boolean "tag" t.boolean "tag"
t.string "ref" t.string "ref"
t.integer "user_id" t.integer "user_id"
t.string "type"
t.string "target_url"
t.string "description"
end 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", "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", ["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", "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 add_index "ci_builds", ["project_id"], name: "index_ci_builds_on_project_id", using: :btree
Loading
Loading
Loading
@@ -62,7 +62,8 @@ Parameters:
Loading
@@ -62,7 +62,8 @@ Parameters:
"authored_date": "2012-09-20T09:06:12+03:00", "authored_date": "2012-09-20T09:06:12+03:00",
"parent_ids": [ "parent_ids": [
"ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba" "ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba"
] ],
"status": "running"
} }
``` ```
   
Loading
Loading
Loading
@@ -46,6 +46,7 @@ module API
Loading
@@ -46,6 +46,7 @@ module API
mount Services mount Services
mount Files mount Files
mount Commits mount Commits
mount CommitStatus
mount Namespaces mount Namespaces
mount Branches mount Branches
mount Labels mount Labels
Loading
Loading
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
Loading
@@ -65,7 +65,7 @@ module API
Loading
@@ -65,7 +65,7 @@ module API
expose :issues_enabled, :merge_requests_enabled, :wiki_enabled, :snippets_enabled, :created_at, :last_activity_at expose :issues_enabled, :merge_requests_enabled, :wiki_enabled, :snippets_enabled, :created_at, :last_activity_at
expose :creator_id expose :creator_id
expose :namespace 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 :avatar_url
expose :star_count, :forks_count expose :star_count, :forks_count
end end
Loading
@@ -149,6 +149,7 @@ module API
Loading
@@ -149,6 +149,7 @@ module API
   
class RepoCommitDetail < RepoCommit class RepoCommitDetail < RepoCommit
expose :parent_ids, :committed_date, :authored_date expose :parent_ids, :committed_date, :authored_date
expose :status
end end
   
class ProjectSnippet < Grape::Entity class ProjectSnippet < Grape::Entity
Loading
@@ -228,6 +229,11 @@ module API
Loading
@@ -228,6 +229,11 @@ module API
expose :created_at expose :created_at
end 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 class Event < Grape::Entity
expose :title, :project_id, :action_name expose :title, :project_id, :action_name
expose :target_id, :target_type, :author_id expose :target_id, :target_type, :author_id
Loading
Loading
Loading
@@ -2,7 +2,7 @@ module Ci
Loading
@@ -2,7 +2,7 @@ module Ci
module API module API
module Entities module Entities
class Commit < Grape::Entity 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 :status, :finished_at, :duration
expose :git_commit_message, :git_author_name, :git_author_email expose :git_commit_message, :git_author_name, :git_author_email
end end
Loading
@@ -12,7 +12,7 @@ module Ci
Loading
@@ -12,7 +12,7 @@ module Ci
end end
   
class Build < Grape::Entity 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 :before_sha, :allow_git_fetch, :project_name
   
expose :options do |model| expose :options do |model|
Loading
Loading
Loading
@@ -27,6 +27,7 @@
Loading
@@ -27,6 +27,7 @@
   
FactoryGirl.define do FactoryGirl.define do
factory :ci_build, class: Ci::Build do factory :ci_build, class: Ci::Build do
name 'test'
ref 'master' ref 'master'
tag false tag false
started_at 'Di 29. Okt 09:51:28 CET 2013' started_at 'Di 29. Okt 09:51:28 CET 2013'
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment