diff --git a/app/models/build_stat.rb b/app/models/build_stat.rb new file mode 100644 index 00000000..c99bf2c3 --- /dev/null +++ b/app/models/build_stat.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +# Recolecta estadísticas durante la generación del sitio +class BuildStat < ApplicationRecord + belongs_to :deploy +end diff --git a/app/models/deploy.rb b/app/models/deploy.rb index 2fe5396d..e91a9d14 100644 --- a/app/models/deploy.rb +++ b/app/models/deploy.rb @@ -9,6 +9,7 @@ require 'open3' # :attributes`. class Deploy < ApplicationRecord belongs_to :site + has_many :build_stats def deploy raise NotImplementedError @@ -18,16 +19,47 @@ class Deploy < ApplicationRecord raise NotImplementedError end - # Corre un comando y devuelve true si terminó correctamente - def run(cmd) - r = 1 + def size + raise NotImplementedError + end + def time_start + @start = Time.now + end + + def time_stop + @stop = Time.now + end + + def time_spent_in_seconds + (@stop - @start).round(3) + end + + # Corre un comando y devuelve true si terminó correctamente + # rubocop:disable Metrics/MethodLength + # rubocop:disable Metrics/AbcSize + def run(cmd) + # XXX: prestar atención a la concurrencia de sqlite3, se podría + # enviar los datos directamente a una API para que se manejen desde + # el proceso principal de rails y evitar problemas. + stat = build_stats.build action: cmd.split('-', 2).first.tr(' ', '_') + r = nil + + time_start Dir.chdir(site.path) do - Open3.popen2(env, cmd, unsetenv_others: true) do |_, _o, t| + Open3.popen2e(env, cmd, unsetenv_others: true) do |_, o, t| r = t.value + stat.log = o.read end end + time_stop - r.exited? + stat.seconds = time_spent_in_seconds + stat.bytes = size + stat.save + + r.try :exited? end + # rubocop:enable Metrics/MethodLength + # rubocop:enable Metrics/AbcSize end diff --git a/app/models/deploy_local.rb b/app/models/deploy_local.rb index 10c21bd3..86229736 100644 --- a/app/models/deploy_local.rb +++ b/app/models/deploy_local.rb @@ -24,10 +24,21 @@ class DeployLocal < Deploy 1 end + # Obtener el tamaño de todos los archivos y directorios (los + # directorios son archivos :) + def size + paths = [destination, File.join(destination, '**', '**')] + + Dir.glob(paths).map do |file| + File.size file + end.inject(:+) + end + private # Un entorno que solo tiene lo que necesitamos def env + # XXX: This doesn't support Windows paths :B paths = [File.dirname(`which bundle`), '/usr/bin'] { 'PATH' => paths.join(':'), 'JEKYLL_ENV' => 'production' } diff --git a/app/models/deploy_zip.rb b/app/models/deploy_zip.rb index 0ec8afcc..b5141529 100644 --- a/app/models/deploy_zip.rb +++ b/app/models/deploy_zip.rb @@ -12,8 +12,10 @@ class DeployZip < Deploy # Una vez que el sitio está generado, tomar todos los archivos y # y generar un zip accesible públicamente. # - # TODO: Recolectar estadísticas y enviarlas a la base de datos + # rubocop:disable Metrics/MethodLength + # rubocop:disable Metrics/AbcSize def deploy + time_start Dir.chdir(destination) do Zip::File.open(path, Zip::File::CREATE) do |z| Dir.glob('./**/**').each do |f| @@ -21,9 +23,24 @@ class DeployZip < Deploy end end end + time_stop + + build_stats.create action: 'zip', + seconds: time_spent_in_seconds, + bytes: size File.exist? path end + # rubocop:enable Metrics/MethodLength + # rubocop:enable Metrics/AbcSize + + def limit + 1 + end + + def size + File.size path + end private diff --git a/db/migrate/20190725185427_create_build_stats.rb b/db/migrate/20190725185427_create_build_stats.rb new file mode 100644 index 00000000..255ea285 --- /dev/null +++ b/db/migrate/20190725185427_create_build_stats.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class CreateBuildStats < ActiveRecord::Migration[5.2] + def change + create_table :build_stats do |t| + t.timestamps + t.belongs_to :deploy, index: true + t.integer :bytes + t.float :seconds + t.string :action, null: false + t.text :log + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 28ca10a5..7e76955c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -12,7 +12,18 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20_190_723_220_002) do +ActiveRecord::Schema.define(version: 20_190_725_185_427) do + create_table 'build_stats', force: :cascade do |t| + t.datetime 'created_at', null: false + t.datetime 'updated_at', null: false + t.integer 'deploy_id' + t.integer 'bytes' + t.float 'seconds' + t.string 'action', null: false + t.text 'log' + t.index ['deploy_id'], name: 'index_build_stats_on_deploy_id' + end + create_table 'deploys', force: :cascade do |t| t.datetime 'created_at', null: false t.datetime 'updated_at', null: false diff --git a/test/models/deploy_local_test.rb b/test/models/deploy_local_test.rb index 39ba7019..b992d8cc 100644 --- a/test/models/deploy_local_test.rb +++ b/test/models/deploy_local_test.rb @@ -6,6 +6,10 @@ class DeployZipTest < ActiveSupport::TestCase assert deploy_local.deploy assert File.directory?(deploy_local.destination) + assert_equal 3, deploy_local.build_stats.count + + assert deploy_local.build_stats.map(&:bytes).compact.inject(:+).positive? + assert deploy_local.build_stats.map(&:seconds).compact.inject(:+).positive? assert deploy_local.destroy assert_not File.directory?(deploy_local.destination) diff --git a/test/models/deploy_zip_test.rb b/test/models/deploy_zip_test.rb index cbe55591..7e8712d7 100644 --- a/test/models/deploy_zip_test.rb +++ b/test/models/deploy_zip_test.rb @@ -15,6 +15,9 @@ class DeployLocalTest < ActiveSupport::TestCase assert File.file?(deploy.path) assert_equal 'application/zip', `file --mime-type "#{escaped_path}"`.split(' ').last + assert_equal 1, deploy.build_stats.count + assert deploy.build_stats.map(&:bytes).inject(:+).positive? + assert deploy.build_stats.map(&:seconds).inject(:+).positive? local.destroy end