Merge branch 'master' into 345-update_to_rails4

Conflicts:
	Gemfile
	Gemfile.lock
This commit is contained in:
Alexander Machehin 2014-03-07 16:25:32 +06:00
commit a81b5fc69e
51 changed files with 333 additions and 588 deletions

View File

@ -82,7 +82,7 @@ group :assets do
gem 'coffee-rails', '~> 4.0.1'
gem 'compass-rails', '~> 1.1.3'
gem 'uglifier', '~> 2.4'
gem 'therubyracer', '~> 0.10.2', platforms: [:mri, :rbx]
gem 'therubyracer', '~> 0.12.1', platforms: [:mri, :rbx]
gem 'therubyrhino', '~> 1.73.1', platforms: :jruby
end
@ -109,6 +109,8 @@ group :development do
gem 'binding_of_caller'
gem 'meta_request'
gem 'localeapp'
gem 'skype'
gem 'ruby-dbus' if RUBY_PLATFORM =~ /linux/i
end
group :test do

View File

@ -178,7 +178,7 @@ GEM
json (1.8.1)
jwt (0.1.11)
multi_json (>= 1.5)
libv8 (3.3.10.4)
libv8 (3.16.14.3)
localeapp (0.7.1)
gli
i18n
@ -323,6 +323,7 @@ GEM
redis-store (~> 1.1.0)
redis-store (1.1.4)
redis (>= 2.2)
ref (1.0.5)
resque (1.25.1)
mono_logger (~> 1.0)
multi_json (~> 1.0)
@ -389,6 +390,8 @@ GEM
skinny (0.2.3)
eventmachine (~> 1.0.0)
thin (~> 1.5.0)
skype (0.2.7)
tmp_cache
soundmanager-rails (1.0.0)
sprockets (2.11.0)
hike (~> 1.2)
@ -404,8 +407,9 @@ GEM
sqlite3 (>= 1.3.3)
state_machine (1.2.0)
stringex (2.1.2)
therubyracer (0.10.2)
libv8 (~> 3.3.10)
therubyracer (0.12.1)
libv8 (~> 3.16.14.0)
ref
thin (1.5.1)
daemons (>= 1.0.9)
eventmachine (>= 0.12.6)
@ -417,6 +421,7 @@ GEM
time_diff (0.3.0)
activesupport
i18n
tmp_cache (0.1.1)
treetop (1.4.15)
polyglot
polyglot (>= 0.3.1)
@ -521,9 +526,10 @@ DEPENDENCIES
schema_plus (~> 1.4.0)
shotgun
shoulda
skype
soundmanager-rails
state_machine (~> 1.2)
therubyracer (~> 0.10.2)
therubyracer (~> 0.12.1)
therubyrhino (~> 1.73.1)
time_diff
uglifier (~> 2.4)

View File

@ -6,9 +6,4 @@ require 'rake'
require 'resque/tasks'
require 'resque_scheduler/tasks'
# This fixes connection fail with Postgres server on new fork:
task "resque:setup" => :environment do
Resque.before_fork = Proc.new { ActiveRecord::Base.establish_connection }
end
Rosa::Application.load_tasks

View File

@ -7,42 +7,39 @@ class Api::V1::JobsController < Api::V1::BaseController
before_filter :authenticate_user!
def shift
platform_ids = Platform.where(name: params[:platforms].split(',')).pluck(:id) if params[:platforms].present?
arch_ids = Arch.where(name: params[:arches].split(',')).pluck(:id) if params[:arches].present?
build_lists = BuildList.for_status(BuildList::BUILD_PENDING).scoped_to_arch(arch_ids).
oldest.order(:created_at)
build_lists = build_lists.for_platform(platform_ids) if platform_ids.present?
if current_user.system?
if task = (Resque.pop('rpm_worker_default') || Resque.pop('rpm_worker'))
@build_list = BuildList.where(id: task['args'][0]['id']).first
@build_list.delayed_add_job_to_abf_worker_queue
end
end
@build_list = BuildList.next_build if current_user.system?
unless @build_list
platform_ids = Platform.where(name: params[:platforms].split(',')).pluck(:id) if params[:platforms].present?
arch_ids = Arch.where(name: params[:arches].split(',')).pluck(:id) if params[:arches].present?
build_lists = BuildList.for_status(BuildList::BUILD_PENDING).scoped_to_arch(arch_ids).
oldest.order(:created_at)
build_lists = build_lists.for_platform(platform_ids) if platform_ids.present?
ActiveRecord::Base.transaction do
if current_user.system?
@build_list ||= build_lists.external_nodes(:everything).first
@build_list.touch if @build_list
else
@build_list = build_lists.external_nodes(:owned).for_user(current_user).first
@build_list ||= build_lists.external_nodes(:everything).
accessible_by(current_ability, :everything).readonly(false).first
ActiveRecord::Base.transaction do
if current_user.system?
@build_list ||= build_lists.external_nodes(:everything).first
@build_list.touch if @build_list
else
@build_list = build_lists.external_nodes(:owned).for_user(current_user).first
@build_list ||= build_lists.external_nodes(:everything).
accessible_by(current_ability, :everything).readonly(false).first
if @build_list
@build_list.builder = current_user
@build_list.save
if @build_list
@build_list.builder = current_user
@build_list.save
end
end
end
end unless @build_list
if @build_list
job = {
worker_queue: @build_list.worker_queue_with_priority,
worker_class: @build_list.worker_queue_class,
:worker_args => [@build_list.abf_worker_args]
}
end
job = {
worker_queue: @build_list.worker_queue_with_priority(false),
worker_class: @build_list.worker_queue_class,
:worker_args => [@build_list.abf_worker_args]
} if @build_list
render json: { job: job }.to_json
end
@ -60,7 +57,10 @@ class Api::V1::JobsController < Api::V1::BaseController
end
def status
render text: Resque.redis.get(params[:key])
if params[:key] =~ /\Aabfworker::(rpm|iso)-worker-[\d]+::live-inspector\z/
status = Resque.redis.get(params[:key])
end
render json: { status: status }.to_json
end
def logs

