Merge pull request #540 from warpc/442-mass_build

[refs #442] Support mass build statistic
This commit is contained in:
Vladimir Sharshov 2012-06-28 05:02:44 -07:00
commit 174c4dab0b
14 changed files with 121 additions and 183 deletions

View File

@ -71,4 +71,14 @@ $(document).ready(function() {
}
});
$(".toggle_btn").click(function() {
var target = $( $(this).attr('data-target') );
//target.toggle();
if ( target.css('visibility') == 'hidden' ) {
target.css('visibility', 'visible');
} else {
target.css('visibility', 'hidden');
}
return false;
});
});

View File

@ -1,157 +0,0 @@
/* =============================================================
* bootstrap-collapse.js v2.0.4
* http://twitter.github.com/bootstrap/javascript.html#collapse
* =============================================================
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ============================================================ */
!function ($) {
"use strict"; // jshint ;_;
/* COLLAPSE PUBLIC CLASS DEFINITION
* ================================ */
var Collapse = function (element, options) {
this.$element = $(element)
this.options = $.extend({}, $.fn.collapse.defaults, options)
if (this.options.parent) {
this.$parent = $(this.options.parent)
}
this.options.toggle && this.toggle()
}
Collapse.prototype = {
constructor: Collapse
, dimension: function () {
var hasWidth = this.$element.hasClass('width')
return hasWidth ? 'width' : 'height'
}
, show: function () {
var dimension
, scroll
, actives
, hasData
if (this.transitioning) return
dimension = this.dimension()
scroll = $.camelCase(['scroll', dimension].join('-'))
actives = this.$parent && this.$parent.find('> .accordion-group > .in')
if (actives && actives.length) {
hasData = actives.data('collapse')
if (hasData && hasData.transitioning) return
actives.collapse('hide')
hasData || actives.data('collapse', null)
}
this.$element[dimension](0)
this.transition('addClass', $.Event('show'), 'shown')
this.$element[dimension](this.$element[0][scroll])
}
, hide: function () {
var dimension
if (this.transitioning) return
dimension = this.dimension()
this.reset(this.$element[dimension]())
this.transition('removeClass', $.Event('hide'), 'hidden')
this.$element[dimension](0)
}
, reset: function (size) {
var dimension = this.dimension()
this.$element
.removeClass('collapse')
[dimension](size || 'auto')
[0].offsetWidth
this.$element[size !== null ? 'addClass' : 'removeClass']('collapse')
return this
}
, transition: function (method, startEvent, completeEvent) {
var that = this
, complete = function () {
if (startEvent.type == 'show') that.reset()
that.transitioning = 0
that.$element.trigger(completeEvent)
}
this.$element.trigger(startEvent)
if (startEvent.isDefaultPrevented()) return
this.transitioning = 1
this.$element[method]('in')
$.support.transition && this.$element.hasClass('collapse') ?
this.$element.one($.support.transition.end, complete) :
complete()
}
, toggle: function () {
this[this.$element.hasClass('in') ? 'hide' : 'show']()
}
}
/* COLLAPSIBLE PLUGIN DEFINITION
* ============================== */
$.fn.collapse = function (option) {
return this.each(function () {
var $this = $(this)
, data = $this.data('collapse')
, options = typeof option == 'object' && option
if (!data) $this.data('collapse', (data = new Collapse(this, options)))
if (typeof option == 'string') data[option]()
})
}
$.fn.collapse.defaults = {
toggle: true
}
$.fn.collapse.Constructor = Collapse
/* COLLAPSIBLE DATA-API
* ==================== */
$(function () {
$('body').on('click.collapse.data-api', '[data-toggle=collapse]', function ( e ) {
var $this = $(this), href
, target = $this.attr('data-target')
|| e.preventDefault()
|| (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
, option = $(target).data('collapse') ? 'toggle' : $this.data()
$(target).collapse(option)
})
})
}(window.jQuery);

View File

@ -1080,3 +1080,14 @@ form.mass_build section.left {
form.mass_build section.right {
margin-right: 50px;
}
.toggle {
overflow: hidden;
padding-top: 10px;
display: block;
visibility: hidden;
}
.min_width_120 {
min-width: 120px;
}

View File

@ -18,6 +18,7 @@ class Platforms::PlatformsController < Platforms::BaseController
if mass_build.save
redirect_to(mass_builds_platform_path(@platform), :notice => t("flash.platform.build_all_success"))
else
@auto_publish_selected = params[:auto_publish].present?
@mass_builds = MassBuild.by_platform(@platform).order('created_at DESC').paginate(:page => params[:page], :per_page => 20)
flash[:warning] = mass_build.errors.full_messages.join('. ')
flash[:error] = t("flash.platform.build_all_error")
@ -26,9 +27,15 @@ class Platforms::PlatformsController < Platforms::BaseController
def mass_builds
@mass_builds = MassBuild.by_platform(@platform).order('created_at DESC').paginate(:page => params[:page], :per_page => 20)
@auto_publish_selected = true
render :action => :build_all
end
def failed_builds_list
@mass_build = MassBuild.find params[:mass_build_id]
render :text => @mass_build.generate_failed_builds_list
end
def index
@platforms = @platforms.accessible_by(current_ability, :related).paginate(:page => params[:page], :per_page => 20)
end

View File

@ -6,7 +6,7 @@ class BuildList < ActiveRecord::Base
belongs_to :build_for_platform, :class_name => 'Platform'
belongs_to :user
belongs_to :advisory
belongs_to :mass_build
belongs_to :mass_build, :counter_cache => true
has_many :items, :class_name => "BuildList::Item", :dependent => :destroy
has_many :packages, :class_name => "BuildList::Package", :dependent => :destroy
@ -103,6 +103,14 @@ class BuildList < ActiveRecord::Base
state_machine :status, :initial => :waiting_for_response do
around_transition do |build_list, transition, block|
if build_list.mass_build
MassBuild.decrement_counter "#{BuildList::HUMAN_STATUSES[build_list.status].to_s}_count", build_list.mass_build_id if MassBuild::COUNT_STATUSES.include?(build_list.status)
block.call
MassBuild.increment_counter "#{BuildList::HUMAN_STATUSES[build_list.status].to_s}_count", build_list.mass_build_id if MassBuild::COUNT_STATUSES.include?(build_list.status)
end
end
after_transition :on => :published, :do => :set_version_and_tag
event :place_build do

View File

@ -12,6 +12,15 @@ class MassBuild < ActiveRecord::Base
after_create :build_all
COUNT_STATUSES = [
:build_lists,
:build_published,
:build_pending,
:build_started,
:build_publish,
:build_error
]
def initialize(args = nil)
super
@ -32,4 +41,13 @@ class MassBuild < ActiveRecord::Base
:auto_publish => self.auto_publish
) # later with resque
end
def generate_failed_builds_list
report = ""
BuildList.where(:status => BuildServer::BUILD_ERROR, :mass_build_id => self.id).each do |build_list|
report << "ID: #{build_list.id}; "
report << "PROJECT_NAME: #{build_list.project.name}\n"
end
report
end
end

View File

@ -19,7 +19,7 @@
.both
%h3= t("activerecord.attributes.build_list.preferences")
.both.bottom_20
= check_box_tag :auto_publish, true, params[:auto_publish].present? ? params[:auto_publish].present? : false, :id => 'auto_publish'
= check_box_tag :auto_publish, true, @auto_publish_selected, :id => 'auto_publish'
= label_tag :auto_publish
%br
@ -30,16 +30,31 @@
%tr
%th.lpadding16= t('activerecord.attributes.mass_build.id')
%th.lpadding16= t('activerecord.attributes.mass_build.name')
%th.lpadding16= t('activerecord.attributes.mass_build.arch_names')
%th.lpadding16= t('activerecord.attributes.mass_build.user')
%th.lpadding16= t('activerecord.attributes.mass_build.auto_publish')
%th.lpadding16= t('activerecord.attributes.mass_build.created_at')
%th.lpadding16= t("layout.mass_builds.statuses")
%th.lpadding16= t("layout.mass_builds.failed_builds_list")
%th.lpadding16= t("layout.mass_builds.extended_data")
- @mass_builds.each do |mass_build|
%tr
%td= mass_build.id
%td= link_to mass_build.name, build_lists_path(:filter => {:mass_build_id => mass_build.id})
%td= mass_build.arch_names
%td= link_to mass_build.user.fullname, mass_build.user
%td= mass_build.auto_publish
%td= mass_build.created_at
%td.min_width_120
- MassBuild::COUNT_STATUSES.each do |status|
= link_to t("layout.build_lists.statuses.#{status}") + ": ", build_lists_path(:filter => {:status => status, :mass_build_id => mass_build.id})
= mass_build.read_attribute "#{status}_count"
.both
%td= link_to t("layout.mass_builds.failed_builds_list"), failed_builds_list_platforms_path(:mass_build_id => mass_build.id), :target => "_blank"
%td
%a.toggle_btn{:href => "#toggle_#{ mass_build.id }", :'data-target' => "#toggle_#{ mass_build.id }"}= t("layout.mass_builds.extended_data")
.toggle{:id => "toggle_#{ mass_build.id }"}
= t('activerecord.attributes.mass_build.arch_names') + ": "
= mass_build.arch_names
.both
= t('activerecord.attributes.mass_build.user') + ": "
= link_to mass_build.user.fullname, mass_build.user
.both
= t('activerecord.attributes.mass_build.auto_publish') + ": "
= mass_build.auto_publish
.both
= t('activerecord.attributes.mass_build.created_at') + ": "
= mass_build.created_at
= will_paginate @mass_builds

View File

@ -97,6 +97,7 @@ en:
git_error: Git error
statuses:
build_lists: All
build_error: Build error
build_published: Build has been published
rejected_publish: Publishing rejected

View File

@ -96,6 +96,7 @@ ru:
git_error: проблема с гит
statuses:
build_lists: Всего
build_error: ошибка сборки
build_published: опубликован
rejected_publish: публикация отклонена

View File

@ -2,6 +2,9 @@ en:
layout:
mass_builds:
repositories: Repositories
extended_data: Extended data
failed_builds_list: Failed Builds List
statuses: Statuses
activerecord:
models:
mass_build: Mass Build

View File

@ -2,6 +2,9 @@ ru:
layout:
mass_builds:
repositories: Репозитории
extended_data: Параметры задания
failed_builds_list: Список ошибок сборок
statuses: Статусы
activerecord:
models:
mass_build: Массовая Сборка

View File

@ -55,6 +55,9 @@ Rosa::Application.routes.draw do
get :mass_builds
get :advisories
end
collection do
get :failed_builds_list
end
get :autocomplete_user_uname, :on => :collection
resources :repositories do
member do

View File

@ -0,0 +1,10 @@
class AddCountersToMassBuilds < ActiveRecord::Migration
def change
add_column :mass_builds, :build_lists_count, :integer, :default => 0
add_column :mass_builds, :build_published_count, :integer, :default => 0
add_column :mass_builds, :build_pending_count, :integer, :default => 0
add_column :mass_builds, :build_started_count, :integer, :default => 0
add_column :mass_builds, :build_publish_count, :integer, :default => 0
add_column :mass_builds, :build_error_count, :integer, :default => 0
end
end

View File

@ -11,14 +11,14 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20120609163454) do
ActiveRecord::Schema.define(:version => 20120622092725) do
create_table "activity_feeds", :force => true do |t|
t.integer "user_id", :null => false
t.string "kind"
t.text "data"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "advisories", :force => true do |t|
@ -204,6 +204,12 @@ ActiveRecord::Schema.define(:version => 20120609163454) do
t.string "arch_names"
t.integer "user_id"
t.boolean "auto_publish", :default => false, :null => false
t.integer "build_lists_count", :default => 0
t.integer "build_published_count", :default => 0
t.integer "build_pending_count", :default => 0
t.integer "build_started_count", :default => 0
t.integer "build_publish_count", :default => 0
t.integer "build_error_count", :default => 0
end
create_table "platforms", :force => true do |t|
@ -217,7 +223,7 @@ ActiveRecord::Schema.define(:version => 20120609163454) do
t.string "owner_type"
t.string "visibility", :default => "open", :null => false
t.string "platform_type", :default => "main", :null => false
t.string "distrib_type", :null => false
t.string "distrib_type"
end
add_index "platforms", ["name"], :name => "index_platforms_on_name", :unique => true, :case_sensitive => false
@ -288,27 +294,25 @@ ActiveRecord::Schema.define(:version => 20120609163454) 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_package", :default => true, :null => false
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, :case_sensitive => false
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"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "interest"
t.text "more"
end
@ -362,6 +366,7 @@ ActiveRecord::Schema.define(:version => 20120609163454) do
t.string "name"
t.string "email", :default => "", :null => false
t.string "encrypted_password", :limit => 128, :default => "", :null => false
t.string "password_salt", :default => "", :null => false
t.string "reset_password_token"
t.datetime "remember_created_at"
t.datetime "created_at"
@ -369,8 +374,11 @@ ActiveRecord::Schema.define(:version => 20120609163454) do
t.string "uname"
t.string "role"
t.string "language", :default => "en"
t.datetime "reset_password_sent_at"
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"
t.string "site"
t.string "company"
@ -382,9 +390,6 @@ ActiveRecord::Schema.define(:version => 20120609163454) 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"
t.string "authentication_token"
t.integer "build_priority", :default => 50
end