Merge pull request #398 from warpc/223-build_list_notify_and_duration_updates

223 build list notify and duration updates
This commit is contained in:
Alexander Machehin 2012-04-13 11:43:57 -07:00
commit ba9184cc49
20 changed files with 96 additions and 80 deletions

View File

@ -94,7 +94,6 @@ class BuildListsController < ApplicationController
else
@build_list.status = BuildList::FAILED_PUBLISH
end
@build_list.notified_at = Time.current
@build_list.save
render :nothing => true, :status => 200
@ -106,7 +105,6 @@ class BuildListsController < ApplicationController
@item.save
@build_list.container_path = params[:container_path]
@build_list.notified_at = Time.current
@build_list.save
render :nothing => true, :status => 200
@ -114,7 +112,6 @@ class BuildListsController < ApplicationController
def pre_build
@build_list.status = BuildServer::BUILD_STARTED
@build_list.notified_at = Time.current
@build_list.save
render :nothing => true, :status => 200
@ -123,7 +120,6 @@ class BuildListsController < ApplicationController
def post_build
@build_list.status = params[:status]
@build_list.container_path = params[:container_path]
@build_list.notified_at = Time.current
@build_list.save
render :nothing => true, :status => 200
@ -134,7 +130,6 @@ class BuildListsController < ApplicationController
def circle_build
@build_list.is_circle = true
@build_list.container_path = params[:container_path]
@build_list.notified_at = Time.current
@build_list.save
render :nothing => true, :status => 200
@ -147,7 +142,6 @@ class BuildListsController < ApplicationController
@build_list.set_items(ActiveSupport::JSON.decode(params[:items]))
@build_list.is_circle = (params[:is_circular].to_i != 0)
@build_list.bs_id = params[:id]
@build_list.notified_at = Time.current
@build_list.save
render :nothing => true, :status => 200

View File