View File

@ -1,7 +1,4 @@
class Groups::MembersController < Groups::BaseController
is_related_controller!
belongs_to :group, finder: 'find_by_insensitive_uname!', optional: true
before_filter lambda { authorize! :manage_members, @group }
def index
@ -10,19 +7,19 @@ class Groups::MembersController < Groups::BaseController
def update
params['user'].keys.each do |user_id|
role = params['user'][user_id]
if relation = parent.actors.where(actor_id: user_id, actor_type: 'User') #find_by_actor_id_and_actor_type(user_id, 'User')
relation.update_all(role: role) if parent.owner.id.to_s != user_id
if relation = @group.actors.where(actor_id: user_id, actor_type: 'User') #find_by_actor_id_and_actor_type(user_id, 'User')
relation.update_all(role: role) if @group.owner.id.to_s != user_id
else
relation = parent.actors.build(actor_id: user_id, actor_type: 'User', role: role)
relation = @group.actors.build(actor_id: user_id, actor_type: 'User', role: role)
relation.save!
end
end if params['user']
if parent.save
if @group.save
flash[:notice] = t("flash.members.successfully_changed")
else
flash[:error] = t("flash.members.error_in_changing")
end
redirect_to group_members_path(parent)
redirect_to group_members_path(@group)
end
def remove
@ -31,20 +28,20 @@ class Groups::MembersController < Groups::BaseController
all_user_ids << user_id if remove == ["1"]
end if params['user_remove']
User.where(id: all_user_ids).each do |user|
parent.remove_member(user)
@group.remove_member(user)
end
redirect_to group_members_path(parent)
redirect_to group_members_path(@group)
end
def add
@user = User.find_by_uname(params[:user_uname])
if !@user
flash[:error] = t("flash.collaborators.wrong_user", uname: params[:user_uname])
elsif parent.add_member(@user, params[:role])
elsif @group.add_member(@user, params[:role])
flash[:notice] = t("flash.members.successfully_added")
else
flash[:error] = t("flash.members.error_in_adding")
end
redirect_to group_members_path(parent)
redirect_to group_members_path(@group)
end
end

View File

@ -1,31 +0,0 @@
class Platforms::PrivateUsersController < Platforms::BaseController
before_filter :authenticate_user!
before_filter :find_platform_and_private_users
load_and_authorize_resource :platform
def index
end
def create
old_pair = PrivateUser.find_by_platform_id_and_user_id(params[:platform_id], current_user.id)
old_pair.destroy if old_pair
@pair = PrivateUser.generate_pair(params[:platform_id], current_user.id)
@urpmi_list = @platform.urpmi_list(request.host, @pair)
redirect_to platform_private_users_path(params[:platform_id]), notice: I18n.t('flash.private_users', login: @pair[:login], password: @pair[:pass])
end
#def destroy
# user = PrivateUser.find(params[:id])
# user.destroy
# redirect_to platform_private_users_path(params[:platform_id])
#end
protected
def find_platform_and_private_users
@private_users = PrivateUser.where(platform_id: params[:platform_id]).paginate page: params[:page]
@platform = Platform.find(params[:platform_id])
end
end

View File

@ -1,32 +0,0 @@
class Platforms::PrivatesController < Platforms::BaseController
require 'digest/sha2'
before_filter :find_platform
before_filter :authenticate
def show
file_name = "#{APP_CONFIG['root_path']}/platforms/#{params[:platform_name]}/#{params[:file_path]}"
if File.directory?(file_name) || !File.exists?(file_name)
render file: "#{Rails.root}/public/404.html", layout: false, status: 404
else
send_file file_name
end
end
protected
def authenticate
authenticate_or_request_with_http_basic do |username, password|
PrivateUser.exists?(
login: username,
password: Digest::SHA2.new.hexdigest(password),
platform_id: @platform.try(:id)
)
end
end
def find_platform
@platform = Platform.find_by_name(params[:platform_name])
end
end

View File

@ -0,0 +1,8 @@
class BuildListsPublishTaskManagerJob
@queue = :hook
def self.perform
AbfWorker::BuildListsPublishTaskManager.new.run
end
end

View File

