mirror of
https://github.com/wahyd4/gitlabhq.git
synced 2026-08-16 16:16:43 +10:00
Use Ci::Commit as Pipeline
This commit is contained in:
@@ -94,8 +94,8 @@ class Projects::CommitController < Projects::ApplicationController
|
||||
@commit ||= @project.commit(params[:id])
|
||||
end
|
||||
|
||||
def ci_commit
|
||||
@ci_commit ||= project.ci_commit(commit.sha)
|
||||
def ci_commits
|
||||
@ci_commits ||= project.ci_commits.where(sha: commit.sha)
|
||||
end
|
||||
|
||||
def define_show_vars
|
||||
@@ -108,7 +108,8 @@ class Projects::CommitController < Projects::ApplicationController
|
||||
@diff_refs = [commit.parent || commit, commit]
|
||||
@notes_count = commit.notes.count
|
||||
|
||||
@statuses = ci_commit.statuses if ci_commit
|
||||
@statuses = CommitStatus.where(commit: ci_commits)
|
||||
@builds = Ci::Build.where(commit: ci_commits)
|
||||
end
|
||||
|
||||
def assign_revert_commit_vars
|
||||
|
||||
@@ -118,6 +118,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
||||
@diffs = @merge_request.compare.diffs(diff_options) if @merge_request.compare
|
||||
|
||||
@ci_commit = @merge_request.ci_commit
|
||||
@ci_commits = [@ci_commit].compact
|
||||
@statuses = @ci_commit.statuses if @ci_commit
|
||||
|
||||
@note_counts = Note.where(commit_id: @commits.map(&:id)).
|
||||
@@ -308,6 +309,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
||||
@merge_request_diff = @merge_request.merge_request_diff
|
||||
|
||||
@ci_commit = @merge_request.ci_commit
|
||||
@ci_commits = [@ci_commit].compact
|
||||
@statuses = @ci_commit.statuses if @ci_commit
|
||||
|
||||
if @merge_request.locked_long_ago?
|
||||
@@ -318,6 +320,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
||||
|
||||
def define_widget_vars
|
||||
@ci_commit = @merge_request.ci_commit
|
||||
@ci_commits = [@ci_commit].compact
|
||||
closes_issues
|
||||
end
|
||||
|
||||
|
||||
@@ -1,17 +1,4 @@
|
||||
module CiStatusHelper
|
||||
def ci_status_path(ci_commit)
|
||||
project = ci_commit.project
|
||||
builds_namespace_project_commit_path(project.namespace, project, ci_commit.sha)
|
||||
end
|
||||
|
||||
def ci_status_icon(ci_commit)
|
||||
ci_icon_for_status(ci_commit.status)
|
||||
end
|
||||
|
||||
def ci_status_label(ci_commit)
|
||||
ci_label_for_status(ci_commit.status)
|
||||
end
|
||||
|
||||
def ci_status_with_icon(status, target = nil)
|
||||
content = ci_icon_for_status(status) + ' '.html_safe + ci_label_for_status(status)
|
||||
klass = "ci-status ci-#{status}"
|
||||
@@ -47,10 +34,10 @@ module CiStatusHelper
|
||||
end
|
||||
|
||||
def render_ci_status(ci_commit, tooltip_placement: 'auto left')
|
||||
link_to ci_status_icon(ci_commit),
|
||||
ci_status_path(ci_commit),
|
||||
link_to ci_icon_for_status(ci_commit.status),
|
||||
project_ci_commit_path(ci_commit.project, ci_commit),
|
||||
class: "ci-status-link ci-status-icon-#{ci_commit.status.dasherize}",
|
||||
title: "Build #{ci_status_label(ci_commit)}",
|
||||
title: "Build #{ci_label_for_status(ci_commit.status)}",
|
||||
data: { toggle: 'tooltip', placement: tooltip_placement }
|
||||
end
|
||||
|
||||
|
||||
@@ -25,10 +25,22 @@ module GitlabRoutingHelper
|
||||
namespace_project_commits_path(project.namespace, project, @ref || project.repository.root_ref)
|
||||
end
|
||||
|
||||
def project_pipelines_path(project, *args)
|
||||
namespace_project_pipelines_path(project.namespace, project, *args)
|
||||
end
|
||||
|
||||
def project_builds_path(project, *args)
|
||||
namespace_project_builds_path(project.namespace, project, *args)
|
||||
end
|
||||
|
||||
def project_commit_path(project, commit)
|
||||
builds_namespace_project_commit_path(project.namespace, project, commit.id)
|
||||
end
|
||||
|
||||
def project_ci_commit_path(project, ci_commit)
|
||||
builds_namespace_project_commit_path(project.namespace, project, ci_commit.sha)
|
||||
end
|
||||
|
||||
def activity_project_path(project, *args)
|
||||
activity_namespace_project_path(project.namespace, project, *args)
|
||||
end
|
||||
|
||||
@@ -50,7 +50,6 @@ module Ci
|
||||
|
||||
scope :unstarted, ->() { where(runner_id: nil) }
|
||||
scope :ignore_failures, ->() { where(allow_failure: false) }
|
||||
scope :similar, ->(build) { where(ref: build.ref, tag: build.tag, trigger_request_id: build.trigger_request_id) }
|
||||
|
||||
mount_uploader :artifacts_file, ArtifactUploader
|
||||
mount_uploader :artifacts_metadata, ArtifactUploader
|
||||
@@ -62,6 +61,8 @@ module Ci
|
||||
|
||||
before_destroy { project }
|
||||
|
||||
after_create :execute_hooks
|
||||
|
||||
class << self
|
||||
def columns_without_lazy
|
||||
(column_names - LAZY_ATTRIBUTES).map do |column_name|
|
||||
@@ -126,12 +127,16 @@ module Ci
|
||||
end
|
||||
|
||||
def retried?
|
||||
!self.commit.latest_statuses_for_ref(self.ref).include?(self)
|
||||
!self.commit.latest.include?(self)
|
||||
end
|
||||
|
||||
def retry
|
||||
Ci::Build.retry(self)
|
||||
end
|
||||
|
||||
def depends_on_builds
|
||||
# Get builds of the same type
|
||||
latest_builds = self.commit.builds.similar(self).latest
|
||||
latest_builds = self.commit.builds.latest
|
||||
|
||||
# Return builds from previous stages
|
||||
latest_builds.where('stage_idx < ?', stage_idx)
|
||||
|
||||
+61
-63
@@ -19,6 +19,7 @@
|
||||
module Ci
|
||||
class Commit < ActiveRecord::Base
|
||||
extend Ci::Model
|
||||
include CiStatus
|
||||
|
||||
belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id
|
||||
has_many :statuses, class_name: 'CommitStatus'
|
||||
@@ -28,12 +29,18 @@ module Ci
|
||||
validates_presence_of :sha
|
||||
validate :valid_commit_sha
|
||||
|
||||
# Make sure that status is saved
|
||||
before_save :status
|
||||
before_save :started_at
|
||||
before_save :finished_at
|
||||
before_save :duration
|
||||
|
||||
def self.truncate_sha(sha)
|
||||
sha[0...8]
|
||||
end
|
||||
|
||||
def to_param
|
||||
sha
|
||||
def stages
|
||||
statuses.group(:stage).order(:stage_idx).pluck(:stage)
|
||||
end
|
||||
|
||||
def project_id
|
||||
@@ -68,15 +75,26 @@ module Ci
|
||||
nil
|
||||
end
|
||||
|
||||
def stage
|
||||
running_or_pending = statuses.latest.running_or_pending.ordered
|
||||
running_or_pending.first.try(:stage)
|
||||
def branch?
|
||||
!tag?
|
||||
end
|
||||
|
||||
def create_builds(ref, tag, user, trigger_request = nil)
|
||||
def retryable?
|
||||
builds.latest.any? do |build|
|
||||
build.failed? || build.retryable?
|
||||
end
|
||||
end
|
||||
|
||||
def invalidate
|
||||
status = nil
|
||||
started_at = nil
|
||||
finished_at = nil
|
||||
end
|
||||
|
||||
def create_builds(user, trigger_request = nil)
|
||||
return unless config_processor
|
||||
config_processor.stages.any? do |stage|
|
||||
CreateBuildsService.new.execute(self, stage, ref, tag, user, trigger_request, 'success').present?
|
||||
CreateBuildsService.new(self).execute(stage, user, 'success', trigger_request).present?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -84,7 +102,7 @@ module Ci
|
||||
return unless config_processor
|
||||
|
||||
# don't create other builds if this one is retried
|
||||
latest_builds = builds.similar(build).latest
|
||||
latest_builds = builds.latest
|
||||
return unless latest_builds.exists?(build.id)
|
||||
|
||||
# get list of stages after this build
|
||||
@@ -97,26 +115,12 @@ module Ci
|
||||
|
||||
# create builds for next stages based
|
||||
next_stages.any? do |stage|
|
||||
CreateBuildsService.new.execute(self, stage, build.ref, build.tag, build.user, build.trigger_request, status).present?
|
||||
CreateBuildsService.new(self).execute(stage, build.user, status, build.trigger_request).present?
|
||||
end
|
||||
end
|
||||
|
||||
def refs
|
||||
statuses.order(:ref).pluck(:ref).uniq
|
||||
end
|
||||
|
||||
def latest_statuses
|
||||
@latest_statuses ||= statuses.latest.to_a
|
||||
end
|
||||
|
||||
def latest_statuses_for_ref(ref)
|
||||
latest_statuses.select { |status| status.ref == ref }
|
||||
end
|
||||
|
||||
def matrix_builds(build = nil)
|
||||
matrix_builds = builds.latest.ordered
|
||||
matrix_builds = matrix_builds.similar(build) if build
|
||||
matrix_builds.to_a
|
||||
def latest
|
||||
statuses.latest
|
||||
end
|
||||
|
||||
def retried
|
||||
@@ -124,56 +128,23 @@ module Ci
|
||||
end
|
||||
|
||||
def status
|
||||
if yaml_errors.present?
|
||||
return 'failed'
|
||||
end
|
||||
|
||||
@status ||= Ci::Status.get_status(latest_statuses)
|
||||
end
|
||||
|
||||
def pending?
|
||||
status == 'pending'
|
||||
end
|
||||
|
||||
def running?
|
||||
status == 'running'
|
||||
end
|
||||
|
||||
def success?
|
||||
status == 'success'
|
||||
end
|
||||
|
||||
def failed?
|
||||
status == 'failed'
|
||||
end
|
||||
|
||||
def canceled?
|
||||
status == 'canceled'
|
||||
end
|
||||
|
||||
def active?
|
||||
running? || pending?
|
||||
end
|
||||
|
||||
def complete?
|
||||
canceled? || success? || failed?
|
||||
read_attribute(:status) || update_status
|
||||
end
|
||||
|
||||
def duration
|
||||
duration_array = statuses.map(&:duration).compact
|
||||
duration_array.reduce(:+).to_i
|
||||
read_attribute(:duration) || update_duration
|
||||
end
|
||||
|
||||
def started_at
|
||||
@started_at ||= statuses.order('started_at ASC').first.try(:started_at)
|
||||
read_attribute(:started_at) || update_started_at
|
||||
end
|
||||
|
||||
def finished_at
|
||||
@finished_at ||= statuses.order('finished_at DESC').first.try(:finished_at)
|
||||
read_attribute(:finished_at) || update_finished_at
|
||||
end
|
||||
|
||||
def coverage
|
||||
coverage_array = latest_statuses.map(&:coverage).compact
|
||||
coverage_array = latest.map(&:coverage).compact
|
||||
if coverage_array.size >= 1
|
||||
'%.2f' % (coverage_array.reduce(:+) / coverage_array.size)
|
||||
end
|
||||
@@ -191,6 +162,7 @@ module Ci
|
||||
end
|
||||
|
||||
def ci_yaml_file
|
||||
return nil if defined?(@ci_yaml_file)
|
||||
@ci_yaml_file ||= begin
|
||||
blob = project.repository.blob_at(sha, '.gitlab-ci.yml')
|
||||
blob.load_all_data!(project.repository)
|
||||
@@ -206,6 +178,32 @@ module Ci
|
||||
|
||||
private
|
||||
|
||||
def update_status
|
||||
status =
|
||||
if yaml_errors.present?
|
||||
'failed'
|
||||
else
|
||||
latest.status
|
||||
end
|
||||
end
|
||||
|
||||
def update_started_at
|
||||
started_at =
|
||||
statuses.order(:id).first.try(:started_at)
|
||||
end
|
||||
|
||||
def update_finished_at
|
||||
finished_at =
|
||||
statuses.order(id: :desc).first.try(:finished_at)
|
||||
end
|
||||
|
||||
def update_duration
|
||||
duration = begin
|
||||
duration_array = latest.map(&:duration).compact
|
||||
duration_array.reduce(:+).to_i
|
||||
end
|
||||
end
|
||||
|
||||
def save_yaml_error(error)
|
||||
return if self.yaml_errors?
|
||||
self.yaml_errors = error
|
||||
|
||||
@@ -209,12 +209,13 @@ class Commit
|
||||
@raw.short_id(7)
|
||||
end
|
||||
|
||||
def ci_commit
|
||||
project.ci_commit(sha)
|
||||
def ci_commits
|
||||
@ci_commits ||= project.ci_commits.where(sha: sha)
|
||||
end
|
||||
|
||||
def status
|
||||
ci_commit.try(:status) || :not_found
|
||||
return @status if defined?(@status)
|
||||
@status ||= ci_commits.status
|
||||
end
|
||||
|
||||
def revert_branch_name
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
#
|
||||
|
||||
class CommitStatus < ActiveRecord::Base
|
||||
include CiStatus
|
||||
|
||||
self.table_name = 'ci_builds'
|
||||
|
||||
belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id
|
||||
@@ -40,21 +42,13 @@ class CommitStatus < ActiveRecord::Base
|
||||
belongs_to :user
|
||||
|
||||
validates :commit, presence: true
|
||||
validates :status, inclusion: { in: %w(pending running failed success canceled) }
|
||||
|
||||
validates_presence_of :name
|
||||
|
||||
alias_attribute :author, :user
|
||||
|
||||
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 :finished, -> { where(status: [:success, :failed, :canceled]) }
|
||||
scope :latest, -> { where(id: unscope(:select).select('max(id)').group(:name, :ref)) }
|
||||
scope :latest, -> { where(id: unscope(:select).select('max(id)').group(:name)) }
|
||||
scope :ordered, -> { order(:ref, :stage_idx, :name) }
|
||||
scope :for_ref, ->(ref) { where(ref: ref) }
|
||||
|
||||
AVAILABLE_STATUSES = ['pending', 'running', 'success', 'failed', 'canceled']
|
||||
|
||||
@@ -87,31 +81,13 @@ class CommitStatus < ActiveRecord::Base
|
||||
MergeRequests::MergeWhenBuildSucceedsService.new(commit_status.commit.project, nil).trigger(commit_status)
|
||||
end
|
||||
|
||||
state :pending, value: 'pending'
|
||||
state :running, value: 'running'
|
||||
state :failed, value: 'failed'
|
||||
state :success, value: 'success'
|
||||
state :canceled, value: 'canceled'
|
||||
after_transition any => any do |commit_status|
|
||||
commit_status.commit.invalidate
|
||||
commit_status.save
|
||||
end
|
||||
end
|
||||
|
||||
delegate :sha, :short_sha, to: :commit, prefix: false
|
||||
|
||||
# TODO: this should be removed with all references
|
||||
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
|
||||
delegate :before_sha, :sha, :short_sha, to: :commit, prefix: false
|
||||
|
||||
def ignored?
|
||||
allow_failure? && (failed? || canceled?)
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
module CiStatus
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
module ClassMethods
|
||||
def status
|
||||
objs = all.to_a
|
||||
if objs.none?
|
||||
nil
|
||||
elsif objs.all? { |status| status.success? || status.try(:ignored?) }
|
||||
'success'
|
||||
elsif objs.all?(&:pending?)
|
||||
'pending'
|
||||
elsif objs.any?(&:running?) || all.any?(&:pending?)
|
||||
'running'
|
||||
elsif objs.all?(&:canceled?)
|
||||
'canceled'
|
||||
else
|
||||
'failed'
|
||||
end
|
||||
end
|
||||
|
||||
def duration
|
||||
duration_array = all.map(&:duration).compact
|
||||
duration_array.reduce(:+).to_i
|
||||
end
|
||||
end
|
||||
|
||||
included do
|
||||
validates :status, inclusion: { in: %w(pending running failed success canceled) }
|
||||
|
||||
state_machine :status, initial: :pending do
|
||||
state :pending, value: 'pending'
|
||||
state :running, value: 'running'
|
||||
state :failed, value: 'failed'
|
||||
state :success, value: 'success'
|
||||
state :canceled, value: 'canceled'
|
||||
end
|
||||
|
||||
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 :finished, -> { where(status: [:success, :failed, :canceled]) }
|
||||
end
|
||||
|
||||
def started?
|
||||
!pending? && !canceled? && started_at
|
||||
end
|
||||
|
||||
def active?
|
||||
running? || pending?
|
||||
end
|
||||
|
||||
def complete?
|
||||
canceled? || success? || failed?
|
||||
end
|
||||
end
|
||||
@@ -589,7 +589,7 @@ class MergeRequest < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def ci_commit
|
||||
@ci_commit ||= source_project.ci_commit(last_commit.id) if last_commit && source_project
|
||||
@ci_commit ||= source_project.ci_commit(last_commit.id, source_branch) if last_commit && source_project
|
||||
end
|
||||
|
||||
def diff_refs
|
||||
|
||||
@@ -919,12 +919,12 @@ class Project < ActiveRecord::Base
|
||||
!namespace.share_with_group_lock
|
||||
end
|
||||
|
||||
def ci_commit(sha)
|
||||
ci_commits.find_by(sha: sha)
|
||||
def ci_commit(sha, ref)
|
||||
ci_commits.find_by(sha: sha, ref: ref)
|
||||
end
|
||||
|
||||
def ensure_ci_commit(sha)
|
||||
ci_commit(sha) || ci_commits.create(sha: sha)
|
||||
def ensure_ci_commit(sha, ref)
|
||||
ci_commit(sha, ref) || ci_commits.create(sha: sha, ref: ref)
|
||||
end
|
||||
|
||||
def enable_ci
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
module Ci
|
||||
class CreateBuildsService
|
||||
def execute(commit, stage, ref, tag, user, trigger_request, status)
|
||||
builds_attrs = commit.config_processor.builds_for_stage_and_ref(stage, ref, tag, trigger_request)
|
||||
def initialize(commit)
|
||||
@commit = commit
|
||||
end
|
||||
|
||||
def execute(stage, user, status, trigger_request = nil)
|
||||
builds_attrs = config_processor.builds_for_stage_and_ref(stage, @commit.ref, @commit.tag, trigger_request)
|
||||
|
||||
# check when to create next build
|
||||
builds_attrs = builds_attrs.select do |build_attrs|
|
||||
@@ -17,7 +21,8 @@ module Ci
|
||||
|
||||
builds_attrs.map do |build_attrs|
|
||||
# don't create the same build twice
|
||||
unless commit.builds.find_by(ref: ref, tag: tag, trigger_request: trigger_request, name: build_attrs[:name])
|
||||
unless commit.builds.find_by(ref: @commit.ref, tag: @commit.tag,
|
||||
trigger_request: trigger_request, name: build_attrs[:name])
|
||||
build_attrs.slice!(:name,
|
||||
:commands,
|
||||
:tag_list,
|
||||
@@ -26,17 +31,21 @@ module Ci
|
||||
:stage,
|
||||
:stage_idx)
|
||||
|
||||
build_attrs.merge!(ref: ref,
|
||||
tag: tag,
|
||||
build_attrs.merge!(ref: @commit.ref,
|
||||
tag: @commit.tag,
|
||||
trigger_request: trigger_request,
|
||||
user: user,
|
||||
project: commit.project)
|
||||
project: @commit.project)
|
||||
|
||||
build = commit.builds.create!(build_attrs)
|
||||
build.execute_hooks
|
||||
build
|
||||
@commit.builds.create!(build_attrs)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def config_processor
|
||||
@config_processor ||= @commit.config_processor
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,7 +7,7 @@ module Ci
|
||||
# check if ref is tag
|
||||
tag = project.repository.find_tag(ref).present?
|
||||
|
||||
ci_commit = project.ensure_ci_commit(commit.sha)
|
||||
ci_commit = project.ci_commits.create(commit.sha, ref)
|
||||
|
||||
trigger_request = trigger.trigger_requests.create!(
|
||||
variables: variables,
|
||||
|
||||
@@ -2,6 +2,7 @@ class CreateCommitBuildsService
|
||||
def execute(project, user, params)
|
||||
return false unless project.builds_enabled?
|
||||
|
||||
before_sha = params[:checkout_sha] || params[:before]
|
||||
sha = params[:checkout_sha] || params[:after]
|
||||
origin_ref = params[:ref]
|
||||
|
||||
@@ -10,15 +11,16 @@ class CreateCommitBuildsService
|
||||
end
|
||||
|
||||
ref = Gitlab::Git.ref_name(origin_ref)
|
||||
tag = Gitlab::Git.tag_ref?(origin_ref)
|
||||
|
||||
# Skip branch removal
|
||||
if sha == Gitlab::Git::BLANK_SHA
|
||||
return false
|
||||
end
|
||||
|
||||
commit = project.ci_commit(sha)
|
||||
commit = project.ci_commit(sha, ref)
|
||||
unless commit
|
||||
commit = project.ci_commits.new(sha: sha)
|
||||
commit = project.ci_commits.new(sha: sha, ref: ref, before_sha: before_sha, tag: tag)
|
||||
|
||||
# Skip creating ci_commit when no gitlab-ci.yml is found
|
||||
unless commit.ci_yaml_file
|
||||
@@ -32,8 +34,7 @@ class CreateCommitBuildsService
|
||||
# Skip creating builds for commits that have [ci skip]
|
||||
unless commit.skip_ci?
|
||||
# Create builds for commit
|
||||
tag = Gitlab::Git.tag_ref?(origin_ref)
|
||||
commit.create_builds(ref, tag, user)
|
||||
commit.create_builds(user)
|
||||
end
|
||||
|
||||
commit
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
|
||||
%td.build-link
|
||||
- if project
|
||||
= link_to ci_status_path(build.commit) do
|
||||
= link_to builds_namespace_project_commit_path(project.namespace, project, build.sha) do
|
||||
%strong #{build.commit.short_sha}
|
||||
|
||||
%td.timestamp
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
.project-last-commit
|
||||
- ci_commit = project.ci_commit(commit.sha)
|
||||
- if ci_commit
|
||||
= link_to ci_status_path(ci_commit), class: "ci-status ci-#{ci_commit.status}" do
|
||||
= ci_status_icon(ci_commit)
|
||||
= ci_status_label(ci_commit)
|
||||
- if commit.status
|
||||
= link_to project_commit_path(commit.project, commit), class: "ci-status ci-#{commit.status}" do
|
||||
= ci_icon_for_status(commit.status)
|
||||
= ci_label_for_status(commit.status)
|
||||
|
||||
= link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id"
|
||||
= link_to_gfm commit.title, namespace_project_commit_path(project.namespace, project, commit), class: "commit-row-message"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
.build-page
|
||||
.gray-content-block.top-block
|
||||
Build ##{@build.id} for commit
|
||||
%strong.monospace= link_to @build.commit.short_sha, ci_status_path(@build.commit)
|
||||
%strong.monospace= link_to @build.commit.short_sha, builds_namespace_project_commit_path(@project.namespace, @project, @build.sha)
|
||||
from
|
||||
= link_to @build.ref, namespace_project_commits_path(@project.namespace, @project, @build.ref)
|
||||
- merge_request = @build.merge_request
|
||||
@@ -13,7 +13,7 @@
|
||||
= link_to "merge request ##{merge_request.iid}", merge_request_path(merge_request)
|
||||
|
||||
#up-build-trace
|
||||
- builds = @build.commit.matrix_builds(@build)
|
||||
- builds = @build.commit.builds.latest.to_a
|
||||
- if builds.size > 1
|
||||
%ul.nav-links.no-top.no-bottom
|
||||
- builds.each do |build|
|
||||
@@ -173,7 +173,7 @@
|
||||
Commit
|
||||
.pull-right
|
||||
%small
|
||||
= link_to @build.commit.short_sha, ci_status_path(@build.commit), class: "monospace"
|
||||
= link_to @build.commit.short_sha, builds_namespace_project_commit_path(@project.namespace, @project, @build.sha), class: "monospace"
|
||||
%p
|
||||
%span.attr-name Branch:
|
||||
= link_to @build.ref, namespace_project_commits_path(@project.namespace, @project, @build.ref)
|
||||
@@ -196,7 +196,7 @@
|
||||
.build-widget
|
||||
%h4.title #{pluralize(@builds.count(:id), "other build")} for
|
||||
= succeed ":" do
|
||||
= link_to @build.commit.short_sha, ci_status_path(@build.commit), class: "monospace"
|
||||
= link_to @build.commit.short_sha, builds_namespace_project_commit_path(@project.namespace, @project, build.sha), class: "monospace"
|
||||
%table.table.builds
|
||||
- @builds.each_with_index do |build, i|
|
||||
%tr.build
|
||||
|
||||
@@ -19,11 +19,12 @@
|
||||
%td
|
||||
= link_to build.short_sha, namespace_project_commit_path(build.project.namespace, build.project, build.sha), class: "monospace"
|
||||
|
||||
%td
|
||||
- if build.ref
|
||||
= link_to build.ref, namespace_project_commits_path(build.project.namespace, build.project, build.ref)
|
||||
- else
|
||||
.light none
|
||||
- if !defined?(ref) || ref
|
||||
%td
|
||||
- if build.ref
|
||||
= link_to build.ref, namespace_project_commits_path(build.project.namespace, build.project, build.ref)
|
||||
- else
|
||||
.light none
|
||||
|
||||
- if defined?(runner) && runner
|
||||
%td
|
||||
@@ -48,6 +49,8 @@
|
||||
%span.label.label-info triggered
|
||||
- if build.try(:allow_failure)
|
||||
%span.label.label-danger allowed to fail
|
||||
- if defined?(retried) && retried
|
||||
%span.label.label-warning retried
|
||||
|
||||
%td.duration
|
||||
- if build.duration
|
||||
|
||||
@@ -1,67 +1,2 @@
|
||||
.gray-content-block.middle-block
|
||||
.pull-right
|
||||
- if can?(current_user, :update_build, @ci_commit.project)
|
||||
- if @ci_commit.builds.latest.failed.any?(&:retryable?)
|
||||
= link_to "Retry failed", retry_builds_namespace_project_commit_path(@ci_commit.project.namespace, @ci_commit.project, @ci_commit.sha), class: 'btn btn-grouped btn-primary', method: :post
|
||||
|
||||
- if @ci_commit.builds.running_or_pending.any?
|
||||
= link_to "Cancel running", cancel_builds_namespace_project_commit_path(@ci_commit.project.namespace, @ci_commit.project, @ci_commit.sha), data: { confirm: 'Are you sure?' }, class: 'btn btn-grouped btn-danger', method: :post
|
||||
|
||||
.oneline
|
||||
= pluralize @statuses.count(:id), "build"
|
||||
- if defined?(link_to_commit) && link_to_commit
|
||||
for commit
|
||||
= link_to @ci_commit.short_sha, namespace_project_commit_path(@ci_commit.project.namespace, @ci_commit.project, @ci_commit.sha), class: "monospace"
|
||||
- if @ci_commit.duration > 0
|
||||
in
|
||||
= time_interval_in_words @ci_commit.duration
|
||||
|
||||
- if @ci_commit.yaml_errors.present?
|
||||
.bs-callout.bs-callout-danger
|
||||
%h4 Found errors in your .gitlab-ci.yml:
|
||||
%ul
|
||||
- @ci_commit.yaml_errors.split(",").each do |error|
|
||||
%li= error
|
||||
You can also test your .gitlab-ci.yml in the #{link_to "Lint", ci_lint_path}
|
||||
|
||||
- if @ci_commit.project.builds_enabled? && !@ci_commit.ci_yaml_file
|
||||
.bs-callout.bs-callout-warning
|
||||
\.gitlab-ci.yml not found in this commit
|
||||
|
||||
.table-holder
|
||||
%table.table.builds
|
||||
%thead
|
||||
%tr
|
||||
%th Status
|
||||
%th Build ID
|
||||
%th Ref
|
||||
%th Stage
|
||||
%th Name
|
||||
%th Duration
|
||||
%th Finished at
|
||||
- if @ci_commit.project.build_coverage_enabled?
|
||||
%th Coverage
|
||||
%th
|
||||
- @ci_commit.refs.each do |ref|
|
||||
- builds = @ci_commit.statuses.for_ref(ref).latest.ordered
|
||||
= render builds, coverage: @ci_commit.project.build_coverage_enabled?, stage: true, allow_retry: true
|
||||
|
||||
- if @ci_commit.retried.any?
|
||||
.gray-content-block.second-block
|
||||
Retried builds
|
||||
|
||||
.table-holder
|
||||
%table.table.builds
|
||||
%thead
|
||||
%tr
|
||||
%th Status
|
||||
%th Build ID
|
||||
%th Ref
|
||||
%th Stage
|
||||
%th Name
|
||||
%th Duration
|
||||
%th Finished at
|
||||
- if @ci_commit.project.build_coverage_enabled?
|
||||
%th Coverage
|
||||
%th
|
||||
= render @ci_commit.retried, coverage: @ci_commit.project.build_coverage_enabled?, stage: true
|
||||
- @ci_commits.each do |ci_commit|
|
||||
= render "ci_commit", ci_commit: ci_commit
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
.gray-content-block.middle-block
|
||||
.pull-right
|
||||
- if can?(current_user, :update_build, @project)
|
||||
- if ci_commit.builds.latest.failed.any?(&:retryable?)
|
||||
= link_to "Retry failed", retry_builds_namespace_project_commit_path(@project.namespace, @project, @commit.id), class: 'btn btn-grouped btn-primary', method: :post
|
||||
|
||||
- if ci_commit.builds.running_or_pending.any?
|
||||
= link_to "Cancel running", cancel_builds_namespace_project_commit_path(@project.namespace, @project, @commit.id), data: { confirm: 'Are you sure?' }, class: 'btn btn-grouped btn-danger', method: :post
|
||||
|
||||
.oneline
|
||||
= pluralize ci_commit.statuses.count(:id), "build"
|
||||
- if ci_commit.ref
|
||||
for
|
||||
%span.label.label-info
|
||||
= ci_commit.ref
|
||||
- if defined?(link_to_commit) && link_to_commit
|
||||
for commit
|
||||
= link_to @commit.short_id, namespace_project_commit_path(@project.namespace, @project, @commit.id), class: "monospace"
|
||||
- if ci_commit.duration > 0
|
||||
in
|
||||
= time_interval_in_words ci_commit.duration
|
||||
|
||||
- if ci_commit.yaml_errors.present?
|
||||
.bs-callout.bs-callout-danger
|
||||
%h4 Found errors in your .gitlab-ci.yml:
|
||||
%ul
|
||||
- ci_commit.yaml_errors.split(",").each do |error|
|
||||
%li= error
|
||||
You can also test your .gitlab-ci.yml in the #{link_to "Lint", ci_lint_path}
|
||||
|
||||
- if @project.builds_enabled? && !ci_commit.ci_yaml_file
|
||||
.bs-callout.bs-callout-warning
|
||||
\.gitlab-ci.yml not found in this commit
|
||||
|
||||
.table-holder
|
||||
%table.table.builds
|
||||
%thead
|
||||
%tr
|
||||
%th Status
|
||||
%th Build ID
|
||||
%th Stage
|
||||
%th Name
|
||||
%th Duration
|
||||
%th Finished at
|
||||
- if @project.build_coverage_enabled?
|
||||
%th Coverage
|
||||
%th
|
||||
- builds = ci_commit.statuses.latest.ordered
|
||||
= render builds, coverage: @project.build_coverage_enabled?, stage: true, ref: false, allow_retry: true
|
||||
|
||||
- if ci_commit.retried.any?
|
||||
.gray-content-block.second-block
|
||||
Retried builds
|
||||
|
||||
.table-holder
|
||||
%table.table.builds
|
||||
%thead
|
||||
%tr
|
||||
%th Status
|
||||
%th Build ID
|
||||
%th Ref
|
||||
%th Stage
|
||||
%th Name
|
||||
%th Duration
|
||||
%th Finished at
|
||||
- if @project.build_coverage_enabled?
|
||||
%th Coverage
|
||||
%th
|
||||
= render ci_commit.retried, coverage: @project.build_coverage_enabled?, stage: true, ref: false
|
||||
@@ -42,12 +42,12 @@
|
||||
- @commit.parents.each do |parent|
|
||||
= link_to parent.short_id, namespace_project_commit_path(@project.namespace, @project, parent), class: "monospace"
|
||||
|
||||
- if @ci_commit
|
||||
- if @commit.status
|
||||
.pull-right
|
||||
= link_to ci_status_path(@ci_commit), class: "ci-status ci-#{@ci_commit.status}" do
|
||||
= ci_status_icon(@ci_commit)
|
||||
= link_to builds_namespace_project_commit_path(@project.namespace, @project, @commit.id), class: "ci-status ci-#{@commit.status}" do
|
||||
= ci_icon_for_status(@commit.status)
|
||||
build:
|
||||
= ci_status_label(@ci_commit)
|
||||
= ci_label_for_status(@commit.status)
|
||||
|
||||
.commit-info-row.branches
|
||||
%i.fa.fa-spinner.fa-spin
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
.prepend-top-default
|
||||
= render "commit_box"
|
||||
- if @ci_commit
|
||||
- if @commit.status
|
||||
= render "ci_menu"
|
||||
- else
|
||||
%div.block-connector
|
||||
|
||||
@@ -4,9 +4,8 @@
|
||||
- notes = commit.notes
|
||||
- note_count = notes.user.count
|
||||
|
||||
- ci_commit = project.ci_commit(commit.sha)
|
||||
- cache_key = [project.path_with_namespace, commit.id, current_application_settings, note_count]
|
||||
- cache_key.push(ci_commit.status) if ci_commit
|
||||
- cache_key.push(commit.status) if commit.status
|
||||
|
||||
= cache(cache_key) do
|
||||
%li.commit.js-toggle-container{ id: "commit-#{commit.short_id}" }
|
||||
@@ -17,8 +16,8 @@
|
||||
%a.text-expander.js-toggle-button ...
|
||||
|
||||
.pull-right
|
||||
- if ci_commit
|
||||
= render_ci_status(ci_commit)
|
||||
- if commit.status
|
||||
= render_ci_status(commit)
|
||||
|
||||
= clipboard_button(clipboard_text: commit.id)
|
||||
= link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
- @related_branches.each do |branch|
|
||||
%li
|
||||
- sha = @project.repository.find_branch(branch).target
|
||||
- ci_commit = @project.ci_commit(sha) if sha
|
||||
- ci_commit = @project.ci_commit(sha, branch) if sha
|
||||
- if ci_commit
|
||||
%span.related-branch-ci-status
|
||||
= render_ci_status(ci_commit)
|
||||
|
||||
@@ -6,9 +6,8 @@
|
||||
- css_class = '' unless local_assigns[:css_class]
|
||||
- show_last_commit_as_description = false unless local_assigns[:show_last_commit_as_description] == true && project.commit
|
||||
- css_class += " no-description" if project.description.blank? && !show_last_commit_as_description
|
||||
- ci_commit = project.ci_commit(project.commit.sha) if ci && !project.empty_repo? && project.commit
|
||||
- cache_key = [project.namespace, project, controller.controller_name, controller.action_name, current_application_settings, 'v2.3']
|
||||
- cache_key.push(ci_commit.status) if ci_commit
|
||||
- cache_key.push(project.commit.status) if project.commit.status
|
||||
|
||||
%li.project-row{ class: css_class }
|
||||
= cache(cache_key) do
|
||||
@@ -16,9 +15,9 @@
|
||||
- if project.main_language
|
||||
%span
|
||||
= project.main_language
|
||||
- if ci_commit
|
||||
- if project.commit.status
|
||||
%span
|
||||
= render_ci_status(ci_commit)
|
||||
= render_ci_status(project.commit)
|
||||
- if forks
|
||||
%span
|
||||
= icon('code-fork')
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
class AddFieldsToCiCommit < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :ci_commits, :status, :string
|
||||
add_column :ci_commits, :started_at, :timestamp
|
||||
add_column :ci_commits, :finished_at, :timestamp
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
class AddActionToCiCommit < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :ci_commits, :action, :string
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
class AddDurationToCiCommit < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :ci_commits, :duration, :integer
|
||||
end
|
||||
end
|
||||
+18
-2
@@ -11,7 +11,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20160331223143) do
|
||||
ActiveRecord::Schema.define(version: 20160411122626) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
@@ -141,6 +141,7 @@ ActiveRecord::Schema.define(version: 20160331223143) do
|
||||
t.text "artifacts_metadata"
|
||||
t.integer "erased_by_id"
|
||||
t.datetime "erased_at"
|
||||
t.string "plugin"
|
||||
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
|
||||
@@ -168,6 +169,11 @@ ActiveRecord::Schema.define(version: 20160331223143) do
|
||||
t.text "yaml_errors"
|
||||
t.datetime "committed_at"
|
||||
t.integer "gl_project_id"
|
||||
t.string "status"
|
||||
t.datetime "started_at"
|
||||
t.datetime "finished_at"
|
||||
t.string "action"
|
||||
t.integer "duration"
|
||||
end
|
||||
|
||||
add_index "ci_commits", ["gl_project_id"], name: "index_ci_commits_on_gl_project_id", using: :btree
|
||||
@@ -306,11 +312,20 @@ ActiveRecord::Schema.define(version: 20160331223143) do
|
||||
add_index "ci_tags", ["name"], name: "index_ci_tags_on_name", unique: true, using: :btree
|
||||
|
||||
create_table "ci_trigger_requests", force: :cascade do |t|
|
||||
t.integer "trigger_id", null: false
|
||||
t.integer "trigger_id"
|
||||
t.text "variables"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.integer "commit_id"
|
||||
t.string "sha"
|
||||
t.string "before_sha"
|
||||
t.string "ref"
|
||||
t.string "action"
|
||||
t.string "status"
|
||||
t.datetime "started_at"
|
||||
t.datetime "finished_at"
|
||||
t.integer "project_id"
|
||||
t.string "origin_ref"
|
||||
end
|
||||
|
||||
create_table "ci_triggers", force: :cascade do |t|
|
||||
@@ -731,6 +746,7 @@ ActiveRecord::Schema.define(version: 20160331223143) do
|
||||
t.boolean "public_builds", default: true, null: false
|
||||
t.string "main_language"
|
||||
t.integer "pushes_since_gc", default: 0
|
||||
t.boolean "images_enabled"
|
||||
end
|
||||
|
||||
add_index "projects", ["builds_enabled", "shared_runners_enabled"], name: "index_projects_on_builds_enabled_and_shared_runners_enabled", using: :btree
|
||||
|
||||
@@ -21,7 +21,7 @@ module API
|
||||
authorize!(:read_commit_status, user_project)
|
||||
|
||||
not_found!('Commit') unless user_project.commit(params[:sha])
|
||||
ci_commit = user_project.ci_commit(params[:sha])
|
||||
ci_commit = user_project.ci_commit(params[:sha], params[:ref])
|
||||
return [] unless ci_commit
|
||||
|
||||
statuses = ci_commit.statuses
|
||||
|
||||
Reference in New Issue
Block a user