@ -139,7 +139,7 @@ class ActivityFeedObserver < ActiveRecord::Observer
ActivityFeed.create(
:user => User.find(recipient),
:kind => 'build_list_notification',
:data => {:task_num => record.bs_id, :build_list_id => record.id, :status => record.status, :notified_at => record.notified_at,
:data => {:task_num => record.bs_id, :build_list_id => record.id, :status => record.status, :updated_at => record.updated_at,
:project_id => record.project_id, :project_name => record.project.name, :project_owner => record.project.owner.uname,
:user_name => record.user.name, :user_email => record.user.email, :user_id => record.user_id}
)

View File

@ -66,22 +66,16 @@ class BuildList < ActiveRecord::Base
scope :scoped_to_project_version, lambda {|project_version| where(:project_version => project_version) }
scope :scoped_to_is_circle, lambda {|is_circle| where(:is_circle => is_circle) }
scope :for_creation_date_period, lambda{|start_date, end_date|
if start_date && end_date
where(["#{table_name}.created_at BETWEEN ? AND ?", start_date, end_date])
elsif start_date && !end_date
where(["#{table_name}.created_at >= ?", start_date])
elsif !start_date && end_date
where(["#{table_name}.created_at <= ?", end_date])
end
scoped = BuildList.scoped
scoped = scoped.where(["created_at >= ?", start_date]) if start_date
scoped = scoped.where(["created_at <= ?", end_date]) if end_date
scoped
}
scope :for_notified_date_period, lambda{|start_date, end_date|
if start_date && end_date
where(["notified_at BETWEEN ? AND ?", start_date, end_date])
elsif start_date && !end_date
where(["notified_at >= ?", start_date])
elsif !start_date && end_date
where(["notified_at <= ?", end_date])
end
scoped = BuildList.scoped
scoped = scoped.where(["updated_at >= ?", start_date]) if start_date
scoped = scoped.where(["updated_at <= ?", end_date]) if end_date
scoped
}
scope :scoped_to_project_name, lambda {|project_name| joins(:project).where('projects.name LIKE ?', "%#{project_name}%")}
@ -136,6 +130,14 @@ class BuildList < ActiveRecord::Base
{:project => project.name, :version => project_version, :arch => arch.name}.inspect
end
def current_duration
(Time.now - started_at).to_i
end
def human_current_duration
I18n.t("layout.build_lists.human_current_duration", {:hours => (current_duration/360).to_i, :minutes => (current_duration/60).to_i})
end
def human_duration
I18n.t("layout.build_lists.human_duration", {:hours => (duration/360).to_i, :minutes => (duration/60).to_i})
end

View File

@ -22,8 +22,8 @@ class BuildList::Filter
if @options[:created_at_start] || @options[:created_at_end]
build_lists = build_lists.for_creation_date_period(@options[:created_at_start], @options[:created_at_end])
end
if @options[:notified_at_start] || @options[:notified_at_end]
build_lists = build_lists.for_notified_date_period(@options[:notified_at_start], @options[:notified_at_end])
if @options[:updated_at_start] || @options[:updated_at_end]
build_lists = build_lists.for_notified_date_period(@options[:updated_at_start], @options[:updated_at_end])
end
end
@ -47,8 +47,8 @@ class BuildList::Filter
:status => nil,
:created_at_start => nil,
:created_at_end => nil,
:notified_at_start => nil,
:notified_at_end => nil,
:updated_at_start => nil,
:updated_at_end => nil,
:arch_id => nil,
:is_circle => nil,
:project_version => nil,
@ -60,8 +60,8 @@ class BuildList::Filter
@options[:status] = @options[:status].present? ? @options[:status].to_i : nil
@options[:created_at_start] = build_date_from_params(:created_at_start, @options)
@options[:created_at_end] = build_date_from_params(:created_at_end, @options)
@options[:notified_at_start] = build_date_from_params(:notified_at_start, @options)
@options[:notified_at_end] = build_date_from_params(:notified_at_end, @options)
@options[:updated_at_start] = build_date_from_params(:updated_at_start, @options)
@options[:updated_at_end] = build_date_from_params(:updated_at_end, @options)
@options[:project_version] = @options[:project_version].presence
@options[:arch_id] = @options[:arch_id].present? ? @options[:arch_id].to_i : nil
@options[:is_circle] = @options[:is_circle].present? ? @options[:is_circle] == "1" : nil

View File

@ -1,7 +1,7 @@
# -*- encoding : utf-8 -*-
class BuildList::Item < ActiveRecord::Base
belongs_to :build_list
belongs_to :build_list, :touch => true
attr_protected :build_list_id

View File

@ -6,7 +6,14 @@ class BuildListObserver < ActiveRecord::Observer
record.started_at = Time.now if record.status == BuildServer::BUILD_STARTED
if [BuildServer::BUILD_ERROR, BuildServer::SUCCESS].include? record.status
# stores time interval beetwin build start and finish in seconds
record.duration = (Time.now - record.started_at).to_i
record.duration = record.current_duration
if record.status == BuildServer::SUCCESS
# Update project average build time
build_count = record.project.build_count
new_av_time = ( record.project.average_build_time * build_count + record.duration ) / ( build_count + 1 )
record.project.update_attributes({ :average_build_time => new_av_time, :build_count => build_count + 1 }, :without_protection => true)
end
end
end
end

View File

@ -203,6 +203,11 @@ class Project < ActiveRecord::Base
recipients
end
def human_average_build_time
time = average_build_time
I18n.t("layout.projects.human_average_build_time", {:hours => (time/360).to_i, :minutes => (time/60).to_i})
end
protected
def build_path(dir)

View File

@ -22,26 +22,11 @@
%h3= t("layout.activity_feed.my_builds_by_day")
%table{:cellpadding => "0", :cellspacing => "0"}
%tbody
- ['BuildList::BUILD_PUBLISHED', 'BuildServer::SUCCESS', 'BuildServer::BUILD_STARTED', 'BuildList::BUILD_PENDING', 'BuildServer::BUILD_ERROR'].each do |state|
%tr
%td.first
= link_to t("layout.build_lists.statuses.#{:build_published}"), build_lists_path(:filter => {:status => BuildList::BUILD_PUBLISHED, :notified_at => midnight})
%td= BuildList.for_status(BuildList::BUILD_PUBLISHED).for_user(current_user).for_notified_date_period(midnight, nil).count
%tr
%td.first
= link_to t("layout.build_lists.statuses.#{:success}"), build_lists_path(:filter => {:status => BuildServer::SUCCESS, :notified_at => midnight})
%td= BuildList.for_status(BuildServer::SUCCESS).for_user(current_user).for_notified_date_period(midnight, nil).count
%tr
%td.first
= link_to t("layout.build_lists.statuses.#{:build_started}"), build_lists_path(:filter => {:status => BuildServer::BUILD_STARTED, :notified_at => midnight})
%td= BuildList.for_status(BuildServer::BUILD_STARTED).for_user(current_user).for_notified_date_period(midnight, nil).count
%tr
%td.first
= link_to t("layout.build_lists.statuses.#{:build_pending}"), build_lists_path(:filter => {:status => BuildList::BUILD_PENDING, :notified_at => midnight})
%td= BuildList.for_status(BuildList::BUILD_PENDING).for_user(current_user).for_notified_date_period(midnight, nil).count
%tr
%td.first
= link_to t("layout.build_lists.statuses.#{:build_error}"), build_lists_path(:filter => {:status => BuildServer::BUILD_ERROR, :notified_at => midnight})
%td= BuildList.for_status(BuildServer::BUILD_ERROR).for_user(current_user).for_notified_date_period(midnight, nil).count
= link_to t("layout.build_lists.statuses.#{state.demodulize.downcase}"), build_lists_path(:filter => {:status => state.constantize, :updated_at => midnight})
%td= BuildList.for_status(state.constantize).for_user(current_user).for_notified_date_period(midnight, nil).count
%tr
%td.first
= link_to t("layout.activity_feed.all_my_builds"), build_lists_path

View File

@ -15,5 +15,5 @@
- else ['failed', t("layout.build_lists.statuses.#{BuildList::HUMAN_STATUSES[status]}")]
= raw t("notifications.bodies.build_status.#{message}", :error => error)
.both
%span.date= notified_at
%span.date= updated_at
.both

View File

@ -6,4 +6,4 @@
%td= build_list.arch.name
%td= link_to build_list.user.try(:fullname), build_list.user
%td= link_to image_tag('x.png', :class => 'delete-row', :id => "delete-row#{build_list_counter}"), cancel_build_list_path(build_list), :method => :put, :confirm => t('layout.confirm') if build_list.can_cancel? and can?(:cancel, build_list)
%td= build_list.notified_at
%td= build_list.updated_at

View File

@ -47,10 +47,10 @@
.date_select= f.date_select(:created_at_start, :include_blank => true, :selected => @filter.created_at_start)
%h3.small= t("layout.build_lists.created_at_end")
.date_select= f.date_select(:created_at_end, :include_blank => true, :selected => @filter.created_at_end)
%h3.small= t("layout.build_lists.notified_at_start")
.date_select= f.date_select(:notified_at_start, :include_blank => true, :selected => @filter.notified_at_start)
%h3.small= t("layout.build_lists.notified_at_end")
.date_select= f.date_select(:notified_at_end, :include_blank => true, :selected => @filter.notified_at_end)
%h3.small= t("layout.build_lists.updated_at_start")
.date_select= f.date_select(:updated_at_start, :include_blank => true, :selected => @filter.updated_at_start)
%h3.small= t("layout.build_lists.updated_at_end")
.date_select= f.date_select(:updated_at_end, :include_blank => true, :selected => @filter.updated_at_end)
%h3.small= t("layout.build_lists.project_name_search")
= f.text_field :project_name
%h3.small= t("layout.build_lists.bs_id_search")

View File

@ -2,4 +2,4 @@
%td= link_to (platform_build_list.bs_id.present? ? platform_build_list.bs_id : t("layout.build_lists.bs_id_not_set")), platform_build_list
%td= platform_build_list.human_status
%td= link_to platform_build_list.project.name, platform_build_list.project
%td= platform_build_list.notified_at
%td= platform_build_list.updated_at

View File

@ -10,7 +10,7 @@
%th.lpadding16= t("activerecord.attributes.build_list.arch")
%th.lpadding16= t("activerecord.attributes.build_list.user")
%th= t("layout.build_lists.action")
%th.lpadding16= t("activerecord.attributes.build_list.notified_at")
%th.lpadding16= t("activerecord.attributes.build_list.updated_at")
%tbody= render @build_lists
.both

View File

@ -46,8 +46,8 @@
.leftside.width125= t("activerecord.attributes.build_list.arch")
.leftside= @build_list.arch.name
.both
.leftside.width125= t("activerecord.attributes.build_list.notified_at")
.leftside= @build_list.notified_at
.leftside.width125= t("activerecord.attributes.build_list.updated_at")
.leftside= @build_list.updated_at
.both
.leftside.width125= t("activerecord.attributes.build_list.is_circle")
.leftside= t("layout.#{@build_list.is_circle?}_")
@ -57,6 +57,13 @@
.leftside.width125
.leftside= @build_list.human_duration
.both
- if !@build_list.finished? && @build_list.started_at
%br
.leftside.width125
.leftside
= "#{@build_list.human_current_duration} / #{@build_list.project.human_average_build_time}"
.both
.hr
%h3= t("layout.build_lists.items_header")
- if @item_groups.blank?

View File

@ -14,10 +14,9 @@ en:
arch_id: Architecture
arch: Architecture
is_circle: Recurrent build
notified_at: Notified at
updated_at: Notified at
additional_repos: Additional repositories
include_repos: Included repositories
updated_at: Updated on
created_at: Created on
pl: Repository for package storage
pl_id: Repository for package storage
@ -45,8 +44,8 @@ en:
current: Curent
created_at_start: "Build to start on:"
created_at_end: "Build to start until:"
notified_at_start: "Last update from BS on:"
notified_at_end: " Last update from BS until:"
updated_at_start: "Last update from BS on:"
updated_at_end: " Last update from BS until:"
bs_id_search: 'Search by Id'
project_name_search: Search by project name
bs_id_not_set: Id has not been configured yet
@ -61,6 +60,7 @@ en:
action: Action
new_header: New build
main_data: Main data
human_current_duration: Build currently takes %{hours} h. %{minutes} min.
human_duration: Builded in %{hours} h. %{minutes} min.
ownership:

View File

@ -14,10 +14,9 @@ ru:
arch_id: Архитектура
arch: Архитектура
is_circle: Циклическая сборка
notified_at: Информация получена
updated_at: Информация получена
additional_repos: Дополнительные репозитории
include_repos: Подключаемые репозитории
updated_at: Обновлен
created_at: Создан
pl: Репозиторий для сохранения пакетов
pl_id: Репозиторий для сохранения пакетов
@ -44,8 +43,8 @@ ru:
current: Текущие
created_at_start: "Время постановки на сборку с:"
created_at_end: "Время постановки на сборку по:"
notified_at_start: "Время последнего обновления от BS с:"
notified_at_end: "Время последнего обновления от BS по:"
updated_at_start: "Время последнего обновления от BS с:"
updated_at_end: "Время последнего обновления от BS по:"
bs_id_search: 'Поиск по Id'
project_name_search: Поиск по названию проекта
bs_id_not_set: Id еще не присвоен
@ -60,6 +59,8 @@ ru:
action: Действие
new_header: Новая сборка
main_data: Основные данные
human_current_duration: Сборка длится уже %{hours} ч. %{minutes} мин.
human_duration: Собрано за %{hours} ч. %{minutes} мин.
ownership:

View File

@ -33,6 +33,7 @@ en:
sections: Sections
has_issue_description: Tracker adds a lightweight issue management system tightly integrated with your repository.
has_wiki_description: Wikis are the simplest way to allow other users to contribute content. Any user can create and edit pages for documentation, examples, support or anything you wish.
human_average_build_time: Expected time is %{hours} h. %{minutes} min.
git_help:
cloning: Cloning the repository

View File

@ -33,6 +33,7 @@ ru:
sections: Разделы
has_issue_description: Трэкер предоставляет лекговесный менеджер для задач по разработке Вашего проекта.
has_wiki_description: Wiki - это самый простой способ предоставить другим вносить свой вклад в развитие Вашего проекта. Каждый пользователь нашего сервиса может использовать Wiki для документирования, примеров, поддержки или всего другого, в чем у Вас появится необходимость.
human_average_build_time: 'Ожидаемое время: %{hours} ч. %{minutes} мин.'
diff_show_header: "%{files} с %{additions} и %{deletions}."
about_subheader: "О проекте"

View File

@ -0,0 +1,9 @@
class BuildAverageTime < ActiveRecord::Migration
def change
add_column :projects, :average_build_time, :integer, :null => false, :default => 0
add_column :projects, :build_count, :integer, :null => false, :default => 0
end
ActivityFeed.where(:kind => 'build_list_notification').destroy_all
end

View File

@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20120411142354) do
ActiveRecord::Schema.define(:version => 20120413102757) do
create_table "activity_feeds", :force => true do |t|
t.integer "user_id", :null => false
@ -190,7 +190,7 @@ ActiveRecord::Schema.define(:version => 20120411142354) do
t.string "owner_type"
t.string "visibility", :default => "open", :null => false
t.string "platform_type", :default => "main", :null => false
t.string "distrib_type"
t.string "distrib_type", :null => false
end
add_index "platforms", ["name"], :name => "index_platforms_on_name", :unique => true, :case_sensitive => false
@ -261,23 +261,27 @@ ActiveRecord::Schema.define(:version => 20120411142354) do
t.text "description"
t.string "ancestry"
t.boolean "has_issues", :default => true
t.boolean "has_wiki", :default => false
t.string "srpm_file_name"
t.string "srpm_content_type"
t.integer "srpm_file_size"
t.datetime "srpm_updated_at"
t.boolean "has_wiki", :default => false
t.string "default_branch", :default => "master"
t.boolean "is_rpm", :default => true
t.integer "average_build_time", :default => 0, :null => false
t.integer "build_count", :default => 0, :null => false
end
add_index "projects", ["owner_id"], :name => "index_projects_on_name_and_owner_id_and_owner_type", :unique => true
create_table "register_requests", :force => true do |t|
t.string "name"
t.string "email"
t.string "token"
t.boolean "approved", :default => false
t.boolean "rejected", :default => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.datetime "created_at"
t.datetime "updated_at"
t.string "interest"
t.text "more"
end
@ -339,9 +343,6 @@ ActiveRecord::Schema.define(:version => 20120411142354) do
t.string "uname"
t.string "role"
t.string "language", :default => "en"
t.string "confirmation_token"
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
t.integer "own_projects_count", :default => 0, :null => false
t.datetime "reset_password_sent_at"
t.text "professional_experience"
@ -355,6 +356,9 @@ ActiveRecord::Schema.define(:version => 20120411142354) do
t.integer "failed_attempts", :default => 0
t.string "unlock_token"
t.datetime "locked_at"
t.string "confirmation_token"
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
end
add_index "users", ["confirmation_token"], :name => "index_users_on_confirmation_token", :unique => true