@ -0,0 +1,49 @@
class BuildListsQueuesMonitoringJob
@queue = :hook
def self.perform
redis.smembers('queues').each do |key|
next if key !~ /(user|mass)_build_/
queue = "queue:#{key}"
id = key.gsub(/[^\d]/, '')
if redis.llen(queue) == 0
if key =~ /^user/
last_updated_at = BuildList.select(:updated_at).
where(user_id: id).order('updated_at DESC').first
else
last_updated_at = MassBuild.select(:updated_at).where(id: 250).first
end
last_updated_at = last_updated_at.try(:updated_at)
# cleans queue if no activity and tasks for this queue
clean(key) if !last_updated_at || (last_updated_at + 5.minutes) < Time.zone.now
else
# ensures that user/mass-build in the set from which we select next jobs
set_key = key =~ /^user/ ? BuildList::USER_BUILDS_SET : BuildList::MASS_BUILDS_SET
redis.sadd set_key, id
end
end
end
def self.clean(key)
queue = "queue:#{key}"
# See [#watch]: https://github.com/redis/redis-rb/blob/master/lib/redis.rb#L2012
redis.watch(queue) do
if redis.llen(queue) == 0
redis.multi do |multi|
multi.del queue
multi.srem 'queues', key
end
else
redis.unwatch
end
end
end
def self.redis
@redis ||= Resque.redis
end
end

View File

@ -0,0 +1,10 @@
class CleanRpmBuildNodeJob
@queue = :hook
def self.perform
RpmBuildNode.all.each do |n|
n.delete unless n.user_id
end
end
end

View File

@ -140,9 +140,6 @@ class Ability
can([:create, :cancel, :update], ProductBuildList) {|pbl| can?(:update, pbl.product)}
can(:destroy, ProductBuildList) {|pbl| can?(:destroy, pbl.product)}
can [:read, :create], PrivateUser, platform: {owner_type: 'User', owner_id: user.id}
can [:read, :create], PrivateUser, platform: {owner_type: 'Group', owner_id: user_group_ids}
can :read, Issue, project: {owner_type: 'User', owner_id: user.id}
can :read, Issue, project: {owner_type: 'Group', owner_id: user_group_ids}
can(:read, Issue, read_relations_for('issues', 'projects')) {|issue| can? :read, issue.project rescue nil}

View File

@ -174,7 +174,7 @@ class BuildList < ActiveRecord::Base
# build_canceling: :build_canceled - canceling from UI
# build_started: :build_canceled - canceling from worker by time-out (time_living has been expired)
event :build_canceled do
transition [:build_canceling, :build_started] => :build_canceled
transition [:build_canceling, :build_started, :build_pending] => :build_canceled
end
event :published do
@ -231,12 +231,12 @@ class BuildList < ActiveRecord::Base
# ===== into testing - end
event :build_success do
transition [:build_started, :build_canceled] => :success
transition [:build_started, :build_canceling, :build_canceled] => :success
end
[:build_error, :tests_failed].each do |kind|
event kind do
transition [:build_started, :build_canceling] => kind
transition [:build_started, :build_canceling, :build_canceled] => kind
end
end
@ -526,6 +526,26 @@ class BuildList < ActiveRecord::Base
)
end
def self.next_build
redis = Resque.redis
kind_id = redis.spop(USER_BUILDS_SET)
key = "user_build_#{kind_id}_rpm_worker_default" if kind_id
task = Resque.pop(key) if key
redis.sadd(USER_BUILDS_SET, kind_id) if task
kind_id ||= redis.spop(MASS_BUILDS_SET)
key ||= "mass_build_#{kind_id}_rpm_worker" if kind_id
task ||= Resque.pop(key) if key
redis.sadd(MASS_BUILDS_SET, kind_id) if task && key =~ /^mass_build/
if task
build_list = BuildList.where(id: task['args'][0]['id']).first
build_list.delayed_add_job_to_abf_worker_queue
build_list
end
end
def delayed_add_job_to_abf_worker_queue(*args)
restart_job if status == BUILD_PENDING
end

View File

@ -19,8 +19,8 @@ class BuildListObserver < ActiveRecord::Observer
rescue ActiveRecord::RecordNotUnique
retry
end
build_count = statistic.build_count
new_av_time = ( statistic.average_build_time * build_count + record.duration ) / ( build_count + 1 )
build_count = statistic.build_count.to_i
new_av_time = ( statistic.average_build_time * build_count + record.duration.to_i ) / ( build_count + 1 )
statistic.update_attributes(average_build_time: new_av_time, build_count: build_count + 1)
end
end

View File

@ -1,5 +1,5 @@
class EventLogObserver < ActiveRecord::Observer
observe :user, :private_user, :platform, :repository, :project, :product, :build_list, :product_build_list
observe :user, :platform, :repository, :project, :product, :build_list, :product_build_list
def after_create(record)
ActiveSupport::Notifications.instrument("event_log.observer", eventable: record)

View File

@ -1,32 +0,0 @@
class PrivateUser < ActiveRecord::Base
require 'digest/sha2'
belongs_to :platform
belongs_to :user
validate :login, uniqueness: true
def event_log_message
{platform: platform.name, user: user.uname}.inspect
end
class << self
def can_generate_more?(user_id, platform_id)
!PrivateUser.exists?(user_id: user_id, platform_id: platform_id)
end
def generate_pair(platform_id, user_id)
login = "login_#{ActiveSupport::SecureRandom.hex(16)}"
pass = "pass_#{ActiveSupport::SecureRandom.hex(16)}"
PrivateUser.create(
login: login,
password: Digest::SHA2.new.hexdigest(pass),
platform_id: platform_id,
user_id: user_id
)
{login: login, pass: pass}
end
end
end

View File

@ -17,12 +17,6 @@ class RpmBuildNode < Ohm::Model
User.where(id: user_id).first
end
def self.cleanup!
RpmBuildNode.all.each do |n|
n.delete unless n.user_id
end
end
def self.total_statistics
systems, others, busy = 0, 0, 0
RpmBuildNode.all.select{ |n| n.user_id }.each do |n|

