Commit 3eef0e18 authored by Kamil Trzciński's avatar Kamil Trzciński

Merge branch 'refactor-build-service' into 'master'

Refactor Ci::Commit and Ci::Build to have all builds for same :sha on single page

This makes Ci::Commit to have only :sha and simplifies routing to have only :sha in path. The :ref and :push_data is now parameter of Ci::Build.

All commit related data (git author, message and .gitlab-ci.yml) is read directly from repository.

All code related for creating builds is moved to CreateBuildsService.

Status deduction is rewritten to make if more efficient and easier to integrate with Commit Status API.

This is partially working, tests are not yet touched.

This slightly changes view of Commit:
![Screen_Shot_2015-10-02_at_15.21.47](https://gitlab.com/gitlab-org/gitlab-ce/uploads/ad3f1ccdcc87659ea437d8db6c5b9f94/Screen_Shot_2015-10-02_at_15.21.47.png)

@dzaporozhets What do you think?


See merge request !1502
parents 97f7edf3 97a11136
...@@ -18,7 +18,7 @@ module Ci ...@@ -18,7 +18,7 @@ module Ci
if commit if commit
# Redirect to commit page # Redirect to commit page
redirect_to ci_project_ref_commit_path(@project, @build.commit.ref, @build.commit.sha) redirect_to ci_project_commit_path(@project, @build.commit)
return return
end end
end end
......
...@@ -13,7 +13,7 @@ module Ci ...@@ -13,7 +13,7 @@ module Ci
end end
def status def status
commit = Ci::Project.find(params[:project_id]).commits.find_by_sha_and_ref!(params[:id], params[:ref_id]) commit = Ci::Project.find(params[:project_id]).commits.find_by_sha!(params[:id])
render json: commit.to_json(only: [:id, :sha], methods: [:status, :coverage]) render json: commit.to_json(only: [:id, :sha], methods: [:status, :coverage])
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render json: { status: "not_found" } render json: { status: "not_found" }
...@@ -22,7 +22,7 @@ module Ci ...@@ -22,7 +22,7 @@ module Ci
def cancel def cancel
commit.builds.running_or_pending.each(&:cancel) commit.builds.running_or_pending.each(&:cancel)
redirect_to ci_project_ref_commits_path(project, commit.ref, commit.sha) redirect_to ci_project_commits_path(project, commit.sha)
end end
private private
...@@ -32,7 +32,7 @@ module Ci ...@@ -32,7 +32,7 @@ module Ci
end end
def commit def commit
@commit ||= Ci::Project.find(params[:project_id]).commits.find_by_sha_and_ref!(params[:id], params[:ref_id]) @commit ||= Ci::Project.find(params[:project_id]).commits.find_by_sha!(params[:id])
end end
end end
end end
...@@ -19,7 +19,8 @@ module Ci ...@@ -19,7 +19,8 @@ module Ci
@ref = params[:ref] @ref = params[:ref]
@commits = @project.commits.reverse_order @commits = @project.commits.reverse_order
@commits = @commits.where(ref: @ref) if @ref # TODO: this is broken
# @commits = @commits.where(ref: @ref) if @ref
@commits = @commits.page(params[:page]).per(20) @commits = @commits.page(params[:page]).per(20)
end end
......
...@@ -3,10 +3,6 @@ module BuildsHelper ...@@ -3,10 +3,6 @@ module BuildsHelper
gitlab_ref_link build.project, build.ref gitlab_ref_link build.project, build.ref
end end
def build_compare_link build
gitlab_compare_link build.project, build.commit.short_before_sha, build.short_sha
end
def build_commit_link build def build_commit_link build
gitlab_commit_link build.project, build.short_sha gitlab_commit_link build.project, build.short_sha
end end
......
module Ci module Ci
module CommitsHelper module CommitsHelper
def ci_commit_path(commit) def ci_commit_path(commit)
ci_project_ref_commits_path(commit.project, commit.ref, commit.sha) ci_project_commits_path(commit.project, commit)
end end
def commit_link(commit) def commit_link(commit)
......
...@@ -26,7 +26,7 @@ module Ci ...@@ -26,7 +26,7 @@ module Ci
def yaml_web_editor_link(project) def yaml_web_editor_link(project)
commits = project.commits commits = project.commits
if commits.any? && commits.last.push_data[:ci_yaml_file] if commits.any? && commits.last.ci_yaml_file
"#{project.gitlab_url}/edit/master/.gitlab-ci.yml" "#{project.gitlab_url}/edit/master/.gitlab-ci.yml"
else else
"#{project.gitlab_url}/new/master" "#{project.gitlab_url}/new/master"
......
module CiStatusHelper module CiStatusHelper
def ci_status_path(ci_commit) def ci_status_path(ci_commit)
ci_project_ref_commits_path(ci_commit.project, ci_commit.ref, ci_commit) ci_project_commits_path(ci_commit.project, ci_commit)
end end
def ci_status_icon(ci_commit) def ci_status_icon(ci_commit)
......
...@@ -32,12 +32,14 @@ module Ci ...@@ -32,12 +32,14 @@ module Ci
belongs_to :commit, class_name: 'Ci::Commit' 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 :commit, presence: true
validates :status, presence: true validates :status, presence: true
validates :coverage, numericality: true, allow_blank: true validates :coverage, numericality: true, allow_blank: true
validates_presence_of :ref
scope :running, ->() { where(status: "running") } scope :running, ->() { where(status: "running") }
scope :pending, ->() { where(status: "pending") } scope :pending, ->() { where(status: "pending") }
...@@ -45,6 +47,10 @@ module Ci ...@@ -45,6 +47,10 @@ module Ci
scope :failed, ->() { where(status: "failed") } 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 :running_or_pending, ->() { where(status:[:running, :pending]) }
scope :latest, ->() { where(id: unscope(:select).select('max(id)').group(:name)).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 acts_as_taggable
...@@ -75,6 +81,8 @@ module Ci ...@@ -75,6 +81,8 @@ module Ci
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.tag = build.tag
new_build.options = build.options new_build.options = build.options
new_build.commands = build.commands new_build.commands = build.commands
new_build.tag_list = build.tag_list new_build.tag_list = build.tag_list
...@@ -82,6 +90,7 @@ module Ci ...@@ -82,6 +90,7 @@ module Ci
new_build.name = build.name new_build.name = build.name
new_build.allow_failure = build.allow_failure new_build.allow_failure = build.allow_failure
new_build.stage = build.stage new_build.stage = build.stage
new_build.stage_idx = build.stage_idx
new_build.trigger_request = build.trigger_request new_build.trigger_request = build.trigger_request
new_build.save new_build.save
new_build new_build
...@@ -117,8 +126,8 @@ module Ci ...@@ -117,8 +126,8 @@ module Ci
Ci::WebHookService.new.build_end(build) Ci::WebHookService.new.build_end(build)
end end
if build.commit.success? if build.commit.should_create_next_builds?(build)
build.commit.create_next_builds(build.trigger_request) build.commit.create_next_builds(build.ref, build.tag, build.user, build.trigger_request)
end end
project.execute_services(build) project.execute_services(build)
...@@ -135,9 +144,13 @@ module Ci ...@@ -135,9 +144,13 @@ module Ci
state :canceled, value: 'canceled' state :canceled, value: 'canceled'
end end
delegate :sha, :short_sha, :before_sha, :ref, :project, delegate :sha, :short_sha, :project,
to: :commit, prefix: false to: :commit, prefix: false
def before_sha
Gitlab::Git::BLANK_SHA
end
def trace_html def trace_html
html = Ci::Ansi2html::convert(trace) if trace.present? html = Ci::Ansi2html::convert(trace) if trace.present?
html || '' html || ''
...@@ -187,6 +200,16 @@ module Ci ...@@ -187,6 +200,16 @@ module Ci
project.name project.name
end end
def project_recipients
recipients = project.email_recipients.split(' ')
if project.email_add_pusher? && user.present? && user.notification_email.present?
recipients << user.notification_email
end
recipients.uniq
end
def repo_url def repo_url
project.repo_url_with_auth project.repo_url_with_auth
end end
......
...@@ -23,9 +23,7 @@ module Ci ...@@ -23,9 +23,7 @@ module Ci
has_many :builds, dependent: :destroy, class_name: 'Ci::Build' has_many :builds, dependent: :destroy, class_name: 'Ci::Build'
has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest' has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest'
serialize :push_data validates_presence_of :sha
validates_presence_of :ref, :sha, :before_sha, :push_data
validate :valid_commit_sha validate :valid_commit_sha
def self.truncate_sha(sha) def self.truncate_sha(sha)
...@@ -60,28 +58,16 @@ module Ci ...@@ -60,28 +58,16 @@ module Ci
end end
end end
def new_branch?
before_sha == Ci::Git::BLANK_SHA
end
def compare?
!new_branch?
end
def git_author_name def git_author_name
commit_data[:author][:name] if commit_data && commit_data[:author] commit_data.author_name if commit_data
end end
def git_author_email def git_author_email
commit_data[:author][:email] if commit_data && commit_data[:author] commit_data.author_email if commit_data
end end
def git_commit_message def git_commit_message
commit_data[:message] if commit_data && commit_data[:message] commit_data.message if commit_data
end
def short_before_sha
Ci::Commit.truncate_sha(before_sha)
end end
def short_sha def short_sha
...@@ -89,84 +75,51 @@ module Ci ...@@ -89,84 +75,51 @@ module Ci
end end
def commit_data def commit_data
push_data[:commits].find do |commit| @commit ||= gl_project.commit(sha)
commit[:id] == sha
end
rescue rescue
nil nil
end end
def project_recipients
recipients = project.email_recipients.split(' ')
if project.email_add_pusher? && push_data[:user_email].present?
recipients << push_data[:user_email]
end
recipients.uniq
end
def stage def stage
return unless config_processor running_or_pending = builds_without_retry.running_or_pending
stages = builds_without_retry.select(&:active?).map(&:stage) running_or_pending.limit(1).pluck(:stage).first
config_processor.stages.find { |stage| stages.include? stage }
end end
def create_builds_for_stage(stage, trigger_request) def create_builds(ref, tag, user, trigger_request = nil)
return if skip_ci? && trigger_request.blank? return if skip_ci? && trigger_request.blank?
return unless config_processor return unless config_processor
config_processor.stages.any? do |stage|
builds_attrs = config_processor.builds_for_stage_and_ref(stage, ref, tag) CreateBuildsService.new.execute(self, stage, ref, tag, user, trigger_request).present?
builds_attrs.map do |build_attrs|
builds.create!({
name: build_attrs[:name],
commands: build_attrs[:script],
tag_list: build_attrs[:tags],
options: build_attrs[:options],
allow_failure: build_attrs[:allow_failure],
stage: build_attrs[:stage],
trigger_request: trigger_request,
})
end end
end end
def create_next_builds(trigger_request) def create_next_builds(ref, tag, user, trigger_request)
return if skip_ci? && trigger_request.blank? return if skip_ci? && trigger_request.blank?
return unless config_processor return unless config_processor
stages = builds.where(trigger_request: trigger_request).group_by(&:stage) stages = builds.where(ref: ref, tag: tag, trigger_request: trigger_request).group_by(&:stage)
config_processor.stages.any? do |stage| config_processor.stages.any? do |stage|
!stages.include?(stage) && create_builds_for_stage(stage, trigger_request).present? unless stages.include?(stage)
CreateBuildsService.new.execute(self, stage, ref, tag, user, trigger_request).present?
end
end end
end end
def create_builds(trigger_request = nil) def refs
return if skip_ci? && trigger_request.blank? builds.group(:ref).pluck(:ref)
return unless config_processor
config_processor.stages.any? do |stage|
create_builds_for_stage(stage, trigger_request).present?
end end
def last_ref
builds.latest.first.try(:ref)
end end
def builds_without_retry def builds_without_retry
@builds_without_retry ||= builds.latest
begin
grouped_builds = builds.group_by(&:name)
grouped_builds.map do |name, builds|
builds.sort_by(&:id).last
end
end
end end
def builds_without_retry_sorted def builds_without_retry_for_ref(ref)
return builds_without_retry unless config_processor builds.for_ref(ref).latest
stages = config_processor.stages
builds_without_retry.sort_by do |build|
[stages.index(build.stage) || -1, build.name || ""]
end
end end
def retried_builds def retried_builds
...@@ -225,6 +178,10 @@ module Ci ...@@ -225,6 +178,10 @@ module Ci
@duration ||= builds_without_retry.select(&:duration).sum(&:duration).to_i @duration ||= builds_without_retry.select(&:duration).sum(&:duration).to_i
end end
def duration_for_ref(ref)
builds_without_retry_for_ref(ref).select(&:duration).sum(&:duration).to_i
end
def finished_at def finished_at
@finished_at ||= builds.order('finished_at DESC').first.try(:finished_at) @finished_at ||= builds.order('finished_at DESC').first.try(:finished_at)
end end
...@@ -238,12 +195,12 @@ module Ci ...@@ -238,12 +195,12 @@ module Ci
end end
end end
def matrix? def matrix_for_ref?(ref)
builds_without_retry.size > 1 builds_without_retry_for_ref(ref).pluck(:id).size > 1
end end
def config_processor def config_processor
@config_processor ||= Ci::GitlabCiYamlProcessor.new(push_data[:ci_yaml_file]) @config_processor ||= Ci::GitlabCiYamlProcessor.new(ci_yaml_file)
rescue Ci::GitlabCiYamlProcessor::ValidationError => e rescue Ci::GitlabCiYamlProcessor::ValidationError => e
save_yaml_error(e.message) save_yaml_error(e.message)
nil nil
...@@ -253,16 +210,31 @@ module Ci ...@@ -253,16 +210,31 @@ module Ci
nil nil
end end
def ci_yaml_file
gl_project.repository.blob_at(sha, '.gitlab-ci.yml')
rescue
nil
end
def skip_ci? def skip_ci?
return false if builds.any? return false if builds.any?
commits = push_data[:commits] git_commit_message =~ /(\[ci skip\])/ if git_commit_message
commits.present? && commits.last[:message] =~ /(\[ci skip\])/
end end
def update_committed! def update_committed!
update!(committed_at: DateTime.now) update!(committed_at: DateTime.now)
end end
def should_create_next_builds?(build)
# don't create other builds if this one is retried
other_builds = builds.similar(build).latest
return false unless other_builds.include?(build)
other_builds.all? do |build|
build.success? || build.ignored?
end
end
private private
def save_yaml_error(error) def save_yaml_error(error)
......
...@@ -28,18 +28,6 @@ module Ci ...@@ -28,18 +28,6 @@ module Ci
status status
end end
# only check for toggling build status within same ref.
def last_commit_changed_status?
ref = last_commit.ref
last_commits = commits.where(ref: ref).last(2)
if last_commits.size < 2
false
else
last_commits[0].status != last_commits[1].status
end
end
def last_commit_for_ref(ref) def last_commit_for_ref(ref)
commits.where(ref: ref).last commits.where(ref: ref).last
end end
......
...@@ -744,7 +744,11 @@ class Project < ActiveRecord::Base ...@@ -744,7 +744,11 @@ class Project < ActiveRecord::Base
end end
def ci_commit(sha) def ci_commit(sha)
gitlab_ci_project.commits.find_by(sha: sha) if gitlab_ci? ci_commits.find_by(sha: sha)
end
def ensure_ci_commit(sha)
ci_commit(sha) || ci_commits.create(sha: sha)
end end
def ensure_gitlab_ci_project def ensure_gitlab_ci_project
......
...@@ -11,14 +11,7 @@ module Ci ...@@ -11,14 +11,7 @@ module Ci
def to_s def to_s
lines = Array.new lines = Array.new
lines.push("<a href=\"#{ci_project_url(project)}\">#{project.name}</a> - ") lines.push("<a href=\"#{ci_project_url(project)}\">#{project.name}</a> - ")
lines.push("<a href=\"#{ci_project_commits_url(project, commit.sha)}\">Commit ##{commit.id}</a></br>")
if commit.matrix?
lines.push("<a href=\"#{ci_project_ref_commits_url(project, commit.ref, commit.sha)}\">Commit ##{commit.id}</a></br>")
else
first_build = commit.builds_without_retry.first
lines.push("<a href=\"#{ci_project_build_url(project, first_build)}\">Build '#{first_build.name}' ##{first_build.id}</a></br>")
end
lines.push("#{commit.short_sha} #{commit.git_author_name} - #{commit.git_commit_message}</br>") lines.push("#{commit.short_sha} #{commit.git_author_name} - #{commit.git_commit_message}</br>")
lines.push("#{humanized_status(commit_status)} in #{commit.duration} second(s).") lines.push("#{humanized_status(commit_status)} in #{commit.duration} second(s).")
lines.join('') lines.join('')
......
...@@ -61,7 +61,7 @@ module Ci ...@@ -61,7 +61,7 @@ module Ci
end end
def execute(build) def execute(build)
build.commit.project_recipients.each do |recipient| build.project_recipients.each do |recipient|
case build.status.to_sym case build.status.to_sym
when :success when :success
mailer.build_success_email(build.id, recipient) mailer.build_success_email(build.id, recipient)
......
...@@ -23,7 +23,6 @@ module Ci ...@@ -23,7 +23,6 @@ module Ci
def attachments def attachments
fields = [] fields = []
if commit.matrix?
commit.builds_without_retry.each do |build| commit.builds_without_retry.each do |build|
next if build.allow_failure? next if build.allow_failure?
next unless build.failed? next unless build.failed?
...@@ -32,7 +31,6 @@ module Ci ...@@ -32,7 +31,6 @@ module Ci
value: "Build <#{ci_project_build_url(project, build)}|\##{build.id}> failed in #{build.duration.to_i} second(s)." value: "Build <#{ci_project_build_url(project, build)}|\##{build.id}> failed in #{build.duration.to_i} second(s)."
} }
end end
end
[{ [{
text: attachment_message, text: attachment_message,
...@@ -47,12 +45,7 @@ module Ci ...@@ -47,12 +45,7 @@ module Ci
def attachment_message def attachment_message
out = "<#{ci_project_url(project)}|#{project_name}>: " out = "<#{ci_project_url(project)}|#{project_name}>: "
if commit.matrix? out << "Commit <#{ci_project_commits_url(project, commit.sha)}|\##{commit.id}> "
out << "Commit <#{ci_project_ref_commits_url(project, commit.ref, commit.sha)}|\##{commit.id}> "
else
build = commit.builds_without_retry.first
out << "Build <#{ci_project_build_url(project, build)}|\##{build.id}> "
end
out << "(<#{commit_sha_link}|#{commit.short_sha}>) " out << "(<#{commit_sha_link}|#{commit.short_sha}>) "
out << "of <#{commit_ref_link}|#{commit.ref}> " out << "of <#{commit_ref_link}|#{commit.ref}> "
out << "by #{commit.git_author_name} " if commit.git_author_name out << "by #{commit.git_author_name} " if commit.git_author_name
......
...@@ -40,19 +40,10 @@ class GitlabCiService < CiService ...@@ -40,19 +40,10 @@ class GitlabCiService < CiService
def execute(data) def execute(data)
return unless supported_events.include?(data[:object_kind]) return unless supported_events.include?(data[:object_kind])
sha = data[:checkout_sha] ci_project = project.gitlab_ci_project
if sha.present?
file = ci_yaml_file(sha)
if file && file.data
data.merge!(ci_yaml_file: file.data)
end
end
ci_project = Ci::Project.find_by(gitlab_id: project.id)
if ci_project if ci_project
Ci::CreateCommitService.new.execute(ci_project, data) current_user = User.find_by(id: data[:user_id])
Ci::CreateCommitService.new.execute(ci_project, current_user, data)
end end
end end
...@@ -63,7 +54,7 @@ class GitlabCiService < CiService ...@@ -63,7 +54,7 @@ class GitlabCiService < CiService
end end
def get_ci_commit(sha, ref) def get_ci_commit(sha, ref)
Ci::Project.find(project.gitlab_ci_project).commits.find_by_sha_and_ref!(sha, ref) Ci::Project.find(project.gitlab_ci_project).commits.find_by_sha!(sha)
end end
def commit_status(sha, ref) def commit_status(sha, ref)
...@@ -80,7 +71,7 @@ class GitlabCiService < CiService ...@@ -80,7 +71,7 @@ class GitlabCiService < CiService
def build_page(sha, ref) def build_page(sha, ref)
if project.gitlab_ci_project.present? if project.gitlab_ci_project.present?
ci_project_ref_commits_url(project.gitlab_ci_project, ref, sha) ci_project_commits_url(project.gitlab_ci_project, sha)
end end
end end
...@@ -99,14 +90,4 @@ class GitlabCiService < CiService ...@@ -99,14 +90,4 @@ class GitlabCiService < CiService
def fields def fields
[] []
end end
private
def ci_yaml_file(sha)
repository.blob_at(sha, '.gitlab-ci.yml')
end
def repository
project.repository
end
end end
...@@ -130,6 +130,7 @@ class User < ActiveRecord::Base ...@@ -130,6 +130,7 @@ class User < ActiveRecord::Base
has_many :assigned_merge_requests, dependent: :destroy, foreign_key: :assignee_id, class_name: "MergeRequest" has_many :assigned_merge_requests, dependent: :destroy, foreign_key: :assignee_id, class_name: "MergeRequest"
has_many :oauth_applications, class_name: 'Doorkeeper::Application', as: :owner, dependent: :destroy has_many :oauth_applications, class_name: 'Doorkeeper::Application', as: :owner, dependent: :destroy
has_one :abuse_report, dependent: :destroy has_one :abuse_report, dependent: :destroy
has_many :ci_builds, dependent: :nullify, class_name: 'Ci::Build'
# #
......
module Ci
class CreateBuildsService
def execute(commit, stage, ref, tag, user, trigger_request)
builds_attrs = commit.config_processor.builds_for_stage_and_ref(stage, ref, tag)
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])
build_attrs.slice!(:name,
:commands,
:tag_list,
:options,
:allow_failure,
:stage,
:stage_idx)
build_attrs.merge!(ref: ref,
tag: tag,
trigger_request: trigger_request,
user: user)
commit.builds.create!(build_attrs)
end
end
end
end
end
module Ci module Ci
class CreateCommitService class CreateCommitService
def execute(project, params) def execute(project, user, params)
before_sha = params[:before]
sha = params[:checkout_sha] || params[:after] sha = params[:checkout_sha] || params[:after]
origin_ref = params[:ref] origin_ref = params[:ref]
...@@ -16,33 +15,10 @@ module Ci ...@@ -16,33 +15,10 @@ module Ci
return false return false
end end
commit = project.commits.find_by_sha_and_ref(sha, ref) tag = origin_ref.start_with?('refs/tags/')
commit = project.gl_project.ensure_ci_commit(sha)
# Create commit if not exists yet
unless commit
data = {
ref: ref,
sha: sha,
tag: origin_ref.start_with?('refs/tags/'),
before_sha: before_sha,
push_data: {
before: before_sha,
after: sha,
ref: ref,
user_name: params[:user_name],
user_email: params[:user_email],
repository: params[:repository],
commits: params[:commits],
total_commits_count: params[:total_commits_count],
ci_yaml_file: params[:ci_yaml_file]
}
}
commit = project.commits.create(data)
end
commit.update_committed! commit.update_committed!
commit.create_builds unless commit.builds.any? commit.create_builds(ref, tag, user)
commit commit
end end
......
module Ci module Ci
class CreateTriggerRequestService class CreateTriggerRequestService
def execute(project, trigger, ref, variables = nil) def execute(project, trigger, ref, variables = nil)
commit = project.commits.where(ref: ref).last commit = project.gl_project.commit(ref)
return unless commit return unless commit
# check if ref is tag
tag = project.gl_project.repository.find_tag(ref).present?
ci_commit = project.gl_project.ensure_ci_commit(commit.sha)
trigger_request = trigger.trigger_requests.create!( trigger_request = trigger.trigger_requests.create!(
commit: commit, variables: variables,
variables: variables commit: ci_commit,
) )
if commit.create_builds(trigger_request) if ci_commit.create_builds(ref, tag, nil, trigger_request)
trigger_request trigger_request
end end
end end
......
...@@ -27,9 +27,8 @@ module Ci ...@@ -27,9 +27,8 @@ module Ci
project_name: project.name, project_name: project.name,
gitlab_url: project.gitlab_url, gitlab_url: project.gitlab_url,
ref: build.ref, ref: build.ref,
sha: build.sha,
before_sha: build.before_sha, before_sha: build.before_sha,
push_data: build.commit.push_data sha: build.sha,
}) })
end end
end end
......
...@@ -6,6 +6,10 @@ ...@@ -6,6 +6,10 @@
= link_to ci_project_build_path(build.project, build) do = link_to ci_project_build_path(build.project, build) do
%strong Build ##{build.id} %strong Build ##{build.id}
- if defined?(ref)
%td
= build.ref
%td %td
= build.stage = build.stage
......
#up-build-trace #up-build-trace
- if @commit.matrix? - if @commit.matrix_for_ref?(@build.ref)
%ul.center-top-menu %ul.center-top-menu
- @commit.builds_without_retry_sorted.each do |build| - @commit.builds_without_retry_for_ref(build.ref).each do |build|
%li{class: ('active' if build == @build) } %li{class: ('active' if build == @build) }
= link_to ci_project_build_url(@project, build) do = link_to ci_project_build_url(@project, build) do
= ci_icon_for_status(build.status) = ci_icon_for_status(build.status)
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
= build.id = build.id
- unless @commit.builds_without_retry.include?(@build) - unless @commit.builds_without_retry_for_ref(@build.ref).include?(@build)
%li.active %li.active
%a %a
Build ##{@build.id} Build ##{@build.id}
...@@ -122,11 +122,6 @@ ...@@ -122,11 +122,6 @@
Commit Commit
.pull-right .pull-right
%small #{build_commit_link @build} %small #{build_commit_link @build}
- if @build.commit.compare?
%p
%span.attr-name Compare:
#{build_compare_link @build}
%p %p
%span.attr-name Branch: %span.attr-name Branch:
#{build_ref_link @build} #{build_ref_link @build}
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
%td.build-link %td.build-link
= link_to ci_project_ref_commits_path(commit.project, commit.ref, commit.sha) do = link_to ci_project_commits_path(commit.project, commit.sha) do
%strong #{commit.short_sha} %strong #{commit.short_sha}
%td.build-message %td.build-message
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
%td.build-branch %td.build-branch
- unless @ref - unless @ref
%span %span
= link_to truncate(commit.ref, length: 25), ci_project_path(@project, ref: commit.ref) = link_to truncate(commit.last_ref, length: 25), ci_project_path(@project, ref: commit.last_ref)
%td.duration %td.duration
- if commit.duration > 0 - if commit.duration > 0
......
...@@ -9,19 +9,11 @@ ...@@ -9,19 +9,11 @@
.gray-content-block.second-block .gray-content-block.second-block
.row .row
.col-sm-6 .col-sm-6
- if @commit.compare?
%p
%span.attr-name Compare:
#{gitlab_compare_link(@project, @commit.short_before_sha, @commit.short_sha)}
- else
%p %p
%span.attr-name Commit: %span.attr-name Commit:
#{gitlab_commit_link(@project, @commit.sha)} #{gitlab_commit_link(@project, @commit.sha)}
%p
%span.attr-name Branch:
#{gitlab_ref_link(@project, @commit.ref)}
.col-sm-6 .col-sm-6
- if @commit.git_author_name || @commit.git_author_email
%p %p
%span.attr-name Author: %span.attr-name Author:
#{@commit.git_author_name} (#{@commit.git_author_email}) #{@commit.git_author_name} (#{@commit.git_author_email})
...@@ -33,7 +25,7 @@ ...@@ -33,7 +25,7 @@
- if current_user && can?(current_user, :manage_builds, gl_project) - if current_user && can?(current_user, :manage_builds, gl_project)
.pull-right .pull-right
- if @commit.builds.running_or_pending.any? - if @commit.builds.running_or_pending.any?
= link_to "Cancel", cancel_ci_project_ref_commits_path(@project, @commit.ref, @commit.sha), class: 'btn btn-sm btn-danger' = link_to "Cancel", cancel_ci_project_commits_path(@project, @commit), class: 'btn btn-sm btn-danger'
- if @commit.yaml_errors.present? - if @commit.yaml_errors.present?
...@@ -43,18 +35,19 @@ ...@@ -43,18 +35,19 @@
- @commit.yaml_errors.split(",").each do |error| - @commit.yaml_errors.split(",").each do |error|
%li= error %li= error
- unless @commit.push_data[:ci_yaml_file] - unless @commit.ci_yaml_file
.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
%h3 - @commit.refs.each do |ref|
Builds %h3
- if @commit.duration > 0 Builds for #{ref}
- if @commit.duration_for_ref(ref) > 0
%small.pull-right %small.pull-right
%i.fa.fa-time %i.fa.fa-time
#{time_interval_in_words @commit.duration} #{time_interval_in_words @commit.duration_for_ref(ref)}
%table.table.builds %table.table.builds
%thead %thead
%tr %tr
%th Status %th Status
...@@ -66,7 +59,7 @@ ...@@ -66,7 +59,7 @@
- if @project.coverage_enabled? - if @project.coverage_enabled?
%th Coverage %th Coverage
%th %th
= render @commit.builds_without_retry_sorted, controls: true = render @commit.builds_without_retry.for_ref(ref), controls: true
- if @commit.retried_builds.any? - if @commit.retried_builds.any?
%h3 %h3
...@@ -77,6 +70,7 @@ ...@@ -77,6 +70,7 @@
%tr %tr
%th Status %th Status
%th Build ID %th Build ID
%th Ref
%th Stage %th Stage
%th Name %th Name
%th Duration %th Duration
...@@ -84,4 +78,4 @@ ...@@ -84,4 +78,4 @@
- if @project.coverage_enabled? - if @project.coverage_enabled?
%th Coverage %th Coverage
%th %th
= render @commit.retried_builds = render @commit.retried_builds, ref: true
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
%p %p
Author: #{@build.commit.git_author_name} Author: #{@build.commit.git_author_name}
%p %p
Branch: #{@build.commit.ref} Branch: #{@build.ref}
%p %p
Message: #{@build.commit.git_commit_message} Message: #{@build.commit.git_commit_message}
......
...@@ -3,7 +3,7 @@ Build failed for <%= @project.name %> ...@@ -3,7 +3,7 @@ Build failed for <%= @project.name %>
Status: <%= @build.status %> Status: <%= @build.status %>
Commit: <%= @build.commit.short_sha %> Commit: <%= @build.commit.short_sha %>
Author: <%= @build.commit.git_author_name %> Author: <%= @build.commit.git_author_name %>
Branch: <%= @build.commit.ref %> Branch: <%= @build.ref %>
Message: <%= @build.commit.git_commit_message %> Message: <%= @build.commit.git_commit_message %>
Url: <%= ci_project_build_url(@build.project, @build) %> Url: <%= ci_project_build_url(@build.project, @build) %>
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
%p %p
Author: #{@build.commit.git_author_name} Author: #{@build.commit.git_author_name}
%p %p
Branch: #{@build.commit.ref} Branch: #{@build.ref}
%p %p
Message: #{@build.commit.git_commit_message} Message: #{@build.commit.git_commit_message}
......
...@@ -3,7 +3,7 @@ Build successful for <%= @project.name %> ...@@ -3,7 +3,7 @@ Build successful for <%= @project.name %>
Status: <%= @build.status %> Status: <%= @build.status %>
Commit: <%= @build.commit.short_sha %> Commit: <%= @build.commit.short_sha %>
Author: <%= @build.commit.git_author_name %> Author: <%= @build.commit.git_author_name %>
Branch: <%= @build.commit.ref %> Branch: <%= @build.ref %>
Message: <%= @build.commit.git_commit_message %> Message: <%= @build.commit.git_commit_message %>
Url: <%= ci_project_build_url(@build.project, @build) %> Url: <%= ci_project_build_url(@build.project, @build) %>
...@@ -30,14 +30,12 @@ Gitlab::Application.routes.draw do ...@@ -30,14 +30,12 @@ Gitlab::Application.routes.draw do
resource :charts, only: [:show] resource :charts, only: [:show]
resources :refs, constraints: { ref_id: /.*/ }, only: [] do
resources :commits, only: [:show] do resources :commits, only: [:show] do
member do member do
get :status get :status
get :cancel get :cancel
end end
end end
end
resources :builds, only: [:show] do resources :builds, only: [:show] do
member do member do
......
class AddStageIdxToBuilds < ActiveRecord::Migration
def change
add_column :ci_builds, :stage_idx, :integer
end
end
class AddIndexForBuilds < ActiveRecord::Migration
def up
add_index :ci_builds, [:commit_id, :stage_idx, :created_at]
end
end
class AddRefAndTagToBuilds < ActiveRecord::Migration
def change
add_column :ci_builds, :tag, :boolean
add_column :ci_builds, :ref, :string
end
end
class MigrateRefAndTagToBuild < ActiveRecord::Migration
def change
execute('UPDATE ci_builds SET ref=(SELECT ref FROM ci_commits WHERE ci_commits.id = ci_builds.commit_id) WHERE ref IS NULL')
execute('UPDATE ci_builds SET tag=(SELECT tag FROM ci_commits WHERE ci_commits.id = ci_builds.commit_id) WHERE tag IS NULL')
end
end
class AddUserIdToBuild < ActiveRecord::Migration
def change
add_column :ci_builds, :user_id, :integer
end
end
...@@ -11,7 +11,7 @@ ...@@ -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: 20150930095736) do ActiveRecord::Schema.define(version: 20151005075649) 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"
...@@ -100,8 +100,13 @@ ActiveRecord::Schema.define(version: 20150930095736) do ...@@ -100,8 +100,13 @@ ActiveRecord::Schema.define(version: 20150930095736) do
t.boolean "allow_failure", default: false, null: false t.boolean "allow_failure", default: false, null: false
t.string "stage" t.string "stage"
t.integer "trigger_request_id" t.integer "trigger_request_id"
t.integer "stage_idx"
t.boolean "tag"
t.string "ref"
t.integer "user_id"
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"], 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
......
...@@ -51,7 +51,7 @@ module Ci ...@@ -51,7 +51,7 @@ module Ci
required_attributes! [:project_id, :data, :project_token] required_attributes! [:project_id, :data, :project_token]
project = Ci::Project.find(params[:project_id]) project = Ci::Project.find(params[:project_id])
authenticate_project_token!(project) authenticate_project_token!(project)
commit = Ci::CreateCommitService.new.execute(project, params[:data]) commit = Ci::CreateCommitService.new.execute(project, current_user, params[:data])
if commit.persisted? if commit.persisted?
present commit, with: Entities::CommitWithBuilds present commit, with: Entities::CommitWithBuilds
......
...@@ -85,9 +85,10 @@ module Ci ...@@ -85,9 +85,10 @@ module Ci
def build_job(name, job) def build_job(name, job)
{ {
stage_idx: stages.index(job[:stage]),
stage: job[:stage], stage: job[:stage],
script: "#{@before_script.join("\n")}\n#{normalize_script(job[:script])}", commands: "#{@before_script.join("\n")}\n#{normalize_script(job[:script])}",
tags: job[:tags] || [], tag_list: job[:tags] || [],
name: name, name: name,
only: job[:only], only: job[:only],
except: job[:except], except: job[:except],
......
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
FactoryGirl.define do FactoryGirl.define do
factory :ci_build, class: Ci::Build do factory :ci_build, class: Ci::Build do
ref 'master'
tag false
started_at 'Di 29. Okt 09:51:28 CET 2013' started_at 'Di 29. Okt 09:51:28 CET 2013'
finished_at 'Di 29. Okt 09:53:28 CET 2013' finished_at 'Di 29. Okt 09:53:28 CET 2013'
commands 'ls -a' commands 'ls -a'
...@@ -43,5 +45,9 @@ FactoryGirl.define do ...@@ -43,5 +45,9 @@ FactoryGirl.define do
started_at nil started_at nil
finished_at nil finished_at nil
end end
factory :ci_build_tag do
tag true
end
end end
end end
...@@ -17,60 +17,32 @@ ...@@ -17,60 +17,32 @@
# Read about factories at https://github.com/thoughtbot/factory_girl # Read about factories at https://github.com/thoughtbot/factory_girl
FactoryGirl.define do FactoryGirl.define do
factory :ci_commit, class: Ci::Commit do factory :ci_empty_commit, class: Ci::Commit do
ref 'master'
before_sha '76de212e80737a608d939f648d959671fb0a0142'
sha '97de212e80737a608d939f648d959671fb0a0142' sha '97de212e80737a608d939f648d959671fb0a0142'
push_data do
{
ref: 'refs/heads/master',
before: '76de212e80737a608d939f648d959671fb0a0142',
after: '97de212e80737a608d939f648d959671fb0a0142',
user_name: 'Git User',
user_email: 'git@example.com',
repository: {
name: 'test-data',
url: 'ssh://git@gitlab.com/test/test-data.git',
description: '',
homepage: 'http://gitlab.com/test/test-data'
},
commits: [
{
id: '97de212e80737a608d939f648d959671fb0a0142',
message: 'Test commit message',
timestamp: '2014-09-23T13:12:25+02:00',
url: 'https://gitlab.com/test/test-data/commit/97de212e80737a608d939f648d959671fb0a0142',
author: {
name: 'Git User',
email: 'git@user.com'
}
}
],
total_commits_count: 1,
ci_yaml_file: File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml'))
}
end
gl_project factory: :empty_project gl_project factory: :empty_project
factory :ci_commit_without_jobs do factory :ci_commit_without_jobs do
after(:create) do |commit, evaluator| after(:build) do |commit|
commit.push_data[:ci_yaml_file] = YAML.dump({}) allow(commit).to receive(:ci_yaml_file) { YAML.dump({}) }
commit.save
end end
end end
factory :ci_commit_with_one_job do factory :ci_commit_with_one_job do
after(:create) do |commit, evaluator| after(:build) do |commit|
commit.push_data[:ci_yaml_file] = YAML.dump({ rspec: { script: "ls" } }) allow(commit).to receive(:ci_yaml_file) { YAML.dump({ rspec: { script: "ls" } }) }
commit.save
end end
end end
factory :ci_commit_with_two_jobs do factory :ci_commit_with_two_jobs do
after(:create) do |commit, evaluator| after(:build) do |commit|
commit.push_data[:ci_yaml_file] = YAML.dump({ rspec: { script: "ls" }, spinach: { script: "ls" } }) allow(commit).to receive(:ci_yaml_file) { YAML.dump({ rspec: { script: "ls" }, spinach: { script: "ls" } }) }
commit.save end
end
factory :ci_commit do
after(:build) do |commit|
allow(commit).to receive(:ci_yaml_file) { File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml')) }
end end
end end
end end
......
...@@ -11,6 +11,10 @@ describe "Commits" do ...@@ -11,6 +11,10 @@ describe "Commits" do
@commit.project.gl_project.team << [@user, :master] @commit.project.gl_project.team << [@user, :master]
end end
before do
stub_ci_commit_to_return_yaml_file
end
describe "GET /:project/commits/:sha" do describe "GET /:project/commits/:sha" do
before do before do
visit ci_commit_path(@commit) visit ci_commit_path(@commit)
...@@ -38,8 +42,7 @@ describe "Commits" do ...@@ -38,8 +42,7 @@ describe "Commits" do
end end
it "shows warning" do it "shows warning" do
@commit.push_data[:ci_yaml_file] = nil stub_ci_commit_yaml_file(nil)
@commit.save
visit ci_commit_path(@commit) visit ci_commit_path(@commit)
......
...@@ -17,11 +17,12 @@ module Ci ...@@ -17,11 +17,12 @@ module Ci
expect(config_processor.builds_for_stage_and_ref(type, "master").size).to eq(1) expect(config_processor.builds_for_stage_and_ref(type, "master").size).to eq(1)
expect(config_processor.builds_for_stage_and_ref(type, "master").first).to eq({ expect(config_processor.builds_for_stage_and_ref(type, "master").first).to eq({
stage: "test", stage: "test",
stage_idx: 1,
except: nil, except: nil,
name: :rspec, name: :rspec,
only: nil, only: nil,
script: "pwd\nrspec", commands: "pwd\nrspec",
tags: [], tag_list: [],
options: {}, options: {},
allow_failure: false allow_failure: false
}) })
...@@ -115,10 +116,11 @@ module Ci ...@@ -115,10 +116,11 @@ module Ci
expect(config_processor.builds_for_stage_and_ref("test", "master").first).to eq({ expect(config_processor.builds_for_stage_and_ref("test", "master").first).to eq({
except: nil, except: nil,
stage: "test", stage: "test",
stage_idx: 1,
name: :rspec, name: :rspec,
only: nil, only: nil,
script: "pwd\nrspec", commands: "pwd\nrspec",
tags: [], tag_list: [],
options: { options: {
image: "ruby:2.1", image: "ruby:2.1",
services: ["mysql"] services: ["mysql"]
...@@ -141,10 +143,11 @@ module Ci ...@@ -141,10 +143,11 @@ module Ci
expect(config_processor.builds_for_stage_and_ref("test", "master").first).to eq({ expect(config_processor.builds_for_stage_and_ref("test", "master").first).to eq({
except: nil, except: nil,
stage: "test", stage: "test",
stage_idx: 1,
name: :rspec, name: :rspec,
only: nil, only: nil,
script: "pwd\nrspec", commands: "pwd\nrspec",
tags: [], tag_list: [],
options: { options: {
image: "ruby:2.5", image: "ruby:2.5",
services: ["postgresql"] services: ["postgresql"]
......
...@@ -30,9 +30,12 @@ describe Ci::Build do ...@@ -30,9 +30,12 @@ describe Ci::Build do
let(:gl_project) { FactoryGirl.create :empty_project, gitlab_ci_project: project } let(:gl_project) { FactoryGirl.create :empty_project, gitlab_ci_project: project }
let(:commit) { FactoryGirl.create :ci_commit, gl_project: gl_project } let(:commit) { FactoryGirl.create :ci_commit, gl_project: gl_project }
let(:build) { FactoryGirl.create :ci_build, commit: commit } let(:build) { FactoryGirl.create :ci_build, commit: commit }
subject { build }
it { is_expected.to belong_to(:commit) } 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 :status }
it { is_expected.to validate_presence_of :ref }
it { is_expected.to respond_to :success? } it { is_expected.to respond_to :success? }
it { is_expected.to respond_to :failed? } it { is_expected.to respond_to :failed? }
...@@ -236,12 +239,6 @@ describe Ci::Build do ...@@ -236,12 +239,6 @@ describe Ci::Build do
it { is_expected.to eq(options) } it { is_expected.to eq(options) }
end end
describe :ref do
subject { build.ref }
it { is_expected.to eq(commit.ref) }
end
describe :sha do describe :sha do
subject { build.sha } subject { build.sha }
...@@ -254,12 +251,6 @@ describe Ci::Build do ...@@ -254,12 +251,6 @@ describe Ci::Build do
it { is_expected.to eq(commit.short_sha) } it { is_expected.to eq(commit.short_sha) }
end end
describe :before_sha do
subject { build.before_sha }
it { is_expected.to eq(commit.before_sha) }
end
describe :allow_git_fetch do describe :allow_git_fetch do
subject { build.allow_git_fetch } subject { build.allow_git_fetch }
...@@ -359,4 +350,38 @@ describe Ci::Build do ...@@ -359,4 +350,38 @@ describe Ci::Build do
end end
end end
end end
describe :project_recipients do
let(:pusher_email) { 'pusher@gitlab.test' }
let(:user) { User.new(notification_email: pusher_email) }
subject { build.project_recipients }
before do
build.update_attributes(user: user)
end
it 'should return pusher_email as only recipient when no additional recipients are given' do
project.update_attributes(email_add_pusher: true,
email_recipients: '')
is_expected.to eq([pusher_email])
end
it 'should return pusher_email and additional recipients' do
project.update_attributes(email_add_pusher: true,
email_recipients: 'rec1 rec2')
is_expected.to eq(['rec1', 'rec2', pusher_email])
end
it 'should return recipients' do
project.update_attributes(email_add_pusher: false,
email_recipients: 'rec1 rec2')
is_expected.to eq(['rec1', 'rec2'])
end
it 'should return unique recipients only' do
project.update_attributes(email_add_pusher: true,
email_recipients: "rec1 rec1 #{pusher_email}")
is_expected.to eq(['rec1', pusher_email])
end
end
end end
This diff is collapsed.
...@@ -3,38 +3,6 @@ require 'spec_helper' ...@@ -3,38 +3,6 @@ require 'spec_helper'
describe Ci::HipChatMessage do describe Ci::HipChatMessage do
subject { Ci::HipChatMessage.new(build) } subject { Ci::HipChatMessage.new(build) }
context "One build" do
let(:commit) { FactoryGirl.create(:ci_commit_with_one_job) }
let(:build) do
commit.create_builds
commit.builds.first
end
context 'when build succeeds' do
it 'returns a successful message' do
build.update(status: "success")
expect( subject.status_color ).to eq 'green'
expect( subject.notify? ).to be_falsey
expect( subject.to_s ).to match(/Build '[^']+' #\d+/)
expect( subject.to_s ).to match(/Successful in \d+ second\(s\)\./)
end
end
context 'when build fails' do
it 'returns a failure message' do
build.update(status: "failed")
expect( subject.status_color ).to eq 'red'
expect( subject.notify? ).to be_truthy
expect( subject.to_s ).to match(/Build '[^']+' #\d+/)
expect( subject.to_s ).to match(/Failed in \d+ second\(s\)\./)
end
end
end
context "Several builds" do
let(:commit) { FactoryGirl.create(:ci_commit_with_two_jobs) } let(:commit) { FactoryGirl.create(:ci_commit_with_two_jobs) }
let(:build) do let(:build) do
...@@ -43,30 +11,29 @@ describe Ci::HipChatMessage do ...@@ -43,30 +11,29 @@ describe Ci::HipChatMessage do
context 'when all matrix builds succeed' do context 'when all matrix builds succeed' do
it 'returns a successful message' do it 'returns a successful message' do
commit.create_builds commit.create_builds('master', false, nil)
commit.builds.update_all(status: "success") commit.builds.update_all(status: "success")
commit.reload commit.reload
expect( subject.status_color ).to eq 'green' expect(subject.status_color).to eq 'green'
expect( subject.notify? ).to be_falsey expect(subject.notify?).to be_falsey
expect( subject.to_s ).to match(/Commit #\d+/) expect(subject.to_s).to match(/Commit #\d+/)
expect( subject.to_s ).to match(/Successful in \d+ second\(s\)\./) expect(subject.to_s).to match(/Successful in \d+ second\(s\)\./)
end end
end end
context 'when at least one matrix build fails' do context 'when at least one matrix build fails' do
it 'returns a failure message' do it 'returns a failure message' do
commit.create_builds commit.create_builds('master', false, nil)
first_build = commit.builds.first first_build = commit.builds.first
second_build = commit.builds.last second_build = commit.builds.last
first_build.update(status: "success") first_build.update(status: "success")
second_build.update(status: "failed") second_build.update(status: "failed")
expect( subject.status_color ).to eq 'red' expect(subject.status_color).to eq 'red'
expect( subject.notify? ).to be_truthy expect(subject.notify?).to be_truthy
expect( subject.to_s ).to match(/Commit #\d+/) expect(subject.to_s).to match(/Commit #\d+/)
expect( subject.to_s ).to match(/Failed in \d+ second\(s\)\./) expect(subject.to_s).to match(/Failed in \d+ second\(s\)\./)
end
end end
end end
end end
...@@ -29,12 +29,13 @@ describe Ci::MailService do ...@@ -29,12 +29,13 @@ describe Ci::MailService do
describe 'Sends email for' do describe 'Sends email for' do
let(:mail) { Ci::MailService.new } let(:mail) { Ci::MailService.new }
let(:user) { User.new(notification_email: 'git@example.com')}
describe 'failed build' do describe 'failed build' do
let(:project) { FactoryGirl.create(:ci_project, email_add_pusher: true) } let(:project) { FactoryGirl.create(:ci_project, email_add_pusher: true) }
let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) } let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) }
let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) } let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) }
let(:build) { FactoryGirl.create(:ci_build, status: :failed, commit: commit) } let(:build) { FactoryGirl.create(:ci_build, status: :failed, commit: commit, user: user) }
before do before do
allow(mail).to receive_messages( allow(mail).to receive_messages(
...@@ -57,7 +58,7 @@ describe Ci::MailService do ...@@ -57,7 +58,7 @@ describe Ci::MailService do
let(:project) { FactoryGirl.create(:ci_project, email_add_pusher: true, email_only_broken_builds: false) } 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(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) }
let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) } let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) }
let(:build) { FactoryGirl.create(:ci_build, status: :success, commit: commit) } let(:build) { FactoryGirl.create(:ci_build, status: :success, commit: commit, user: user) }
before do before do
allow(mail).to receive_messages( allow(mail).to receive_messages(
...@@ -85,7 +86,7 @@ describe Ci::MailService do ...@@ -85,7 +86,7 @@ describe Ci::MailService do
end end
let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) } let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) }
let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) } let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) }
let(:build) { FactoryGirl.create(:ci_build, status: :success, commit: commit) } let(:build) { FactoryGirl.create(:ci_build, status: :success, commit: commit, user: user) }
before do before do
allow(mail).to receive_messages( allow(mail).to receive_messages(
...@@ -114,7 +115,7 @@ describe Ci::MailService do ...@@ -114,7 +115,7 @@ describe Ci::MailService do
end end
let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) } let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) }
let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) } let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) }
let(:build) { FactoryGirl.create(:ci_build, status: :success, commit: commit) } let(:build) { FactoryGirl.create(:ci_build, status: :success, commit: commit, user: user) }
before do before do
allow(mail).to receive_messages( allow(mail).to receive_messages(
...@@ -143,7 +144,7 @@ describe Ci::MailService do ...@@ -143,7 +144,7 @@ describe Ci::MailService do
end end
let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) } let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) }
let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) } let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) }
let(:build) { FactoryGirl.create(:ci_build, status: :success, commit: commit) } let(:build) { FactoryGirl.create(:ci_build, status: :success, commit: commit, user: user) }
before do before do
allow(mail).to receive_messages( allow(mail).to receive_messages(
...@@ -166,7 +167,7 @@ describe Ci::MailService do ...@@ -166,7 +167,7 @@ describe Ci::MailService do
end end
let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) } let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) }
let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) } let(:commit) { FactoryGirl.create(:ci_commit, gl_project: gl_project) }
let(:build) { FactoryGirl.create(:ci_build, status: :failed, commit: commit) } let(:build) { FactoryGirl.create(:ci_build, status: :failed, commit: commit, user: user) }
before do before do
allow(mail).to receive_messages( allow(mail).to receive_messages(
......
...@@ -3,51 +3,13 @@ require 'spec_helper' ...@@ -3,51 +3,13 @@ require 'spec_helper'
describe Ci::SlackMessage do describe Ci::SlackMessage do
subject { Ci::SlackMessage.new(commit) } subject { Ci::SlackMessage.new(commit) }
context "One build" do
let(:commit) { FactoryGirl.create(:ci_commit_with_one_job) }
let(:build) do
commit.create_builds
commit.builds.first
end
context 'when build succeeded' do
let(:color) { 'good' }
it 'returns a message with succeeded build' do
build.update(status: "success")
expect(subject.color).to eq(color)
expect(subject.fallback).to include('Build')
expect(subject.fallback).to include("\##{build.id}")
expect(subject.fallback).to include('succeeded')
expect(subject.attachments.first[:fields]).to be_empty
end
end
context 'when build failed' do
let(:color) { 'danger' }
it 'returns a message with failed build' do
build.update(status: "failed")
expect(subject.color).to eq(color)
expect(subject.fallback).to include('Build')
expect(subject.fallback).to include("\##{build.id}")
expect(subject.fallback).to include('failed')
expect(subject.attachments.first[:fields]).to be_empty
end
end
end
context "Several builds" do
let(:commit) { FactoryGirl.create(:ci_commit_with_two_jobs) } let(:commit) { FactoryGirl.create(:ci_commit_with_two_jobs) }
context 'when all matrix builds succeeded' do context 'when all matrix builds succeeded' do
let(:color) { 'good' } let(:color) { 'good' }
it 'returns a message with success' do it 'returns a message with success' do
commit.create_builds commit.create_builds('master', false, nil)
commit.builds.update_all(status: "success") commit.builds.update_all(status: "success")
commit.reload commit.reload
...@@ -63,7 +25,7 @@ describe Ci::SlackMessage do ...@@ -63,7 +25,7 @@ describe Ci::SlackMessage do
let(:color) { 'danger' } let(:color) { 'danger' }
it 'returns a message with information about failed build' do it 'returns a message with information about failed build' do
commit.create_builds commit.create_builds('master', false, nil)
first_build = commit.builds.first first_build = commit.builds.first
second_build = commit.builds.last second_build = commit.builds.last
first_build.update(status: "success") first_build.update(status: "success")
...@@ -78,5 +40,4 @@ describe Ci::SlackMessage do ...@@ -78,5 +40,4 @@ describe Ci::SlackMessage do
expect(subject.attachments.first[:fields].first[:value]).to include("\##{second_build.id}") expect(subject.attachments.first[:fields].first[:value]).to include("\##{second_build.id}")
end end
end end
end
end end
...@@ -39,8 +39,8 @@ describe GitlabCiService do ...@@ -39,8 +39,8 @@ describe GitlabCiService do
end end
describe :build_page do describe :build_page do
it { expect(@service.build_page("2ab7834c", 'master')).to eq("http://localhost/ci/projects/#{@ci_project.id}/refs/master/commits/2ab7834c")} it { expect(@service.build_page("2ab7834c", 'master')).to eq("http://localhost/ci/projects/#{@ci_project.id}/commits/2ab7834c")}
it { expect(@service.build_page("issue#2", 'master')).to eq("http://localhost/ci/projects/#{@ci_project.id}/refs/master/commits/issue%232")} it { expect(@service.build_page("issue#2", 'master')).to eq("http://localhost/ci/projects/#{@ci_project.id}/commits/issue%232")}
end end
describe "execute" do describe "execute" do
...@@ -48,8 +48,8 @@ describe GitlabCiService do ...@@ -48,8 +48,8 @@ describe GitlabCiService do
let(:project) { create(:project, name: 'project') } let(:project) { create(:project, name: 'project') }
let(:push_sample_data) { Gitlab::PushDataBuilder.build_sample(project, user) } let(:push_sample_data) { Gitlab::PushDataBuilder.build_sample(project, user) }
it "calls ci_yaml_file" do it "calls CreateCommitService" do
expect(@service).to receive(:ci_yaml_file).with(push_sample_data[:checkout_sha]) expect_any_instance_of(Ci::CreateCommitService).to receive(:execute).with(@ci_project, user, push_sample_data)
@service.execute(push_sample_data) @service.execute(push_sample_data)
end end
......
...@@ -7,6 +7,10 @@ describe Ci::API::API do ...@@ -7,6 +7,10 @@ describe Ci::API::API do
let(:project) { FactoryGirl.create(:ci_project) } let(:project) { FactoryGirl.create(:ci_project) }
let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) } let(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) }
before do
stub_ci_commit_to_return_yaml_file
end
describe "Builds API for runners" do describe "Builds API for runners" do
let(:shared_runner) { FactoryGirl.create(:ci_runner, token: "SharedRunner") } let(:shared_runner) { FactoryGirl.create(:ci_runner, token: "SharedRunner") }
let(:shared_project) { FactoryGirl.create(:ci_project, name: "SharedProject") } let(:shared_project) { FactoryGirl.create(:ci_project, name: "SharedProject") }
...@@ -19,7 +23,7 @@ describe Ci::API::API do ...@@ -19,7 +23,7 @@ describe Ci::API::API do
describe "POST /builds/register" do describe "POST /builds/register" do
it "should start a build" do it "should start a build" do
commit = FactoryGirl.create(:ci_commit, gl_project: gl_project) commit = FactoryGirl.create(:ci_commit, gl_project: gl_project)
commit.create_builds commit.create_builds('master', false, nil)
build = commit.builds.first build = commit.builds.first
post ci_api("/builds/register"), token: runner.token, info: { platform: :darwin } post ci_api("/builds/register"), token: runner.token, info: { platform: :darwin }
...@@ -55,7 +59,7 @@ describe Ci::API::API do ...@@ -55,7 +59,7 @@ describe Ci::API::API do
it "returns options" do it "returns options" do
commit = FactoryGirl.create(:ci_commit, gl_project: gl_project) commit = FactoryGirl.create(:ci_commit, gl_project: gl_project)
commit.create_builds commit.create_builds('master', false, nil)
post ci_api("/builds/register"), token: runner.token, info: { platform: :darwin } post ci_api("/builds/register"), token: runner.token, info: { platform: :darwin }
...@@ -65,7 +69,7 @@ describe Ci::API::API do ...@@ -65,7 +69,7 @@ describe Ci::API::API do
it "returns variables" do it "returns variables" do
commit = FactoryGirl.create(:ci_commit, gl_project: gl_project) commit = FactoryGirl.create(:ci_commit, gl_project: gl_project)
commit.create_builds commit.create_builds('master', false, nil)
project.variables << Ci::Variable.new(key: "SECRET_KEY", value: "secret_value") project.variables << Ci::Variable.new(key: "SECRET_KEY", value: "secret_value")
post ci_api("/builds/register"), token: runner.token, info: { platform: :darwin } post ci_api("/builds/register"), token: runner.token, info: { platform: :darwin }
...@@ -82,7 +86,7 @@ describe Ci::API::API do ...@@ -82,7 +86,7 @@ describe Ci::API::API do
commit = FactoryGirl.create(:ci_commit, gl_project: gl_project) commit = FactoryGirl.create(:ci_commit, gl_project: gl_project)
trigger_request = FactoryGirl.create(:ci_trigger_request_with_variables, commit: commit, trigger: trigger) trigger_request = FactoryGirl.create(:ci_trigger_request_with_variables, commit: commit, trigger: trigger)
commit.create_builds(trigger_request) commit.create_builds('master', false, nil, trigger_request)
project.variables << Ci::Variable.new(key: "SECRET_KEY", value: "secret_value") project.variables << Ci::Variable.new(key: "SECRET_KEY", value: "secret_value")
post ci_api("/builds/register"), token: runner.token, info: { platform: :darwin } post ci_api("/builds/register"), token: runner.token, info: { platform: :darwin }
......
...@@ -44,8 +44,7 @@ describe Ci::API::API, 'Commits' do ...@@ -44,8 +44,7 @@ describe Ci::API::API, 'Commits' do
"email" => "jordi@softcatala.org", "email" => "jordi@softcatala.org",
} }
} }
], ]
ci_yaml_file: gitlab_ci_yaml
} }
end end
......
...@@ -5,8 +5,8 @@ describe Ci::API::API do ...@@ -5,8 +5,8 @@ describe Ci::API::API do
describe 'POST /projects/:project_id/refs/:ref/trigger' do describe 'POST /projects/:project_id/refs/:ref/trigger' do
let!(:trigger_token) { 'secure token' } let!(:trigger_token) { 'secure token' }
let!(:project) { FactoryGirl.create(:ci_project) } let!(:gl_project) { FactoryGirl.create(:project) }
let!(:gl_project) { FactoryGirl.create(:empty_project, gitlab_ci_project: project) } let!(:project) { FactoryGirl.create(:ci_project, gl_project: gl_project) }
let!(:project2) { FactoryGirl.create(:ci_project) } let!(:project2) { FactoryGirl.create(:ci_project) }
let!(:trigger) { FactoryGirl.create(:ci_trigger, project: project, token: trigger_token) } let!(:trigger) { FactoryGirl.create(:ci_trigger, project: project, token: trigger_token) }
let(:options) do let(:options) do
...@@ -15,6 +15,10 @@ describe Ci::API::API do ...@@ -15,6 +15,10 @@ describe Ci::API::API do
} }
end end
before do
stub_ci_commit_to_return_yaml_file
end
context 'Handles errors' do context 'Handles errors' do
it 'should return bad request if token is missing' do it 'should return bad request if token is missing' do
post ci_api("/projects/#{project.id}/refs/master/trigger") post ci_api("/projects/#{project.id}/refs/master/trigger")
...@@ -33,15 +37,13 @@ describe Ci::API::API do ...@@ -33,15 +37,13 @@ describe Ci::API::API do
end end
context 'Have a commit' do context 'Have a commit' do
before do let(:commit) { project.commits.last }
@commit = FactoryGirl.create(:ci_commit, gl_project: gl_project)
end
it 'should create builds' do it 'should create builds' do
post ci_api("/projects/#{project.id}/refs/master/trigger"), options post ci_api("/projects/#{project.id}/refs/master/trigger"), options
expect(response.status).to eq(201) expect(response.status).to eq(201)
@commit.builds.reload commit.builds.reload
expect(@commit.builds.size).to eq(2) expect(commit.builds.size).to eq(2)
end end
it 'should return bad request with no builds created if there\'s no commit for that ref' do it 'should return bad request with no builds created if there\'s no commit for that ref' do
...@@ -70,8 +72,8 @@ describe Ci::API::API do ...@@ -70,8 +72,8 @@ describe Ci::API::API do
it 'create trigger request with variables' do it 'create trigger request with variables' do
post ci_api("/projects/#{project.id}/refs/master/trigger"), options.merge(variables: variables) post ci_api("/projects/#{project.id}/refs/master/trigger"), options.merge(variables: variables)
expect(response.status).to eq(201) expect(response.status).to eq(201)
@commit.builds.reload commit.builds.reload
expect(@commit.builds.first.trigger_request.variables).to eq(variables) expect(commit.builds.first.trigger_request.variables).to eq(variables)
end end
end end
end end
......
...@@ -7,7 +7,7 @@ describe "Commits" do ...@@ -7,7 +7,7 @@ describe "Commits" do
describe "GET /:project/refs/:ref_name/commits/:id/status.json" do describe "GET /:project/refs/:ref_name/commits/:id/status.json" do
before do before do
get status_ci_project_ref_commits_path(@commit.project, @commit.ref, @commit.sha), format: :json get status_ci_project_commits_path(@commit.project, @commit.sha), format: :json
end end
it { expect(response.status).to eq(200) } it { expect(response.status).to eq(200) }
......
...@@ -4,15 +4,19 @@ module Ci ...@@ -4,15 +4,19 @@ module Ci
describe CreateCommitService do describe CreateCommitService do
let(:service) { CreateCommitService.new } let(:service) { CreateCommitService.new }
let(:project) { FactoryGirl.create(:ci_project) } let(:project) { FactoryGirl.create(:ci_project) }
let(:user) { nil }
before do
stub_ci_commit_to_return_yaml_file
end
describe :execute do describe :execute do
context 'valid params' do context 'valid params' do
let(:commit) do let(:commit) do
service.execute(project, service.execute(project, user,
ref: 'refs/heads/master', ref: 'refs/heads/master',
before: '00000000', before: '00000000',
after: '31das312', after: '31das312',
ci_yaml_file: gitlab_ci_yaml,
commits: [ { message: "Message" } ] commits: [ { message: "Message" } ]
) )
end end
...@@ -26,11 +30,10 @@ module Ci ...@@ -26,11 +30,10 @@ module Ci
context "skip tag if there is no build for it" do context "skip tag if there is no build for it" do
it "creates commit if there is appropriate job" do it "creates commit if there is appropriate job" do
result = service.execute(project, result = service.execute(project, user,
ref: 'refs/tags/0_1', ref: 'refs/tags/0_1',
before: '00000000', before: '00000000',
after: '31das312', after: '31das312',
ci_yaml_file: gitlab_ci_yaml,
commits: [ { message: "Message" } ] commits: [ { message: "Message" } ]
) )
expect(result).to be_persisted expect(result).to be_persisted
...@@ -38,12 +41,12 @@ module Ci ...@@ -38,12 +41,12 @@ module Ci
it "creates commit if there is no appropriate job but deploy job has right ref setting" do it "creates commit if there is no appropriate job but deploy job has right ref setting" do
config = YAML.dump({ deploy: { deploy: "ls", only: ["0_1"] } }) config = YAML.dump({ deploy: { deploy: "ls", only: ["0_1"] } })
stub_ci_commit_yaml_file(config)
result = service.execute(project, result = service.execute(project, user,
ref: 'refs/heads/0_1', ref: 'refs/heads/0_1',
before: '00000000', before: '00000000',
after: '31das312', after: '31das312',
ci_yaml_file: config,
commits: [ { message: "Message" } ] commits: [ { message: "Message" } ]
) )
expect(result).to be_persisted expect(result).to be_persisted
...@@ -51,11 +54,11 @@ module Ci ...@@ -51,11 +54,11 @@ module Ci
end end
it 'fails commits without .gitlab-ci.yml' do it 'fails commits without .gitlab-ci.yml' do
result = service.execute(project, stub_ci_commit_yaml_file(nil)
result = service.execute(project, user,
ref: 'refs/heads/0_1', ref: 'refs/heads/0_1',
before: '00000000', before: '00000000',
after: '31das312', after: '31das312',
ci_yaml_file: config,
commits: [ { message: 'Message' } ] commits: [ { message: 'Message' } ]
) )
expect(result).to be_persisted expect(result).to be_persisted
...@@ -64,41 +67,46 @@ module Ci ...@@ -64,41 +67,46 @@ module Ci
end end
describe :ci_skip? do describe :ci_skip? do
let(:message) { "some message[ci skip]" }
before do
allow_any_instance_of(Ci::Commit).to receive(:git_commit_message) { message }
end
it "skips builds creation if there is [ci skip] tag in commit message" do it "skips builds creation if there is [ci skip] tag in commit message" do
commits = [{ message: "some message[ci skip]" }] commits = [{ message: message }]
commit = service.execute(project, commit = service.execute(project, user,
ref: 'refs/tags/0_1', ref: 'refs/tags/0_1',
before: '00000000', before: '00000000',
after: '31das312', after: '31das312',
commits: commits, commits: commits
ci_yaml_file: gitlab_ci_yaml
) )
expect(commit.builds.any?).to be false expect(commit.builds.any?).to be false
expect(commit.status).to eq("skipped") expect(commit.status).to eq("skipped")
end end
it "does not skips builds creation if there is no [ci skip] tag in commit message" do it "does not skips builds creation if there is no [ci skip] tag in commit message" do
commits = [{ message: "some message" }] allow_any_instance_of(Ci::Commit).to receive(:git_commit_message) { "some message" }
commit = service.execute(project, commits = [{ message: "some message" }]
commit = service.execute(project, user,
ref: 'refs/tags/0_1', ref: 'refs/tags/0_1',
before: '00000000', before: '00000000',
after: '31das312', after: '31das312',
commits: commits, commits: commits
ci_yaml_file: gitlab_ci_yaml
) )
expect(commit.builds.first.name).to eq("staging") expect(commit.builds.first.name).to eq("staging")
end end
it "skips builds creation if there is [ci skip] tag in commit message and yaml is invalid" do it "skips builds creation if there is [ci skip] tag in commit message and yaml is invalid" do
commits = [{ message: "some message[ci skip]" }] stub_ci_commit_yaml_file('invalid: file')
commit = service.execute(project, commits = [{ message: message }]
commit = service.execute(project, user,
ref: 'refs/tags/0_1', ref: 'refs/tags/0_1',
before: '00000000', before: '00000000',
after: '31das312', after: '31das312',
commits: commits, commits: commits
ci_yaml_file: "invalid: file"
) )
expect(commit.builds.any?).to be false expect(commit.builds.any?).to be false
expect(commit.status).to eq("skipped") expect(commit.status).to eq("skipped")
...@@ -106,35 +114,36 @@ module Ci ...@@ -106,35 +114,36 @@ module Ci
end end
it "skips build creation if there are already builds" do it "skips build creation if there are already builds" do
allow_any_instance_of(Ci::Commit).to receive(:ci_yaml_file) { gitlab_ci_yaml }
commits = [{ message: "message" }] commits = [{ message: "message" }]
commit = service.execute(project, commit = service.execute(project, user,
ref: 'refs/heads/master', ref: 'refs/heads/master',
before: '00000000', before: '00000000',
after: '31das312', after: '31das312',
commits: commits, commits: commits
ci_yaml_file: gitlab_ci_yaml
) )
expect(commit.builds.count(:all)).to eq(2) expect(commit.builds.count(:all)).to eq(2)
commit = service.execute(project, commit = service.execute(project, user,
ref: 'refs/heads/master', ref: 'refs/heads/master',
before: '00000000', before: '00000000',
after: '31das312', after: '31das312',
commits: commits, commits: commits
ci_yaml_file: gitlab_ci_yaml
) )
expect(commit.builds.count(:all)).to eq(2) expect(commit.builds.count(:all)).to eq(2)
end end
it "creates commit with failed status if yaml is invalid" do it "creates commit with failed status if yaml is invalid" do
stub_ci_commit_yaml_file('invalid: file')
commits = [{ message: "some message" }] commits = [{ message: "some message" }]
commit = service.execute(project, commit = service.execute(project, user,
ref: 'refs/tags/0_1', ref: 'refs/tags/0_1',
before: '00000000', before: '00000000',
after: '31das312', after: '31das312',
commits: commits, commits: commits
ci_yaml_file: "invalid: file"
) )
expect(commit.status).to eq("failed") expect(commit.status).to eq("failed")
......
...@@ -2,20 +2,20 @@ require 'spec_helper' ...@@ -2,20 +2,20 @@ require 'spec_helper'
describe Ci::CreateTriggerRequestService do describe Ci::CreateTriggerRequestService do
let(:service) { Ci::CreateTriggerRequestService.new } let(:service) { Ci::CreateTriggerRequestService.new }
let(:project) { FactoryGirl.create :ci_project } let(:gl_project) { create(:project) }
let(:gl_project) { FactoryGirl.create :empty_project, gitlab_ci_project: project } let(:project) { create(:ci_project, gl_project: gl_project) }
let(:trigger) { FactoryGirl.create :ci_trigger, project: project } let(:trigger) { create(:ci_trigger, project: project) }
before do
stub_ci_commit_to_return_yaml_file
end
describe :execute do describe :execute do
context 'valid params' do context 'valid params' do
subject { service.execute(project, trigger, 'master') } subject { service.execute(project, trigger, 'master') }
before do
@commit = FactoryGirl.create :ci_commit, gl_project: gl_project
end
it { expect(subject).to be_kind_of(Ci::TriggerRequest) } it { expect(subject).to be_kind_of(Ci::TriggerRequest) }
it { expect(subject.commit).to eq(@commit) } it { expect(subject.builds.first).to be_kind_of(Ci::Build) }
end end
context 'no commit for ref' do context 'no commit for ref' do
...@@ -28,26 +28,11 @@ describe Ci::CreateTriggerRequestService do ...@@ -28,26 +28,11 @@ describe Ci::CreateTriggerRequestService do
subject { service.execute(project, trigger, 'master') } subject { service.execute(project, trigger, 'master') }
before do before do
FactoryGirl.create :ci_commit_without_jobs, gl_project: gl_project stub_ci_commit_yaml_file('{}')
FactoryGirl.create :ci_commit, gl_project: gl_project
end end
it { expect(subject).to be_nil } it { expect(subject).to be_nil }
end end
context 'for multiple commits' do
subject { service.execute(project, trigger, 'master') }
before do
@commit1 = FactoryGirl.create :ci_commit, committed_at: 2.hour.ago, gl_project: gl_project
@commit2 = FactoryGirl.create :ci_commit, committed_at: 1.hour.ago, gl_project: gl_project
@commit3 = FactoryGirl.create :ci_commit, committed_at: 3.hour.ago, gl_project: gl_project
end
context 'retries latest one' do
it { expect(subject).to be_kind_of(Ci::TriggerRequest) }
it { expect(subject).to be_persisted }
it { expect(subject.commit).to eq(@commit2) }
end
end
end end
end end
...@@ -43,4 +43,8 @@ RSpec.configure do |config| ...@@ -43,4 +43,8 @@ RSpec.configure do |config|
end end
end end
FactoryGirl::SyntaxRunner.class_eval do
include RSpec::Mocks::ExampleMethods
end
ActiveRecord::Migration.maintain_test_schema! ActiveRecord::Migration.maintain_test_schema!
...@@ -13,6 +13,14 @@ module StubGitlabCalls ...@@ -13,6 +13,14 @@ module StubGitlabCalls
allow_any_instance_of(Network).to receive(:projects) { project_hash_array } allow_any_instance_of(Network).to receive(:projects) { project_hash_array }
end end
def stub_ci_commit_to_return_yaml_file
stub_ci_commit_yaml_file(gitlab_ci_yaml)
end
def stub_ci_commit_yaml_file(ci_yaml)
allow_any_instance_of(Ci::Commit).to receive(:ci_yaml_file) { ci_yaml }
end
private private
def gitlab_url def gitlab_url
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment