2015-08-25 21:42:46 -04:00
|
|
|
# == Schema Information
|
|
|
|
#
|
|
|
|
# Table name: projects
|
|
|
|
#
|
|
|
|
# id :integer not null, primary key
|
|
|
|
# name :string(255) not null
|
|
|
|
# timeout :integer default(3600), not null
|
|
|
|
# created_at :datetime
|
|
|
|
# updated_at :datetime
|
|
|
|
# token :string(255)
|
|
|
|
# default_ref :string(255)
|
|
|
|
# path :string(255)
|
|
|
|
# always_build :boolean default(FALSE), not null
|
|
|
|
# polling_interval :integer
|
|
|
|
# public :boolean default(FALSE), not null
|
|
|
|
# ssh_url_to_repo :string(255)
|
|
|
|
# gitlab_id :integer
|
|
|
|
# allow_git_fetch :boolean default(TRUE), not null
|
|
|
|
# email_recipients :string(255) default(""), not null
|
|
|
|
# email_add_pusher :boolean default(TRUE), not null
|
|
|
|
# email_only_broken_builds :boolean default(TRUE), not null
|
|
|
|
# skip_refs :string(255)
|
|
|
|
# coverage_regex :string(255)
|
|
|
|
# shared_runners_enabled :boolean default(FALSE)
|
|
|
|
# generated_yaml_config :text
|
|
|
|
#
|
|
|
|
|
|
|
|
module Ci
|
|
|
|
class Project < ActiveRecord::Base
|
|
|
|
extend Ci::Model
|
2015-09-11 06:52:56 -04:00
|
|
|
|
2015-08-25 21:42:46 -04:00
|
|
|
include Ci::ProjectStatus
|
|
|
|
|
2015-09-11 07:38:37 -04:00
|
|
|
belongs_to :gl_project, class_name: '::Project', foreign_key: :gitlab_id
|
2015-09-11 06:52:56 -04:00
|
|
|
|
2015-08-25 21:42:46 -04:00
|
|
|
has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject'
|
|
|
|
has_many :runners, through: :runner_projects, class_name: 'Ci::Runner'
|
|
|
|
has_many :web_hooks, dependent: :destroy, class_name: 'Ci::WebHook'
|
|
|
|
has_many :events, dependent: :destroy, class_name: 'Ci::Event'
|
|
|
|
has_many :variables, dependent: :destroy, class_name: 'Ci::Variable'
|
|
|
|
has_many :triggers, dependent: :destroy, class_name: 'Ci::Trigger'
|
|
|
|
|
|
|
|
# Project services
|
|
|
|
has_many :services, dependent: :destroy, class_name: 'Ci::Service'
|
|
|
|
has_one :hip_chat_service, dependent: :destroy, class_name: 'Ci::HipChatService'
|
|
|
|
has_one :slack_service, dependent: :destroy, class_name: 'Ci::SlackService'
|
|
|
|
has_one :mail_service, dependent: :destroy, class_name: 'Ci::MailService'
|
|
|
|
|
|
|
|
accepts_nested_attributes_for :variables, allow_destroy: true
|
|
|
|
|
2015-09-23 06:47:29 -04:00
|
|
|
delegate :name_with_namespace, :path_with_namespace, :web_url, :http_url_to_repo, :ssh_url_to_repo, to: :gl_project
|
|
|
|
|
2015-08-25 21:42:46 -04:00
|
|
|
#
|
|
|
|
# Validations
|
|
|
|
#
|
2015-09-23 06:47:29 -04:00
|
|
|
validates_presence_of :timeout, :token, :default_ref, :gitlab_id
|
2015-08-25 21:42:46 -04:00
|
|
|
|
|
|
|
validates_uniqueness_of :gitlab_id
|
|
|
|
|
|
|
|
validates :polling_interval,
|
2015-09-28 07:14:34 -04:00
|
|
|
presence: true,
|
|
|
|
if: ->(project) { project.always_build.present? }
|
2015-08-25 21:42:46 -04:00
|
|
|
|
|
|
|
before_validation :set_default_values
|
|
|
|
|
|
|
|
class << self
|
|
|
|
include Ci::CurrentSettings
|
|
|
|
|
|
|
|
def base_build_script
|
|
|
|
<<-eos
|
|
|
|
git submodule update --init
|
|
|
|
ls -la
|
|
|
|
eos
|
|
|
|
end
|
|
|
|
|
|
|
|
def parse(project)
|
|
|
|
params = {
|
2015-09-23 06:47:29 -04:00
|
|
|
gitlab_id: project.id,
|
|
|
|
default_ref: project.default_branch || 'master',
|
|
|
|
email_add_pusher: current_application_settings.add_pusher,
|
2015-08-25 21:42:46 -04:00
|
|
|
email_only_broken_builds: current_application_settings.all_broken_builds,
|
|
|
|
}
|
|
|
|
|
|
|
|
project = Ci::Project.new(params)
|
|
|
|
project.build_missing_services
|
|
|
|
project
|
|
|
|
end
|
|
|
|
|
|
|
|
def already_added?(project)
|
|
|
|
where(gitlab_id: project.id).any?
|
|
|
|
end
|
|
|
|
|
|
|
|
def unassigned(runner)
|
|
|
|
joins("LEFT JOIN #{Ci::RunnerProject.table_name} ON #{Ci::RunnerProject.table_name}.project_id = #{Ci::Project.table_name}.id " \
|
|
|
|
"AND #{Ci::RunnerProject.table_name}.runner_id = #{runner.id}").
|
2015-09-25 11:46:03 -04:00
|
|
|
where("#{Ci::RunnerProject.table_name}.project_id" => nil)
|
2015-08-25 21:42:46 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def ordered_by_last_commit_date
|
2015-09-28 09:18:25 -04:00
|
|
|
last_commit_subquery = "(SELECT gl_project_id, MAX(committed_at) committed_at FROM #{Ci::Commit.table_name} GROUP BY gl_project_id)"
|
|
|
|
joins("LEFT JOIN #{last_commit_subquery} AS last_commit ON #{Ci::Project.table_name}.gitlab_id = last_commit.gl_project_id").
|
2015-08-25 21:42:46 -04:00
|
|
|
order("CASE WHEN last_commit.committed_at IS NULL THEN 1 ELSE 0 END, last_commit.committed_at DESC")
|
|
|
|
end
|
2015-09-23 06:47:29 -04:00
|
|
|
end
|
2015-08-25 21:42:46 -04:00
|
|
|
|
2015-09-23 06:47:29 -04:00
|
|
|
def name
|
|
|
|
name_with_namespace
|
|
|
|
end
|
|
|
|
|
|
|
|
def path
|
|
|
|
path_with_namespace
|
|
|
|
end
|
|
|
|
|
|
|
|
def gitlab_url
|
|
|
|
web_url
|
2015-08-25 21:42:46 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def any_runners?
|
|
|
|
if runners.active.any?
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
shared_runners_enabled && Ci::Runner.shared.active.any?
|
|
|
|
end
|
|
|
|
|
|
|
|
def set_default_values
|
|
|
|
self.token = SecureRandom.hex(15) if self.token.blank?
|
2015-09-28 07:14:34 -04:00
|
|
|
self.default_ref ||= 'master'
|
2015-08-25 21:42:46 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def tracked_refs
|
2015-09-28 07:14:34 -04:00
|
|
|
@tracked_refs ||= default_ref.split(",").map { |ref| ref.strip }
|
2015-08-25 21:42:46 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def valid_token? token
|
|
|
|
self.token && self.token == token
|
|
|
|
end
|
|
|
|
|
|
|
|
def no_running_builds?
|
|
|
|
# Get running builds not later than 3 days ago to ignore hangs
|
|
|
|
builds.running.where("updated_at > ?", 3.days.ago).empty?
|
|
|
|
end
|
|
|
|
|
|
|
|
def email_notification?
|
|
|
|
email_add_pusher || email_recipients.present?
|
|
|
|
end
|
|
|
|
|
|
|
|
def web_hooks?
|
|
|
|
web_hooks.any?
|
|
|
|
end
|
|
|
|
|
|
|
|
def services?
|
|
|
|
services.any?
|
|
|
|
end
|
|
|
|
|
|
|
|
def timeout_in_minutes
|
|
|
|
timeout / 60
|
|
|
|
end
|
|
|
|
|
|
|
|
def timeout_in_minutes=(value)
|
|
|
|
self.timeout = value.to_i * 60
|
|
|
|
end
|
|
|
|
|
|
|
|
def coverage_enabled?
|
|
|
|
coverage_regex.present?
|
|
|
|
end
|
|
|
|
|
|
|
|
# Build a clone-able repo url
|
|
|
|
# using http and basic auth
|
|
|
|
def repo_url_with_auth
|
|
|
|
auth = "gitlab-ci-token:#{token}@"
|
2015-10-01 05:42:41 -04:00
|
|
|
http_url_to_repo.sub(/^https?:\/\//) do |prefix|
|
2015-08-25 21:42:46 -04:00
|
|
|
prefix + auth
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def available_services_names
|
|
|
|
%w(slack mail hip_chat)
|
|
|
|
end
|
|
|
|
|
|
|
|
def build_missing_services
|
|
|
|
available_services_names.each do |service_name|
|
|
|
|
service = services.find { |service| service.to_param == service_name }
|
|
|
|
|
|
|
|
# If service is available but missing in db
|
|
|
|
# we should create an instance. Ex `create_gitlab_ci_service`
|
2015-10-03 01:56:37 -04:00
|
|
|
self.send :"create_#{service_name}_service" if service.nil?
|
2015-08-25 21:42:46 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def execute_services(data)
|
|
|
|
services.each do |service|
|
|
|
|
|
|
|
|
# Call service hook only if it is active
|
|
|
|
begin
|
|
|
|
service.execute(data) if service.active && service.can_execute?(data)
|
|
|
|
rescue => e
|
|
|
|
logger.error(e)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def setup_finished?
|
|
|
|
commits.any?
|
|
|
|
end
|
2015-09-28 09:33:19 -04:00
|
|
|
|
|
|
|
def commits
|
|
|
|
gl_project.ci_commits
|
|
|
|
end
|
|
|
|
|
|
|
|
def builds
|
|
|
|
gl_project.ci_builds
|
|
|
|
end
|
2015-08-25 21:42:46 -04:00
|
|
|
end
|
|
|
|
end
|