View File

@ -9,7 +9,7 @@
%th= t("layout.collaborators.members")
%th{colspan: "3"}= t("layout.collaborators.roles")
%tbody
- (parent.members - [parent.owner]).each do |user|
- (@group.members - [@group.owner]).each do |user|
%tr
%td
%span#niceCheckbox1.niceCheck-main= check_box_tag "user_remove[#{user.id}][]"
@ -18,13 +18,13 @@
.forimg= link_to user.fullname, user_path(user)
- Relation::ROLES.each_with_index do |role, i|
%td
.radio= radio_button_tag "user[#{user.id}]", role, ((parent.actors.exists? actor_id: user.id, actor_type: 'User', role: role) ? :checked : nil), class: 'niceRadio'
.radio= radio_button_tag "user[#{user.id}]", role, ((@group.actors.exists? actor_id: user.id, actor_type: 'User', role: role) ? :checked : nil), class: 'niceRadio'
.forradio= t("layout.collaborators.role_names.#{ role }")
= link_to_function t("layout.delete"), "deleteAdminMember();", class: 'button'
.both
.hr.top
= form_tag add_group_members_path(parent) do
= form_tag add_group_members_path(@group) do
.admin-search= autocomplete_field_tag 'user_uname', params[:user_uname], autocomplete_user_uname_autocompletes_path
.admin-role
.lineForm= select_tag 'role', options_for_collaborators_roles_select

View File

@ -34,6 +34,3 @@
= link_to t("layout.key_pairs.header"), platform_key_pairs_path(@platform)
%li{class: (contr == :tokens) ? 'active' : ''}
= link_to t('layout.tokens.header'), platform_tokens_path(@platform)
-#- if current_user.owner_of? @platform or current_user.admin?
%li{class: (act == :index && contr == :private_users) ? 'active' : ''}
= link_to t("layout.platforms.private_users"), platform_private_users_path(@platform)

View File

@ -1,50 +0,0 @@
-set_meta_tags title: [title_object(current_user.repository), t('layout.personal_repositories.private_users')]
.block
.secondary-navigation
%ul.wat-cf
%li.first= link_to t("layout.personal_repositories.show"), personal_repository_path(current_user.personal_repository)
%li= link_to t("layout.personal_repositories.settings"), settings_personal_repository_path(current_user.personal_repository)
%li.active= link_to t("layout.personal_repositories.private_users"), platform_private_users_path(current_user.personal_platform) if current_user.personal_platform.hidden?
.content
.inner
%p
%b
= t("activerecord.attributes.platform.name")
\:
= @platform.name
%p
%b
= t("activerecord.attributes.repository.platform")
\:
= link_to @platform.name, platform_path(@platform)
- if @urpmi_list
= render 'shared/urpmi_list', urpmi_commands: @urpmi_list
.wat-cf
=# link_to image_tag("x.png", alt: t("layout.delete")) + " " + t("layout.delete"), platform_repository_path(@platform, @repository), method: "delete", class: "button", confirm: t("layout.repositories.confirm_delete")
%br
.inner
=t('layout.private_users.warning_message')
.block
.secondary-navigation
%ul.wat-cf
%li.first.active= link_to t("layout.private_users.list"), platform_private_users_path(@platform)
%li= link_to t("layout.private_users.new"), platform_private_users_path(@platform), method: :post if PrivateUser.can_generate_more?(current_user.id, @platform.id)
.content
%h2.title
= t("layout.private_users.list_header")
.inner
%table.table
%tr
%th.first= t("activerecord.attributes.private_user.login")
%th.last &nbsp;
- @private_users.each do |private_user|
%tr{class: cycle("odd", "even")}
%td
= private_user.login
%td.last
#{link_to t("layout.private_users.regenerate_btn"), platform_private_users_path(@platform), method: :post, confirm: t("layout.private_users.confirm_regenerate")}
.actions-bar.wat-cf
.actions
= will_paginate @private_users

View File

@ -21,6 +21,7 @@ module Rosa
# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)
config.autoload_paths += %W(#{config.root}/app/presenters)
config.autoload_paths += %W(#{config.root}/app/jobs)
# Only load the plugins named here, in the order given (default is alphabetical).
# :all can be used as a placeholder for all plugins not explicitly named.

View File

@ -33,6 +33,9 @@ require 'puma/capistrano'
set :workers_count, 4
require './lib/recipes/resque'
require './lib/recipes/skype'
set :skype_topic, 'ABF' # Skype chat topic name
namespace :deploy do
task :symlink_all, :roles => :app do
run "mkdir -p #{fetch :shared_path}/config"

View File

@ -91,15 +91,6 @@ en:
sign_in_header: Sign in
sign_up_with: or sign in with
private_users:
list: List
new: New pair
list_header: Pair login/password
confirm_delete: Are you sure to delete this pair login/password?
confirm_regenerate: Are you sure to regenerate this pair login/password?
regenerate_btn: Regenerate
warning_message: Warning - Old data set as invalid when new data obtaining
collaborators:
back_to_proj: Back to project
edit: Edit list
@ -132,8 +123,6 @@ en:
saved: Settings saved success
save_error: Setting update error
private_users: "Login: %{login} Password: %{password}"
subscribe:
saved: Subscription on notifications for this task is created
saved_error: Subscription create error
@ -177,7 +166,6 @@ en:
can_have_less_or_equal: You cannot have more than %{count} projects.
models:
private_user: Private user
product_build_list: Product build list
attributes:
@ -195,10 +183,6 @@ en:
new_build: Notify about my build tasks
new_associated_build: Notify about associated with me build tasks
private_user:
login: Login
password: Password
arch:
name: Name
created_at: Created

View File

@ -11,7 +11,6 @@ en:
'devise/sessions_controller': 'User Authentication'
'devise/passwords_controller': 'Password recovery'
'users/omniauth_callbacks_controller': 'External users authentication'
private_users_controller: 'access to private repositories'
personal_repositories_controller: 'Personal repositories management'
actions:
'devise/sessions_controller':
@ -27,9 +26,6 @@ en:
create: 'sent to build'
rpc_controller:
xe_index: inquiry
private_users_controller:
create: 'given'
destroy: 'deleted'
personal_repositories_controller:
change_visibility: 'status change'
create: 'created'

View File

@ -11,7 +11,6 @@ ru:
'devise/sessions_controller': 'Аутентификация пользователей'
'devise/passwords_controller': 'Восстановление пароля'
'users/omniauth_callbacks_controller': 'Внешняя аутентификация пользователей'
private_users_controller: 'Доступ к приватным репозиториям'
personal_repositories_controller: 'Управление персональными репозиториями'
actions:
'devise/sessions_controller':
@ -27,9 +26,6 @@ ru:
create: 'отправлен на сборку'
rpc_controller:
xe_index: запрос
private_users_controller:
create: 'предоставлен'
destroy: 'удален'
personal_repositories_controller:
change_visibility: 'смена статуса'
create: 'создано'

View File

@ -35,7 +35,6 @@ en:
visibility: Visibility
platform_type: Platform type
distrib_type: Distribution type
private_users: Access data
confirm_clone: Clone?
clone: Clone
delete_warning: Attention! Deleted platform can not be restored!

View File

@ -35,7 +35,6 @@ ru:
visibility: Видимость
platform_type: Тип платформы
distrib_type: Тип дистрибутива
private_users: Данные для доступа
confirm_clone: Клонировать?
clone: Клонировать
delete_warning: Внимание! Удаленная платформа восстановлению не подлежит.

View File

@ -91,15 +91,6 @@ ru:
sign_in_header: Вход в систему
sign_up_with: или войти с помощью
private_users:
list: Список
new: Новая пара
list_header: Пары логин/пароль
confirm_delete: Вы уверены, что хотите удалить эту пару логин/пароль?
confirm_regenerate: Вы уверены, что хотите перегенерировать эту пару логин/пароль?
regenerate_btn: Перегенерировать
warning_message: Примечание - При получении новых данных старые становятся недействительными
collaborators:
back_to_proj: Вернуться к проекту
edit: Редактировать список
@ -132,8 +123,6 @@ ru:
saved: Настройки успешно сохранены
save_error: При обновлении настроек произошла ошибка
private_users: "Логин: %{login} Пароль: %{password}"
subscribe:
saved: Вы подписаны на оповещения для этой задачи
saved_error: При создании подписки произошла ошибка
@ -177,7 +166,6 @@ ru:
can_have_less_or_equal: Нельзя иметь больше, чем %{count} проектов.
models:
private_user: Приватный пользователь
product_build_list: Сборочный лист продукта
attributes:
@ -195,10 +183,6 @@ ru:
new_build: Оповещать о моих сборочных заданиях
new_associated_build: Оповещать о связанных со мной сборочных заданиях
private_user:
login: Логин
password: Пароль
arch:
name: Название
created_at: Создана

View File

@ -0,0 +1,20 @@
clean_rpm_build_nodes:
every:
- '1m'
class: 'CleanRpmBuildNodeJob'
queue: hook
description: 'Cleans RPM build nodes'
build_lists_publish_task_manager:
every:
- '3m'
class: 'BuildListsPublishTaskManagerJob'
queue: hook
description: 'Creates tasks for publishing'
build_lists_queues_monitoring:
every:
- '1m'
class: 'BuildListsQueuesMonitoringJob'
queue: hook
description: 'Monitoring for "user/mass-build" queues'

View File

@ -165,7 +165,6 @@ Rosa::Application.routes.draw do
scope module: 'platforms' do
resources :platforms, constraints: {id: Platform::NAME_PATTERN} do
resources :private_users, except: [:show, :destroy, :update]
member do
put :regenerate_metadata
put :clear
@ -221,7 +220,6 @@ Rosa::Application.routes.draw do
end
resources :maintainers, only: [:index]
end
match '/private/:platform_name/*file_path' => 'privates#show'
resources :product_build_lists, only: [:index, :show]
end

View File

@ -26,14 +26,6 @@ every :day, at: '3:00 am' do
rake 'activity_feeds:clear', output: 'log/activity_feeds.log'
end
every 3.minute do
runner 'AbfWorker::BuildListsPublishTaskManager.new.run', output: 'log/task_manager.log'
end
every 1.minute do
runner 'RpmBuildNode.cleanup!'
end
every 1.hour do
rake 'buildlist:clear:outdated_canceling', output: 'log/canceling_build_list_clear.log'
end

View File

@ -0,0 +1,15 @@
class DestroyPrivateUser < ActiveRecord::Migration
def self.up
drop_table :private_users
end
def self.down
create_table :private_users do |t|
t.integer :platform_id
t.string :login
t.string :password
t.integer :user_id
t.timestamps
end
end
end

View File

@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20140224134012) do
ActiveRecord::Schema.define(:version => 20140306102620) do
create_table "activity_feeds", :force => true do |t|
t.integer "user_id", :null => false
@ -285,7 +285,6 @@ ActiveRecord::Schema.define(:version => 20140224134012) do
t.string "arch_names"
t.integer "user_id"
t.boolean "auto_publish", :default => false, :null => false
t.integer "build_lists_count", :default => 0, :null => false
t.boolean "stop_build", :default => false, :null => false
t.text "projects_list"
t.integer "missed_projects_count", :default => 0, :null => false
@ -295,6 +294,7 @@ ActiveRecord::Schema.define(:version => 20140224134012) do
t.text "extra_repositories"
t.text "extra_build_lists"
t.boolean "increase_release_tag", :default => false, :null => false
t.integer "build_lists_count", :default => 0
end
create_table "platform_arch_settings", :force => true do |t|
@ -329,15 +329,6 @@ ActiveRecord::Schema.define(:version => 20140224134012) do
add_index "platforms", ["name"], :name => "index_platforms_on_name", :unique => true, :case_sensitive => false
create_table "private_users", :force => true do |t|
t.integer "platform_id"
t.string "login"
t.string "password"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "user_id"
end
create_table "product_build_lists", :force => true do |t|
t.integer "product_id"
t.integer "status", :null => false

View File

@ -299,8 +299,6 @@ module AbfWorker
platform_path << '/' << build_for_platform.name
system "mkdir -p #{platform_path}"
end
worker_queue = bl ? bl.worker_queue_with_priority("publish_worker") : 'publish_worker_default'
worker_class = bl ? bl.worker_queue_class("AbfWorker::PublishWorker") : 'AbfWorker::PublishWorkerDefault'
distrib_type = build_for_platform.distrib_type
cmd_params = {
@ -350,9 +348,9 @@ module AbfWorker
packages[:sources] = new_sources.values.compact
Resque.push(
worker_queue,
'class' => worker_class,
'args' => [options.merge({
'publish_worker_default',
'class' => 'AbfWorker::PublishWorkerDefault',
'args' => [options.merge({
packages: packages,
old_packages: old_packages,
build_list_ids: build_list_ids,

View File

@ -3,6 +3,9 @@ module AbfWorker::ModelHelper
# - #abf_worker_args
# - #build_canceled
MASS_BUILDS_SET = 'abf-worker::mass-builds'
USER_BUILDS_SET = 'abf-worker::user-builds'
def self.included(base)
base.extend(ClassMethods)
end
@ -14,6 +17,11 @@ module AbfWorker::ModelHelper
port: APP_CONFIG['abf_worker']['log_server']['port']
)
end
def self.next_build
raise NotImplementedError
end
end
def abf_worker_log
@ -21,6 +29,7 @@ module AbfWorker::ModelHelper
end
def add_job_to_abf_worker_queue
update_build_sets
Resque.push(
worker_queue_with_priority,
'class' => worker_queue_class,
@ -29,6 +38,7 @@ module AbfWorker::ModelHelper
end
def restart_job
update_build_sets
Resque.redis.lpush "queue:#{worker_queue_with_priority}",
Resque.encode({'class' => worker_queue_class, 'args' => [abf_worker_args]})
end
@ -50,19 +60,40 @@ module AbfWorker::ModelHelper
)
end
def worker_queue_with_priority(queue = nil)
queue ||= abf_worker_base_queue
def worker_queue_with_priority(prefix = true)
queue = ''
if prefix && is_a?(BuildList)
if mass_build_id
queue << "mass_build_#{mass_build_id}_"
else
queue << "user_build_#{user_id}_"
end
end
queue << abf_worker_base_queue
queue << '_' << abf_worker_priority if abf_worker_priority.present?
queue
end
def worker_queue_class(queue_class = nil)
queue_class ||= "AbfWorker::#{abf_worker_base_queue.classify}"
queue_class << abf_worker_priority.capitalize
def worker_queue_class
"AbfWorker::#{abf_worker_base_queue.classify}#{abf_worker_priority.capitalize}"
end
private
def update_build_sets
return unless is_a?(BuildList)
key = mass_build_id ? MASS_BUILDS_SET : USER_BUILDS_SET
Resque.redis.pipelined do
Resque.redis.sadd key, mass_build_id || user_id
Resque.redis.sadd 'queues', worker_queue_with_priority
end
end
def send_stop_signal
Resque.redis.setex(
"#{service_queue}::live-inspector",

View File

@ -9,13 +9,23 @@ module AbfWorker
result[:rpm][:workers] += nodes[:systems]
result[:rpm][:build_tasks] += nodes[:busy]
result[:rpm][:other_workers] = nodes[:others]
external_bls = BuildList.for_status(BuildList::BUILD_PENDING).external_nodes(:everything).count
result[:rpm][:default_tasks] += external_bls
result[:rpm][:tasks] += external_bls
result[:rpm][:default_tasks] += external_bls + count_of_tasks('user_build_')
mass_build_tasks = count_of_tasks('mass_build_')
result[:rpm][:low_tasks] += mass_build_tasks
result[:rpm][:tasks] += external_bls + mass_build_tasks
result
end
end
def count_of_tasks(regexp)
Resque.redis.smembers('queues').
select{ |q| q =~ /#{regexp}/ }.
map{ |q| Resque.redis.llen("queue:#{q}") }.sum
end
def products_status
get_status(:iso) { |w, worker|
str = w.to_s

View File

@ -1,16 +0,0 @@
module RelatedModels
extend ActiveSupport::Autoload
autoload :ClassMethods
autoload :BelongsToHelpers
autoload :PolymorphicHelpers
autoload :UrlHelpers
autoload :Base
end
class ActionController::Base
#include ClassMethods
def self.is_related_controller!
RelatedModels::Base.is_child!(self)
end
end

View File

@ -1,23 +0,0 @@
module RelatedModels
class Base < ::ApplicationController
def self.is_child!(base)
base.class_eval do
# include InheritedResources::Actions
# include InheritedResources::BaseHelpers
extend RelatedModels::ClassMethods
extend RelatedModels::UrlHelpers
helper_method :parent_url, :parent_path
self.class_attribute :parents_symbols, :resources_configuration, instance_writer: false
self.parents_symbols ||= []
self.resources_configuration ||= {}
protected :parents_symbols, :resources_configuration, :parents_symbols?, :resources_configuration?
end
end
is_child!(self)
end
end

View File

@ -1,39 +0,0 @@
module RelatedModels
module BelongsToHelpers
protected
def parent?
true
end
def parent
@parent ||= find_parent
end
def parent_type
parent.class.name.underscore.to_sym
end
private
def symbols_for_association_chain
parents_symbols.compact
end
def find_parent
k = params.symbolize_keys.keys
res = nil
symbols_for_association_chain.reverse.each do |sym|
if k.include? resources_configuration[sym][:param]
parent_config = resources_configuration[sym]
res = parent_config[:parent_class].send(parent_config[:finder], params[parent_config[:param]])
break
end
end
unless res
raise "Couldn't find parent"
end
return res
end
end
end

View File

@ -1,68 +0,0 @@
module RelatedModels
module ClassMethods
protected
def belongs_to(*symbols)
options = symbols.extract_options!
options.symbolize_keys!
options.assert_valid_keys(:polymorphic, :optional, :finder)
optional = options.delete(:optional)
polymorphic = options.delete(:polymorphic)
finder = options.delete(:finder)
include BelongsToHelpers if self.parents_symbols.empty?
acts_as_polymorphic! if polymorphic || optional
raise ArgumentError, 'You have to give me at least one association name.' if symbols.empty?
raise ArgumentError, 'You cannot define multiple associations with options: #{options.keys.inspect} to belongs to.' unless symbols.size == 1 || options.empty?
symbols.each do |symbol|
symbol = symbol.to_sym
if polymorphic || optional
self.parents_symbols << :polymorphic unless self.parents_symbols.include?(:polymorphic)
self.resources_configuration[:polymorphic] ||= {}
self.resources_configuration[:polymorphic][:symbols] ||= []
self.resources_configuration[:polymorphic][:symbols] << symbol
self.resources_configuration[:polymorphic][:optional] ||= optional
else
self.parents_symbols << symbol
end
config = self.resources_configuration[symbol] = {}
config[:parent_class] = begin
class_name = symbol.to_s.pluralize.classify
class_name.constantize
rescue NameError => e
raise unless e.message.include?(class_name)
nil
end
config[:collection_name] = symbol.to_s.pluralize.to_sym
config[:instance_name] = symbol
config[:param] = :"#{symbol}_id"
config[:route_name] = symbol
config[:finder] = finder || :find
end
create_resources_url_helpers!
helper_method :parent, :parent?
end
private
def acts_as_polymorphic! #:nodoc:
unless self.parents_symbols.include?(:polymorphic)
include PolymorphicHelpers
helper_method :parent_type, :parent_class
end
end
def inherited(base)
super(base)
end
end
end

View File

@ -1,80 +0,0 @@
module RelatedModels
module PolymorphicHelpers
protected
# Returns the parent type. A Comments class can have :task, :file, :note
# as parent types.
#
def parent_type
@parent_type
end
def parent_class
parent.class if @parent_type
end
# Returns the parent object. They are also available with the instance
# variable name: @task, @file, @note...
#
def parent
k = params.symbolize_keys.keys
res = nil
symbols_for_association_chain.reverse.each do |sym|
if k.include? resources_configuration[sym][:param]
parent_config = resources_configuration[sym]
res = parent_config[:parent_class].send(parent_config[:finder], params[parent_config[:param]])
break
end
end
return res
end
# If the polymorphic association is optional, we might not have a parent.
#
def parent?
if resources_configuration[:polymorphic][:optional]
parents_symbols.size > 1 || !@parent_type.nil?
else
true
end
end
private
# Maps parents_symbols to build association chain.
#
# If the parents_symbols find :polymorphic, it goes through the
# params keys to see which polymorphic parent matches the given params.
#
# When optional is given, it does not raise errors if the polymorphic
# params are missing.
#
def symbols_for_association_chain #:nodoc:
polymorphic_config = resources_configuration[:polymorphic]
parents_symbols.map do |symbol|
if symbol == :polymorphic
params_keys = params.keys
keys = polymorphic_config[:symbols].map do |poly|
params_keys.include?(resources_configuration[poly][:param].to_s) ? poly : nil
end.compact
if keys.empty?
raise ScriptError, "Could not find param for polymorphic association. The request" <<
"parameters are #{params.keys.inspect} and the polymorphic " <<
"associations are #{polymorphic_config[:symbols].inspect}." unless polymorphic_config[:optional]
nil
else
@parent_type = keys[-1].to_sym
@parent_types = keys.map(&:to_sym)
end
else
symbol
end
end.flatten.compact
end
end
end

View File

@ -1,28 +0,0 @@
module RelatedModels
module UrlHelpers
protected
def create_resources_url_helpers!
segment = if parents_symbols.include? :polymorphic
:polymorphic
else
resources_configuration[symbols_for_association_chain.first][:route_name]
end
unless parent.nil?
class_eval <<-URL_HELPERS, __FILE__, __LINE__
protected
def parent_path(*given_args)
given_options = given_args.extract_options!
#{segment}_path(parent, given_options)
end
def parent_url(*given_args)
given_options = given_args.extract_options!
#{segment}_url(parent, given_options)
end
URL_HELPERS
end
end
end
end

View File

@ -68,7 +68,7 @@ Capistrano::Configuration.instance(:must_exist).load do
def start_scheduler
pid = "#{fetch :current_path}/tmp/pids/scheduler.pid"
run "cd #{fetch :current_path} && #{rails_env} PIDFILE=#{pid} BACKGROUND=yes VERBOSE=1 MUTE=1 bundle exec rake resque:scheduler"
run "cd #{fetch :current_path} && #{rails_env} PIDFILE=#{pid} BACKGROUND=yes VERBOSE=1 MUTE=1 RESQUE_SCHEDULER_INTERVAL=0.5 bundle exec rake resque:scheduler"
end
def stop_scheduler

77
lib/recipes/skype.rb Normal file
View File

@ -0,0 +1,77 @@
require 'skype'
Capistrano::Configuration.instance(:must_exist).load do
Skype.config app_name: 'test-message'
set :skype_send_notification, true
namespace :skype do
task :trigger_notification do
set :skype_send_notification, true if !dry_run
end
task :configure_for_migrations do
set :skype_with_migrations, ' (with migrations)'
end
task :notify_deploy_started do
if skype_send_notification
environment_string = env
if self.respond_to?(:stage)
environment_string = "#{stage} (#{env})"
end
on_rollback do
send("Cancelled deployment of #{deployment_name} to #{environment_string}.\n#{'#'*60}")
end
send("#{'#'*60}\nDeploying #{deployment_name} to #{environment_string}#{fetch(:skype_with_migrations, '')}.")
end
end
task :notify_deploy_finished do
if skype_send_notification
environment_string = env
if self.respond_to?(:stage)
environment_string = "#{stage} (#{env})"
end
send("Finished deploying #{deployment_name} to #{environment_string}#{fetch(:skype_with_migrations, '')}.\n#{'#'*60}")
end
end
def send(message)
set :skype_client, Skype.chats.find { |c| c.topic == fetch(:skype_topic, '') } if fetch(:skype_client, nil).nil?
begin
skype_client.post(message)
rescue => e
puts e.message
puts e.backtrace
end
end
def deployment_name
if fetch(:branch, nil)
name = "#{application}/#{branch}"
name += " (revision #{real_revision[0..7]})" if real_revision
name
else
application
end
end
def message_notification
fetch(:skype_announce, false)
end
def env
fetch(:skype_env, fetch(:rack_env, fetch(:rails_env, "production")))
end
end
before "deploy", "skype:trigger_notification"
before "deploy:update_code", "skype:notify_deploy_started"
after "deploy", "skype:notify_deploy_finished"
after "deploy:migrations", "skype:notify_deploy_finished"
end

View File

@ -7,4 +7,17 @@ namespace :resque do
end
system("kill -QUIT #{pids.join(' ')}") if pids.size > 0
end
# This fixes connection fail with Postgres server on new fork:
task setup: :environment do
Resque.after_fork do
Resque.redis.client.reconnect
end
Resque.before_fork = Proc.new { ActiveRecord::Base.establish_connection }
end
task scheduler_setup: :environment do
Resque.schedule = YAML.load_file(Rails.root.join('config', 'resque_schedule.yml'))
end
end

View File

@ -1,5 +0,0 @@
require 'spec_helper'
describe Platforms::PrivateUsersController do
end

View File

@ -1,5 +0,0 @@
require 'spec_helper'
describe Platforms::PrivatesController do
end

View File

@ -1,8 +0,0 @@
FactoryGirl.define do
factory :private_user do
login { FactoryGirl.generate(:string) }
password { FactoryGirl.generate(:string) }
association :platform, factory: :platform
association :user, factory: :user
end
end

View File

@ -130,21 +130,6 @@ describe CanCan do
@ability.should_not be_able_to(:manage, RegisterRequest)
end
context "private users relations" do
before(:each) do
@private_user = FactoryGirl.create(:private_user)
@private_user.platform.owner = @user
@private_user.platform.save
end
[:read, :create].each do |action|
it "should be able to #{ action } PrivateUser" do
@ability.should be_able_to(action, @private_user)
end
end
end
context 'as project collaborator' do
before(:each) do
@project = FactoryGirl.create(:project_with_commit)

View File

@ -1,5 +0,0 @@
require 'spec_helper'
describe PrivateUser do
pending "add some examples to (or delete) #{__FILE__}"
end