├── .gitignore ├── .ruby-version ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── Procfile ├── README.md ├── Rakefile ├── app ├── assets │ ├── images │ │ ├── .keep │ │ └── fastlane.png │ ├── javascripts │ │ ├── application.js │ │ └── bacons.coffee │ └── stylesheets │ │ ├── application.css │ │ ├── bacons.scss │ │ └── scaffolds.scss ├── controllers │ ├── application_controller.rb │ ├── bacons_controller.rb │ ├── concerns │ │ └── .keep │ └── stability_controller.rb ├── helpers │ ├── application_helper.rb │ └── bacons_helper.rb ├── mailers │ └── .keep ├── models │ ├── .keep │ ├── bacon.rb │ └── concerns │ │ └── .keep ├── views │ ├── bacons │ │ ├── graphs.html.erb │ │ └── stats.html.erb │ ├── layouts │ │ └── application.html.erb │ └── stability │ │ ├── index.html.erb │ │ └── okrs.html.erb └── workers │ ├── analytic_ingester_worker.rb │ └── bacon_updater_worker.rb ├── bin ├── bundle ├── rails ├── rake ├── setup └── spring ├── config.ru ├── config ├── application.rb ├── boot.rb ├── database.yml ├── environment.rb ├── environments │ ├── development.rb │ ├── production.rb │ └── test.rb ├── initializers │ ├── assets.rb │ ├── backtrace_silencers.rb │ ├── cookies_serializer.rb │ ├── filter_parameter_logging.rb │ ├── inflections.rb │ ├── mime_types.rb │ ├── session_store.rb │ └── wrap_parameters.rb ├── locales │ └── en.yml ├── routes.rb └── secrets.yml ├── db ├── migrate │ ├── 20150413194641_create_bacons.rb │ ├── 20160509194220_add_tool_version_and_number_crashes_to_bacons.rb │ └── 20170427183242_add_index_to_bacons.rb ├── schema.rb └── seeds.rb ├── lib ├── assets │ └── .keep └── tasks │ └── .keep ├── public ├── 404.html ├── 422.html ├── 500.html ├── favicon.ico └── robots.txt └── vendor └── assets ├── javascripts └── .keep └── stylesheets └── .keep /.gitignore: -------------------------------------------------------------------------------- 1 | *.rbc 2 | capybara-*.html 3 | .rspec 4 | .env 5 | /log 6 | /tmp 7 | /db/*.sqlite3 8 | /public/system 9 | /coverage/ 10 | /spec/tmp 11 | **.orig 12 | rerun.txt 13 | pickle-email-*.html 14 | 15 | # TODO Comment out these rules if you are OK with secrets being uploaded to the repo 16 | config/initializers/secret_token.rb 17 | 18 | ## Environment normalisation: 19 | /.bundle 20 | /vendor/bundle 21 | 22 | # these should all be checked in to normalise the environment: 23 | # Gemfile.lock, .ruby-version, .ruby-gemset 24 | 25 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: 26 | .rvmrc 27 | 28 | # if using bower-rails ignore default bower_components path bower.json files 29 | /vendor/assets/bower_components 30 | *.bowerrc 31 | bower.json 32 | 33 | latest.dump 34 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.3.0 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | ruby "2.3.0" 3 | 4 | # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' 5 | gem 'rails', '4.2.1' 6 | # Use SCSS for stylesheets 7 | gem 'sass-rails', '~> 5.0' 8 | # Use Uglifier as compressor for JavaScript assets 9 | gem 'uglifier', '>= 1.3.0' 10 | # Use CoffeeScript for .coffee assets and views 11 | gem 'coffee-rails', '~> 4.1.0' 12 | # See https://github.com/rails/execjs#readme for more supported runtimes 13 | # gem 'therubyracer', platforms: :ruby 14 | 15 | # Use jquery as the JavaScript library 16 | gem 'jquery-rails' 17 | # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks 18 | gem 'turbolinks' 19 | # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder 20 | gem 'jbuilder', '~> 2.0' 21 | # bundle exec rake doc:rails generates the API under doc/api. 22 | gem 'sdoc', '~> 0.4.0', group: :doc 23 | 24 | gem 'chart-js-rails' # nice HTML5 graphs 25 | 26 | gem 'table_for_collection' 27 | 28 | gem 'faraday' 29 | 30 | gem 'pg' 31 | 32 | # background jobs using a Redis server as the queue 33 | gem 'resque', '~> 1.27.2' 34 | 35 | gem 'foreman' 36 | 37 | # Use ActiveModel has_secure_password 38 | # gem 'bcrypt', '~> 3.1.7' 39 | 40 | # Use Unicorn as the app server 41 | # gem 'unicorn' 42 | 43 | # Use Capistrano for deployment 44 | # gem 'capistrano-rails', group: :development 45 | 46 | group :development, :test do 47 | # Call 'byebug' anywhere in the code to stop execution and get a debugger console 48 | gem 'byebug' 49 | 50 | # Access an IRB console on exception pages or by using <%= console %> in views 51 | gem 'web-console', '~> 2.0' 52 | 53 | # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring 54 | gem 'spring' 55 | 56 | gem 'sqlite3' 57 | end 58 | 59 | group :production do 60 | gem 'rails_12factor' # Heroku (http://stackoverflow.com/questions/18324063/rails-4-images-not-loading-on-heroku) 61 | end 62 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | actionmailer (4.2.1) 5 | actionpack (= 4.2.1) 6 | actionview (= 4.2.1) 7 | activejob (= 4.2.1) 8 | mail (~> 2.5, >= 2.5.4) 9 | rails-dom-testing (~> 1.0, >= 1.0.5) 10 | actionpack (4.2.1) 11 | actionview (= 4.2.1) 12 | activesupport (= 4.2.1) 13 | rack (~> 1.6) 14 | rack-test (~> 0.6.2) 15 | rails-dom-testing (~> 1.0, >= 1.0.5) 16 | rails-html-sanitizer (~> 1.0, >= 1.0.1) 17 | actionview (4.2.1) 18 | activesupport (= 4.2.1) 19 | builder (~> 3.1) 20 | erubis (~> 2.7.0) 21 | rails-dom-testing (~> 1.0, >= 1.0.5) 22 | rails-html-sanitizer (~> 1.0, >= 1.0.1) 23 | activejob (4.2.1) 24 | activesupport (= 4.2.1) 25 | globalid (>= 0.3.0) 26 | activemodel (4.2.1) 27 | activesupport (= 4.2.1) 28 | builder (~> 3.1) 29 | activerecord (4.2.1) 30 | activemodel (= 4.2.1) 31 | activesupport (= 4.2.1) 32 | arel (~> 6.0) 33 | activesupport (4.2.1) 34 | i18n (~> 0.7) 35 | json (~> 1.7, >= 1.7.7) 36 | minitest (~> 5.1) 37 | thread_safe (~> 0.3, >= 0.3.4) 38 | tzinfo (~> 1.1) 39 | arel (6.0.4) 40 | binding_of_caller (0.7.2) 41 | debug_inspector (>= 0.0.1) 42 | builder (3.2.3) 43 | byebug (9.0.6) 44 | chart-js-rails (0.1.2) 45 | railties (> 3.1) 46 | coffee-rails (4.1.1) 47 | coffee-script (>= 2.2.0) 48 | railties (>= 4.0.0, < 5.1.x) 49 | coffee-script (2.4.1) 50 | coffee-script-source 51 | execjs 52 | coffee-script-source (1.12.2) 53 | concurrent-ruby (1.0.5) 54 | debug_inspector (0.0.2) 55 | erubis (2.7.0) 56 | execjs (2.7.0) 57 | faraday (0.11.0) 58 | multipart-post (>= 1.2, < 3) 59 | foreman (0.84.0) 60 | thor (~> 0.19.1) 61 | globalid (0.3.7) 62 | activesupport (>= 4.1.0) 63 | i18n (0.8.1) 64 | jbuilder (2.6.3) 65 | activesupport (>= 3.0.0, < 5.2) 66 | multi_json (~> 1.2) 67 | jquery-rails (4.3.1) 68 | rails-dom-testing (>= 1, < 3) 69 | railties (>= 4.2.0) 70 | thor (>= 0.14, < 2.0) 71 | json (1.8.6) 72 | loofah (2.0.3) 73 | nokogiri (>= 1.5.9) 74 | mail (2.6.4) 75 | mime-types (>= 1.16, < 4) 76 | mime-types (3.1) 77 | mime-types-data (~> 3.2015) 78 | mime-types-data (3.2016.0521) 79 | mini_portile2 (2.1.0) 80 | minitest (5.10.1) 81 | mono_logger (1.1.0) 82 | multi_json (1.12.1) 83 | multipart-post (2.0.0) 84 | nokogiri (1.7.1) 85 | mini_portile2 (~> 2.1.0) 86 | pg (0.20.0) 87 | rack (1.6.5) 88 | rack-protection (1.5.3) 89 | rack 90 | rack-test (0.6.3) 91 | rack (>= 1.0) 92 | rails (4.2.1) 93 | actionmailer (= 4.2.1) 94 | actionpack (= 4.2.1) 95 | actionview (= 4.2.1) 96 | activejob (= 4.2.1) 97 | activemodel (= 4.2.1) 98 | activerecord (= 4.2.1) 99 | activesupport (= 4.2.1) 100 | bundler (>= 1.3.0, < 2.0) 101 | railties (= 4.2.1) 102 | sprockets-rails 103 | rails-deprecated_sanitizer (1.0.3) 104 | activesupport (>= 4.2.0.alpha) 105 | rails-dom-testing (1.0.8) 106 | activesupport (>= 4.2.0.beta, < 5.0) 107 | nokogiri (~> 1.6) 108 | rails-deprecated_sanitizer (>= 1.0.1) 109 | rails-html-sanitizer (1.0.3) 110 | loofah (~> 2.0) 111 | rails_12factor (0.0.3) 112 | rails_serve_static_assets 113 | rails_stdout_logging 114 | rails_serve_static_assets (0.0.5) 115 | rails_stdout_logging (0.0.5) 116 | railties (4.2.1) 117 | actionpack (= 4.2.1) 118 | activesupport (= 4.2.1) 119 | rake (>= 0.8.7) 120 | thor (>= 0.18.1, < 2.0) 121 | rake (12.0.0) 122 | rdoc (4.3.0) 123 | redis (3.3.3) 124 | redis-namespace (1.5.3) 125 | redis (~> 3.0, >= 3.0.4) 126 | resque (1.27.2) 127 | mono_logger (~> 1.0) 128 | multi_json (~> 1.0) 129 | redis-namespace (~> 1.3) 130 | sinatra (>= 0.9.2) 131 | vegas (~> 0.1.2) 132 | sass (3.4.23) 133 | sass-rails (5.0.6) 134 | railties (>= 4.0.0, < 6) 135 | sass (~> 3.1) 136 | sprockets (>= 2.8, < 4.0) 137 | sprockets-rails (>= 2.0, < 4.0) 138 | tilt (>= 1.1, < 3) 139 | sdoc (0.4.2) 140 | json (~> 1.7, >= 1.7.7) 141 | rdoc (~> 4.0) 142 | sinatra (1.4.8) 143 | rack (~> 1.5) 144 | rack-protection (~> 1.4) 145 | tilt (>= 1.3, < 3) 146 | spring (2.0.1) 147 | activesupport (>= 4.2) 148 | sprockets (3.7.1) 149 | concurrent-ruby (~> 1.0) 150 | rack (> 1, < 3) 151 | sprockets-rails (3.2.0) 152 | actionpack (>= 4.0) 153 | activesupport (>= 4.0) 154 | sprockets (>= 3.0.0) 155 | sqlite3 (1.3.13) 156 | table_for_collection (1.0.7) 157 | actionpack 158 | thor (0.19.4) 159 | thread_safe (0.3.6) 160 | tilt (2.0.7) 161 | turbolinks (5.0.1) 162 | turbolinks-source (~> 5) 163 | turbolinks-source (5.0.0) 164 | tzinfo (1.2.3) 165 | thread_safe (~> 0.1) 166 | uglifier (3.1.10) 167 | execjs (>= 0.3.0, < 3) 168 | vegas (0.1.11) 169 | rack (>= 1.0.0) 170 | web-console (2.3.0) 171 | activemodel (>= 4.0) 172 | binding_of_caller (>= 0.7.2) 173 | railties (>= 4.0) 174 | sprockets-rails (>= 2.0, < 4.0) 175 | 176 | PLATFORMS 177 | ruby 178 | 179 | DEPENDENCIES 180 | byebug 181 | chart-js-rails 182 | coffee-rails (~> 4.1.0) 183 | faraday 184 | foreman 185 | jbuilder (~> 2.0) 186 | jquery-rails 187 | pg 188 | rails (= 4.2.1) 189 | rails_12factor 190 | resque (~> 1.27.2) 191 | sass-rails (~> 5.0) 192 | sdoc (~> 0.4.0) 193 | spring 194 | sqlite3 195 | table_for_collection 196 | turbolinks 197 | uglifier (>= 1.3.0) 198 | web-console (~> 2.0) 199 | 200 | RUBY VERSION 201 | ruby 2.3.0p0 202 | 203 | BUNDLED WITH 204 | 1.14.6 205 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Felix Krause 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: bundle exec rails server -p $PORT 2 | anaingworker: env QUEUE=analytic_ingester TERM_CHILD=1 RESQUE_TERM_TIMEOUT=7 bundle exec rake environment resque:work 3 | baconworker: env QUEUE=bacon_updater TERM_CHILD=1 RESQUE_TERM_TIMEOUT=7 bundle exec rake environment resque:work 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### This repository is deprecated 2 | 3 | Please check out the [main readme](https://github.com/fastlane/fastlane#metrics) for most up to date information about what kind of data fastlane stores. 4 | 5 | ---- 6 | 7 | 8 |

9 | 10 | 11 |
12 | fastlane 13 |
14 |

15 | 16 | ------- 17 | 18 | enhancer 19 | ============ 20 | 21 | [![Twitter: @FastlaneTools](https://img.shields.io/badge/contact-@FastlaneTools-blue.svg?style=flat)](https://twitter.com/FastlaneTools) 22 | [![License](http://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://github.com/fastlane/enhancer/blob/master/LICENSE) 23 | 24 | [fastlane](https://fastlane.tools) tracks the number of errors for each action to detect integration issues. 25 | 26 | ### Privacy 27 | 28 | This does **not** store any personal or sensitive data. Everything `enhancer` stores is the ratio between successful and failed action runs. 29 | 30 | ### Why? 31 | 32 | - This data is very useful to find out which actions tend to cause the most build errors and improve them! 33 | - The actions that are used by many developers should be improved in both implementation and documentation. It's great to know which actions are worth improving! 34 | 35 | To sum up, all data is used to improve `fastlane` more efficiently 36 | 37 | ### Opt out 38 | 39 | You can set the environment variable `FASTLANE_OPT_OUT_USAGE` to opt out. 40 | 41 | Alternatively, add `opt_out_usage` to your `Fastfile`. 42 | 43 | # Running _enhancer_ locally 44 | 45 | * Start with a `bundle install` in the project directory to make sure you have all of the dependencies 46 | 47 | ## Set needed environment variables 48 | 49 | * Create a `.env` file in your _enhancer_ project root containing the desired values for: 50 | 51 | ``` 52 | ANALYTIC_INGESTER_URL=[the public URL for the Analytic Ingester service - can be omitted!] 53 | FL_PASSWORD=[password used to see the web dashboard] 54 | ``` 55 | 56 | ## Getting a database snapshot 57 | 58 | * Get PostgreSQL installed on your Mac 59 | * https://postgresapp.com/ is a quick way to get that going 60 | * Make sure you are signed in to the Heroku command line application 61 | * https://devcenter.heroku.com/articles/heroku-cli 62 | * Run `heroku pg:pull DATABASE_URL enhancer --app fastlane-enhancer` to pull the latest data from production into your local DB 63 | * This will fail if you already have a local database called `enhancer`. In that case, decide where you want to drop your local DB, and try it again. 64 | 65 | ## Get Redis installed and running 66 | 67 | * Install with `brew install redis` 68 | * Run `redis-server /Users/mfurtak/homebrew/etc/redis.conf` in a tab that you keep around, or run `brew services start redis` to have it start up whenever your Mac does 69 | 70 | ## Run the Rails and Resque processes 71 | 72 | Heroku uses something called a `Procfile` to track multiple processes that you want have started up, and a gem called `foreman` knows how to run these things for you locally 73 | 74 | * Run `RAILS_ENV=development bundle exec foreman start` to start up the `web` and `worker` processes 75 | 76 | ``` 77 | $ bundle exec foreman start 78 | 10:09:22 web.1 | started with pid 55133 79 | 10:09:22 worker.1 | started with pid 55134 80 | 10:09:24 web.1 | [2017-03-29 10:09:24] INFO WEBrick 1.3.1 81 | 10:09:24 web.1 | [2017-03-29 10:09:24] INFO ruby 2.3.0 (2015-12-25) [x86_64-darwin16] 82 | 10:09:24 web.1 | [2017-03-29 10:09:24] INFO WEBrick::HTTPServer#start: pid=55133 port=5000 83 | ``` 84 | 85 | **Note that this runs the web server on port 5000, rather than the typical 3000 for Rails** 86 | 87 | # Using _enhancer_ 88 | 89 | ### Supported Parameters 90 | 91 | Enhancer supports parameters to filter the shown actions. Any combination of parameters are supported. 92 | 93 | #### only 94 | 95 | Limits the actions that will be shown to the supplied list. It can be used either with a single value or multiple values: 96 | 97 | - `?only=gym`: Only shows info for the `gym` action 98 | - `?only[]=gym&only[]=testflight&only[]=...`: Only show info for the supplied actions `gym, testflight, ...` 99 | 100 | #### weeks 101 | 102 | Limits the data to data from the previous weeks, for example: 103 | 104 | - `?weeks=4`: Only show data from the previous 4 weeks 105 | 106 | #### minimum_launches 107 | 108 | Only shows action with a certain mimimum number of launches 109 | 110 | - `?minimum_launches=500000`: only show the most used actions 111 | - `?minimum_launches=50000&weeks=4`: only show actions with 50,000 launches within the last 4 weeks 112 | 113 | #### ratio_above & ratio_below 114 | 115 | Only shows actions that are above or below a certain error ratio. The error ratio is calculated by `number_of_errors / number_of_launches`. 116 | 117 | - `?ratio_above=0.5`: Shows actions with an error ratio >= 0.5 118 | - `?ratio_below=0.5&ratio_above=0.1`: Shows actions with an error ratio between 0.1 and 0.5 119 | 120 | #### top 121 | 122 | Show the top % of actions 123 | 124 | - `?top=10`: Show the top 10% of actions for each table (by launches and by ratio) 125 | 126 | #### Examples 127 | 128 | `?top=50&weeks=1&only[]=ipa&only[]=gym` 129 | 130 | This will show which of the actions `ipa` and `gym` was used more often in the past week, and which of those had a worse error ratio 131 | 132 | `?weeks=4&ratio_above=0.25&ratio_below=0.75` 133 | 134 | Shows a list of actions that had an error ratio between 0.25 and 0.75 in the past 4 weeks. 135 | 136 | # Code of Conduct 137 | Help us keep `fastlane` open and inclusive. Please read and follow our [Code of Conduct](https://github.com/fastlane/code-of-conduct). 138 | 139 | # License 140 | This project is licensed under the terms of the MIT license. See the LICENSE file. 141 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | require 'resque/tasks' 4 | 5 | require File.expand_path('../config/application', __FILE__) 6 | 7 | Rails.application.load_tasks 8 | 9 | # Create a new DB backup, and import it to the local Postgres DB 10 | task :db do 11 | app = ENV["HEROKU_APP"] || "fastlane-enhancer" 12 | db_name = ENV["DB_NAME"] || "enhancer" 13 | user = ENV["USER"] 14 | 15 | puts "This script is going to drop your local database #{db_name} and fetch the database from heroku #{app}. Quit now if that doesn't sound good, or press any key to continue" 16 | STDIN.gets 17 | 18 | Bundler.with_clean_env do 19 | sh "heroku pg:backups capture --app #{app}" 20 | sh "curl -o latest.dump `heroku pg:backups public-url --app #{app}`" 21 | sh "dropdb #{db_name} || true" 22 | sh "createdb #{db_name}" 23 | sh "pg_restore --verbose --clean --no-acl --no-owner -h localhost -U #{user} -d #{db_name} latest.dump" 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /app/assets/images/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastlane-old/enhancer/d041a2ad01d52d56ce48c77ce8c886ab16837abd/app/assets/images/.keep -------------------------------------------------------------------------------- /app/assets/images/fastlane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastlane-old/enhancer/d041a2ad01d52d56ce48c77ce8c886ab16837abd/app/assets/images/fastlane.png -------------------------------------------------------------------------------- /app/assets/javascripts/application.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into application.js, which will include all the files 2 | // listed below. 3 | // 4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, 5 | // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. 6 | // 7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 8 | // compiled file. 9 | // 10 | // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details 11 | // about supported directives. 12 | // 13 | //= require jquery 14 | //= require jquery_ujs 15 | //= require turbolinks 16 | //= require Chart 17 | //= require_tree . 18 | -------------------------------------------------------------------------------- /app/assets/javascripts/bacons.coffee: -------------------------------------------------------------------------------- 1 | # Place all the behaviors and hooks related to the matching controller here. 2 | # All this logic will automatically be available in application.js. 3 | # You can use CoffeeScript in this file: http://coffeescript.org/ 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll be compiled into application.css, which will include all the files 3 | * listed below. 4 | * 5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, 6 | * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. 7 | * 8 | * You're free to add application-wide styles to this file and they'll appear at the bottom of the 9 | * compiled file so the styles you add here take precedence over styles defined in any styles 10 | * defined in the other CSS/SCSS files in this directory. It is generally better to create a new 11 | * file per style scope. 12 | * 13 | *= require_tree . 14 | *= require_self 15 | */ 16 | 17 | table { 18 | border-collapse: collapse; 19 | table-layout: fixed; 20 | } 21 | 22 | tr th, 23 | tr td { 24 | padding: 10px; 25 | vertical-align: top; 26 | } 27 | 28 | tr { 29 | border-bottom: 1px solid #ccc; 30 | } 31 | 32 | h1, h2, h3, h4 { 33 | padding-top: 20px; 34 | } 35 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bacons.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the Bacons controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/scaffolds.scss: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #fff; 3 | color: #333; 4 | font-family: verdana, arial, helvetica, sans-serif; 5 | font-size: 13px; 6 | line-height: 18px; 7 | } 8 | 9 | p, ol, ul, td { 10 | font-family: verdana, arial, helvetica, sans-serif; 11 | font-size: 13px; 12 | line-height: 18px; 13 | } 14 | 15 | pre { 16 | background-color: #eee; 17 | padding: 10px; 18 | font-size: 11px; 19 | } 20 | 21 | a { 22 | color: #000; 23 | &:visited { 24 | color: #666; 25 | } 26 | &:hover { 27 | color: #fff; 28 | background-color: #000; 29 | } 30 | } 31 | 32 | div { 33 | &.field, &.actions { 34 | margin-bottom: 10px; 35 | } 36 | } 37 | 38 | #notice { 39 | color: green; 40 | } 41 | 42 | .field_with_errors { 43 | padding: 2px; 44 | background-color: red; 45 | display: table; 46 | } 47 | 48 | #error_explanation { 49 | width: 450px; 50 | border: 2px solid red; 51 | padding: 7px; 52 | padding-bottom: 0; 53 | margin-bottom: 20px; 54 | background-color: #f0f0f0; 55 | h2 { 56 | text-align: left; 57 | font-weight: bold; 58 | padding: 5px 5px 5px 15px; 59 | font-size: 12px; 60 | margin: -7px; 61 | margin-bottom: 0px; 62 | background-color: #c00; 63 | color: #fff; 64 | } 65 | ul li { 66 | font-size: 12px; 67 | list-style: square; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | TOOLS = %w( 3 | cert 4 | credentials_manager 5 | deliver 6 | fastlane 7 | fastlane_core 8 | frameit 9 | gym 10 | match 11 | pem 12 | pilot 13 | produce 14 | scan 15 | screengrab 16 | sigh 17 | snapshot 18 | spaceship 19 | supply 20 | watchbuild 21 | ) 22 | 23 | def authenticate 24 | authenticate_or_request_with_http_basic do |username, password| 25 | username == "admin" && password == ENV["FL_PASSWORD"] 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /app/controllers/bacons_controller.rb: -------------------------------------------------------------------------------- 1 | require 'faraday' 2 | 3 | class BaconsController < ApplicationController 4 | before_filter :authenticate, only: [:graphs, :stats] 5 | 6 | def did_launch 7 | launches = JSON.parse(params[:steps]) rescue nil 8 | 9 | unless launches 10 | render json: { error: "Missing values" } 11 | return 12 | end 13 | 14 | # Store the number of runs per action 15 | parsed_versions = JSON.parse(params[:versions]) rescue {} 16 | Resque.enqueue(BaconUpdaterWorker, launches, params[:error], params[:crash], parsed_versions) 17 | 18 | send_analytic_ingester_event(params[:fastfile_id], params[:error], params[:crash], launches, Time.now.to_i, parsed_versions) 19 | 20 | render json: { success: true } 21 | end 22 | 23 | # This helps us track the success/failure of Fastfiles which are generated 24 | # by an automated process, such as fastlane web onboarding 25 | def send_analytic_ingester_event(fastfile_id, error, crash, launches, timestamp_seconds, parsed_versions) 26 | return unless ENV['ANALYTIC_INGESTER_URL'].present? 27 | 28 | Resque.enqueue(AnalyticIngesterWorker, fastfile_id, error, crash, launches, timestamp_seconds, parsed_versions) 29 | end 30 | 31 | def stats 32 | bacon_actions = Bacon.group(:action_name) 33 | 34 | if params[:only] 35 | only_show = params[:only].is_a?(Array) ? params[:only] : [params[:only]] 36 | bacon_actions = bacon_actions.where(action_name: only_show) 37 | end 38 | 39 | if params[:weeks] 40 | num_weeks = params[:weeks].to_i 41 | cutoff_date = num_weeks.weeks.ago 42 | 43 | bacon_actions = bacon_actions.where("launch_date >= :cutoff_date", cutoff_date: cutoff_date) 44 | end 45 | 46 | @minimum_launches = 20000 47 | if params[:minimum_launches].to_s.length > 0 # because 0 is also a valid number 48 | @minimum_launches = params[:minimum_launches].to_i 49 | elsif params[:weeks].to_i > 0 50 | @minimum_launches = params[:weeks].to_i * 100 51 | end 52 | 53 | # Selects the sums and action name without converting into a Bacon object 54 | launch_info = bacon_actions.pluck("sum(number_errors)", "sum(launches)", "sum(number_crashes)", :action_name) 55 | 56 | @sums = [] 57 | launch_info.each do |errors, launches, crashes, action| 58 | next if launches < @minimum_launches 59 | entry = { 60 | action: action, 61 | action_short: action.gsub("fastlane-plugin-", "plugin-").truncate(50), 62 | launches: launches, 63 | errors: errors, 64 | ratio: (errors.to_f / launches.to_f).round(3), 65 | crashes: crashes 66 | } 67 | ratio_above = params[:ratio_above].nil? ? 0.0 : params[:ratio_above].to_f 68 | ratio_below = params[:ratio_below].nil? ? 1.0 : params[:ratio_below].to_f 69 | @sums << entry if entry[:ratio] >= ratio_above && entry[:ratio] <= ratio_below 70 | end 71 | 72 | @sums.sort! { |a, b| b[:ratio] <=> a[:ratio] } 73 | 74 | @by_launches = @sums.sort { |a, b| b[:launches] <=> a[:launches] } 75 | # Add the ranking number as one of the values per hash 76 | @by_launches.each_with_index { |value, index| value[:index] = index + 1 } 77 | 78 | if params[:top] 79 | top_percentage = params[:top].to_i / 100.0 80 | @sums = @sums.first(top_percentage * @sums.count) 81 | @by_launches = @by_launches.first(top_percentage * @by_launches.count) 82 | end 83 | 84 | @levels = [ 85 | { value: 0.5, color: 'red' }, 86 | { value: 0.3, color: 'orange' }, 87 | { value: 0.1, color: 'yellow' }, 88 | { value: 0.0, color: 'green' } 89 | ] 90 | 91 | respond_to do |format| 92 | format.html # renders the matching template 93 | format.json { render json: @by_launches } 94 | end 95 | end 96 | end 97 | -------------------------------------------------------------------------------- /app/controllers/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastlane-old/enhancer/d041a2ad01d52d56ce48c77ce8c886ab16837abd/app/controllers/concerns/.keep -------------------------------------------------------------------------------- /app/controllers/stability_controller.rb: -------------------------------------------------------------------------------- 1 | class StabilityController < ApplicationController 2 | before_filter :authenticate 3 | 4 | def index 5 | @tool = params[:tool] || 'fastlane' 6 | @version = params[:version] 7 | 8 | all_names = select_all_names 9 | all_plugins = select_all_plugins 10 | @tool_select_groups = { 11 | 'Tools' => TOOLS, 12 | 'Actions' => all_names - TOOLS - all_plugins, 13 | 'Plugins' => all_plugins 14 | } 15 | 16 | @details = select_details_info(@tool).group_by(&:launch_date) 17 | 18 | # Generate the data we need to show stability grouped by version, instead of date 19 | @graph_data = {} 20 | minimum_launches_to_show_in_graph = nil # we don't want to show the crash rate of a version that's only used once in the last month or so 21 | 22 | # Now detect the minimum launches we need to show a version 23 | @details.each do |_, bacon_list| 24 | bacon_list.each do |current_bacon| 25 | current_i = current_bacon.launches * 0.1 26 | 27 | if minimum_launches_to_show_in_graph.nil? || current_i > minimum_launches_to_show_in_graph 28 | minimum_launches_to_show_in_graph = current_i 29 | end 30 | end 31 | end 32 | 33 | @details.each do |_, bacon_list| 34 | bacon_list.each do |current_bacon| 35 | @graph_data[current_bacon[:tool_version]] ||= { 36 | number_user_errors: 0, 37 | number_crashes: 0, 38 | launches: 0 39 | } 40 | @graph_data[current_bacon[:tool_version]][:number_user_errors] += current_bacon.number_user_errors 41 | @graph_data[current_bacon[:tool_version]][:number_crashes] += current_bacon.number_crashes 42 | @graph_data[current_bacon[:tool_version]][:launches] += current_bacon.launches 43 | end 44 | end 45 | 46 | @graph_data = Hash[@graph_data.sort { |x, y| Gem::Version.new(x.first) <=> Gem::Version.new(y.first) }] 47 | 48 | # We always want to show the most current version to see releases that are being rolled out 49 | # We can't just use `@graph_data.keys.last`, as people fork fastlane and increase the fastlane version to 100 50 | # not super friendly, but something we can work around by accessing the RubyGems API 51 | require 'open-uri' 52 | highest_version = JSON.parse(open("https://rubygems.org/api/v1/gems/fastlane.json").read)["version"] 53 | @graph_data.delete_if do |tool_version, data| 54 | data[:launches] < minimum_launches_to_show_in_graph && tool_version != highest_version 55 | end 56 | 57 | # @graph_data => {"1.105.3"=>{:number_user_errors=>1225, :number_crashes=>267, :launches => 123123}, 58 | # "1.108.0"=>{:number_user_errors=>2195, :number_crashes=>430, :launches => 884743}, 59 | # ... 60 | 61 | @versions = @graph_data.keys # needed for the graph 62 | @raw_graph = [ 63 | { 64 | label: "Crashes", 65 | fillColor: "rgba(220,220,220,0.2)", 66 | backgroundColor: "rgba(220,220,220,0.07)", 67 | borderColor: "red", 68 | pointStrokeColor: "#fff", 69 | pointHitRadius: 10, 70 | pointHighlightFill: "#fff", 71 | pointHighlightStroke: "rgba(220,220,220,1)", 72 | data: @graph_data.collect do |_, a| 73 | (a[:number_crashes].to_f / a[:launches]).round(3) * 100 74 | end 75 | }, 76 | { 77 | label: "User Errors", 78 | fillColor: "rgba(220,220,220,0.2)", 79 | backgroundColor: "rgba(220,220,220,0.07)", 80 | borderColor: "orange", 81 | pointStrokeColor: "#fff", 82 | pointHitRadius: 10, 83 | pointHighlightFill: "#fff", 84 | pointHighlightStroke: "rgba(220,220,220,1)", 85 | data: @graph_data.collect do |_, a| 86 | (a[:number_user_errors].to_f / a[:launches]).round(3) * 100 87 | end 88 | }, 89 | { 90 | label: "Success", 91 | fillColor: "rgba(220,220,220,0.2)", 92 | backgroundColor: "rgba(220,220,220,0.07)", 93 | borderColor: "green", 94 | pointStrokeColor: "#fff", 95 | pointHitRadius: 10, 96 | pointHighlightFill: "#fff", 97 | pointHighlightStroke: "rgba(220,220,220,1)", 98 | data: @graph_data.collect do |_, a| 99 | ((a[:launches] - a[:number_user_errors] - a[:number_crashes]).to_f / a[:launches]).round(3) * 100 100 | end 101 | } 102 | ] 103 | end 104 | 105 | # pass ?weeks=x to 106 | def okrs 107 | # Render our OKR goals around fastlane stability 108 | tools = { 109 | cert: 0.89, 110 | deliver: 0.7, 111 | fastlane: 0.7, 112 | frameit: 0.9, 113 | gym: 0.76, 114 | match: 0.88, 115 | pem: 0.88, 116 | pilot: 0.7, 117 | produce: 0.85, 118 | scan: 0.65, # this is lower than 0.7, beacuse failing tests also report a lower success rate 119 | screengrab: 0.7, 120 | sigh: 0.86, 121 | snapshot: 0.85, 122 | supply: 0.73 123 | } 124 | 125 | actions = { 126 | cocoapods: 0.9, 127 | increment_build_number: 0.95, 128 | slack: 0.95, 129 | clear_derived_data: 0.95, 130 | set_info_plist_value: 0.95, 131 | gradle: 0.8, 132 | get_version_number: 0.95, 133 | crashlytics: 0.9, 134 | get_info_plist_value: 0.95, 135 | xcodebuild: 0.9, 136 | hockey: 0.94, 137 | carthage: 0.9, 138 | unlock_keychain: 0.9, 139 | update_fastlane: 0.95, 140 | update_info_plist: 0.95, 141 | reset_git_repo: 0.95, 142 | increment_version_number: 0.95, 143 | get_build_number: 0.95, 144 | xcode_select: 0.95, 145 | update_app_identifier: 0.95, 146 | update_project_provisioning: 0.95, 147 | badge: 0.95, 148 | changelog_from_git_commits: 0.95, 149 | add_git_tag: 0.95, 150 | ensure_git_branch: 0.95, 151 | hipchat: 0.95, 152 | register_devices: 0.95 153 | } 154 | 155 | @okrs_tools = [] 156 | @okrs_actions = [] 157 | 158 | tools.merge(actions).each do |action_name, goal| 159 | data_for_action = select_details_info(action_name, (params["weeks"] || 3 * 4).to_i) # defaults to one quarter 160 | number_of_launches = data_for_action.sum(:launches) 161 | data_for_action_array = data_for_action.to_a 162 | number_of_non_successes = data_for_action_array.sum(&:number_user_errors) + data_for_action_array.sum(&:number_crashes) 163 | number_of_successes = number_of_launches - number_of_non_successes 164 | actual_value = (number_of_successes / number_of_launches.to_f).round(3) 165 | 166 | current_row = { 167 | action_name: action_name, 168 | goal_value: goal, 169 | actual_value: actual_value, 170 | emoji: (goal > actual_value) ? "🔥" : "🌴", 171 | success: (goal > actual_value) ? 0 : 1 172 | } 173 | if tools.key?(action_name) 174 | @okrs_tools << current_row 175 | else 176 | @okrs_actions << current_row 177 | end 178 | end 179 | 180 | @okrs_tools.sort! { |a, b| a[:actual_value] <=> b[:actual_value] } 181 | @okrs_actions.sort! { |a, b| a[:actual_value] <=> b[:actual_value] } 182 | 183 | # Calculating the success of the high level OKRs 184 | @okr_status_tools = { 185 | goal: @okrs_tools.count, 186 | actual: @okrs_tools.sum {|a| a[:success] } 187 | } 188 | @okr_status_tools[:color] = okr_color(@okr_status_tools[:actual], @okr_status_tools[:goal]) 189 | 190 | @okr_status_actions = { 191 | goal: @okrs_actions.count, 192 | actual: @okrs_actions.sum {|a| a[:success] } 193 | } 194 | @okr_status_actions[:color] = okr_color(@okr_status_actions[:actual], @okr_status_actions[:goal]) 195 | end 196 | 197 | def okr_color(actual, goal) 198 | case (actual / goal.to_f) 199 | when 0...0.5 200 | "red" 201 | when 0.5...0.7 202 | "yellow" 203 | when 0.7..1.0 204 | "#47FD49" 205 | end 206 | end 207 | 208 | def select_all_names 209 | Bacon.where("tool_version <> 'unknown'"). 210 | pluck(:action_name). 211 | map(&:downcase). # Unfortunately we have values like "FASTLANE" and 'Fastlane' 212 | uniq. 213 | sort 214 | end 215 | 216 | def select_all_plugins 217 | Bacon.where("action_name LIKE 'fastlane-plugin-%'"). 218 | pluck(:action_name). 219 | map(&:downcase). 220 | uniq. 221 | sort 222 | end 223 | 224 | def select_details_info(tool, number_of_weeks = 26) 225 | date_limit = number_of_weeks.weeks.ago.to_date 226 | 227 | select_statement = [ 228 | "action_name", 229 | "launch_date", 230 | "tool_version", 231 | "launches", 232 | "(number_errors - number_crashes) as number_user_errors", 233 | "number_crashes", 234 | "(1::float - (number_errors::float / launches::float)) * 100::float as success_rate", 235 | "((number_errors::float - number_crashes::float) / launches::float) * 100::float as user_error_rate", 236 | "(number_crashes::float / launches::float) * 100::float as crash_rate" 237 | ].join(', ') 238 | 239 | bacons = Bacon.select(select_statement). 240 | where("launch_date >= ?::date AND tool_version <> 'unknown' AND action_name = ?", date_limit, tool). 241 | order("launch_date DESC") 242 | 243 | bacons = bacons.where("tool_version = ?", params[:version]) if params[:version] 244 | 245 | bacons 246 | end 247 | end 248 | -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/bacons_helper.rb: -------------------------------------------------------------------------------- 1 | module BaconsHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/mailers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastlane-old/enhancer/d041a2ad01d52d56ce48c77ce8c886ab16837abd/app/mailers/.keep -------------------------------------------------------------------------------- /app/models/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastlane-old/enhancer/d041a2ad01d52d56ce48c77ce8c886ab16837abd/app/models/.keep -------------------------------------------------------------------------------- /app/models/bacon.rb: -------------------------------------------------------------------------------- 1 | class Bacon < ActiveRecord::Base 2 | end 3 | -------------------------------------------------------------------------------- /app/models/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastlane-old/enhancer/d041a2ad01d52d56ce48c77ce8c886ab16837abd/app/models/concerns/.keep -------------------------------------------------------------------------------- /app/views/bacons/graphs.html.erb: -------------------------------------------------------------------------------- 1 |

Graphs about the number of launches of each fastlane tool

2 |

View the source code on GitHub

3 |

Error rate

4 | 5 | 6 | 7 | 24 | 25 |

View the source code of 'refresher'

-------------------------------------------------------------------------------- /app/views/bacons/stats.html.erb: -------------------------------------------------------------------------------- 1 | 15 | 16 |

Enhancer

17 | 18 |

This is the number of times an action was run and compared to the number of errors this action caused. More information on GitHub

19 | 20 | 21 | 22 | 38 | 54 | 55 |
23 | By # Launches 24 | <%= table_for @by_launches, html: { 25 | tr: { 26 | class: lambda do |entry| 27 | result = nil 28 | @levels.reverse.each do |value| 29 | result = value[:color] if entry[:ratio] >= value[:value] 30 | end 31 | result 32 | end 33 | } 34 | } do -%> 35 | <% columns :index, :action_short, :ratio, :launches, :errors, :crashes %> 36 | <% end %> 37 | 39 | By Ratio 40 | <%= table_for @sums, html: { 41 | tr: { 42 | class: lambda do |entry| 43 | result = nil 44 | @levels.reverse.each do |value| 45 | result = value[:color] if entry[:ratio] >= value[:value] 46 | end 47 | result 48 | end 49 | } 50 | } do -%> 51 | <% columns :action_short, :ratio, :launches, :errors, :crashes %> 52 | <% end %> 53 |
56 | 57 | The tables above hide all actions that have less than <%= @minimum_launches %> launches. You can change that using `?minimum_launches=123`. 58 | -------------------------------------------------------------------------------- /app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Enhancer 5 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> 6 | <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> 7 | <%= csrf_meta_tags %> 8 | 9 | 10 | 11 | <%= yield %> 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/views/stability/index.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= select_tag 'tool_select', grouped_options_for_select(@tool_select_groups, @tool) %> 3 |
4 | 5 | 11 | 12 |

<%= @tool %> Stability

13 | 14 |

Stability per version in %

15 | 16 | 17 | 36 | -------------------------------------------------------------------------------- /app/views/stability/okrs.html.erb: -------------------------------------------------------------------------------- 1 | 6 | 7 |

fastlane stability OKRs

8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 21 | 22 | 23 | 24 | 25 | 28 | 29 | 30 |
MetricGoalActual
Number of tools being stable<%= @okr_status_tools[:goal] %> 19 | <%= @okr_status_tools[:actual] %> 20 |
Number of actions being stable<%= @okr_status_actions[:goal] %> 26 | <%= @okr_status_actions[:actual] %> 27 |
31 | 32 |
33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | <% @okrs_tools.each do |okr| %> 41 | 42 | 43 | 44 | 45 | 46 | 47 | <% end %> 48 | 49 |
ToolGoal StabilityActual StabilityState
<%= okr[:action_name] %><%= okr[:goal_value] %><%= okr[:actual_value] %><%= okr[:emoji] %>
50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | <% @okrs_actions.each do |okr| %> 58 | 59 | 60 | 61 | 62 | 63 | 64 | <% end %> 65 | 66 |
ActionGoal StabilityActual StabilityState
<%= okr[:action_name] %><%= okr[:goal_value] %><%= okr[:actual_value] %><%= okr[:emoji] %>
67 | -------------------------------------------------------------------------------- /app/workers/analytic_ingester_worker.rb: -------------------------------------------------------------------------------- 1 | require 'faraday' 2 | 3 | class AnalyticIngesterWorker 4 | @queue = :analytic_ingester 5 | 6 | def self.perform(fastfile_id, error, crash, launches, timestamp_seconds, versions={}) 7 | start = Time.now 8 | 9 | analytics = [] 10 | 11 | if fastfile_id.present? && launches.size == 1 && launches['fastlane'] 12 | completion_status = crash.present? ? 'crash' : ( error.present? ? 'error' : 'success' ) 13 | analytics << event_for_web_onboarding(fastfile_id, completion_status, timestamp_seconds) 14 | end 15 | 16 | launches.each do |action, count| 17 | action_version = versions[action] || 'unknown' 18 | action_completion_status = action == crash ? 'crash' : ( action == error ? 'error' : 'success' ) 19 | 20 | analytics << event_for_completion(action, action_completion_status, action_version, timestamp_seconds) 21 | analytics << event_for_count(action, count, action_version, timestamp_seconds) 22 | end 23 | 24 | analytic_event_body = { analytics: analytics }.to_json 25 | 26 | puts "Sending analytic event: #{analytic_event_body}" 27 | 28 | response = Faraday.new(:url => ENV["ANALYTIC_INGESTER_URL"]).post do |req| 29 | req.headers['Content-Type'] = 'application/json' 30 | req.body = analytic_event_body 31 | end 32 | 33 | stop = Time.now 34 | 35 | puts "Analytic ingester response was: #{response.status}" 36 | puts "Sending analytic ingester event took #{(stop - start) * 1000}ms" 37 | end 38 | 39 | def self.event_for_web_onboarding(fastfile_id, completion_status, timestamp_seconds) 40 | { 41 | event_source: { 42 | oauth_app_name: 'fastlane-enhancer', 43 | product: 'fastlane_web_onboarding' 44 | }, 45 | actor: { 46 | name: 'customer', 47 | detail: fastfile_id 48 | }, 49 | action: { 50 | name: 'fastfile_executed' 51 | }, 52 | primary_target: { 53 | name: 'fastlane_completion_status', 54 | detail: completion_status 55 | }, 56 | millis_since_epoch: timestamp_seconds * 1000, 57 | version: 1 58 | } 59 | end 60 | 61 | def self.event_for_completion(action, completion_status, version, timestamp_seconds) 62 | { 63 | event_source: { 64 | oauth_app_name: 'fastlane-enhancer', 65 | product: 'fastlane' 66 | }, 67 | actor: { 68 | name: 'action', 69 | detail: action 70 | }, 71 | action: { 72 | name: 'execution_completed' 73 | }, 74 | primary_target: { 75 | name: 'completion_status', 76 | detail: completion_status 77 | }, 78 | secondary_target: { 79 | name: 'version', 80 | detail: version 81 | }, 82 | millis_since_epoch: timestamp_seconds * 1000, 83 | version: 1 84 | } 85 | end 86 | 87 | def self.event_for_count(action, count, version, timestamp_seconds) 88 | { 89 | event_source: { 90 | oauth_app_name: 'fastlane-enhancer', 91 | product: 'fastlane' 92 | }, 93 | actor: { 94 | name: 'action', 95 | detail: action 96 | }, 97 | action: { 98 | name: 'execution_counted' 99 | }, 100 | primary_target: { 101 | name: 'count', 102 | detail: count.to_s || "1" 103 | }, 104 | secondary_target: { 105 | name: 'version', 106 | detail: version 107 | }, 108 | millis_since_epoch: timestamp_seconds * 1000, 109 | version: 1 110 | } 111 | end 112 | end 113 | -------------------------------------------------------------------------------- /app/workers/bacon_updater_worker.rb: -------------------------------------------------------------------------------- 1 | class BaconUpdaterWorker 2 | @queue = :bacon_updater 3 | 4 | ActiveRecord::Base.logger = Logger.new(STDOUT) 5 | 6 | def self.perform(launches, error, crash, versions={}) 7 | puts "Starting bacons update for launches: #{launches}, versions: #{versions}, error: #{error}, crash: #{crash}" 8 | 9 | clear_start = Time.now 10 | # Returns any connections in use by the current thread back to the pool, and also returns 11 | # connections to the pool cached by threads that are no longer alive. 12 | ActiveRecord::Base.clear_active_connections! 13 | clear_stop = Time.now 14 | puts "Timing: ActiveRecord::Base.clear_active_connections! took #{(clear_stop - clear_start) * 1000}ms" 15 | 16 | now = Time.now.to_date 17 | 18 | launches_start = Time.now 19 | launches.each do |action, count| 20 | launch_start = Time.now 21 | 22 | tool_version = versions[action] || 'unknown' 23 | entry = Bacon.find_or_create_by(action_name: action, launch_date: now, tool_version: tool_version) 24 | entry.increment(:launches, count) 25 | entry.save 26 | 27 | launch_stop = Time.now 28 | puts "Timing: launch DB write took #{(launch_stop - launch_start) * 1000}ms" 29 | end 30 | launches_stop = Time.now 31 | puts "Timing: All launches DB writes took #{(launches_stop - launches_start) * 1000}ms" 32 | 33 | if error.present? 34 | error_start = Time.now 35 | 36 | tool_version = versions[error] || 'unknown' 37 | update_bacon_for(error, now, tool_version) do |bacon| 38 | bacon.increment(:number_errors) 39 | bacon.save 40 | end 41 | 42 | error_stop = Time.now 43 | puts "Timing: error DB write took #{(error_stop - error_start) * 1000}ms" 44 | end 45 | 46 | if crash.present? 47 | crash_start = Time.now 48 | 49 | tool_version = versions[crash] || 'unknown' 50 | update_bacon_for(crash, now, tool_version) do |bacon| 51 | bacon.increment(:number_crashes) 52 | bacon.save 53 | end 54 | 55 | crash_stop = Time.now 56 | puts "Timing: crash DB write took #{(crash_stop - crash_start) * 1000}ms" 57 | end 58 | 59 | puts "Finished bacons update for launches: #{launches}, versions: #{versions}, error: #{error}, crash: #{crash}" 60 | rescue => ex 61 | puts "#{ex.message} - #{ex.backtrace.join("\n")}" 62 | end 63 | 64 | def self.update_bacon_for(action_name, launch_date, tool_version) 65 | Bacon.find_by(action_name: action_name, launch_date: launch_date, tool_version: tool_version).try do |bacon| 66 | yield bacon 67 | end 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 3 | load Gem.bin_path('bundler', 'bundle') 4 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | begin 3 | load File.expand_path("../spring", __FILE__) 4 | rescue LoadError 5 | end 6 | APP_PATH = File.expand_path('../../config/application', __FILE__) 7 | require_relative '../config/boot' 8 | require 'rails/commands' 9 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | begin 3 | load File.expand_path("../spring", __FILE__) 4 | rescue LoadError 5 | end 6 | require_relative '../config/boot' 7 | require 'rake' 8 | Rake.application.run 9 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'pathname' 3 | 4 | # path to your application root. 5 | APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) 6 | 7 | Dir.chdir APP_ROOT do 8 | # This script is a starting point to setup your application. 9 | # Add necessary setup steps to this file: 10 | 11 | puts "== Installing dependencies ==" 12 | system "gem install bundler --conservative" 13 | system "bundle check || bundle install" 14 | 15 | # puts "\n== Copying sample files ==" 16 | # unless File.exist?("config/database.yml") 17 | # system "cp config/database.yml.sample config/database.yml" 18 | # end 19 | 20 | puts "\n== Preparing database ==" 21 | system "bin/rake db:setup" 22 | 23 | puts "\n== Removing old logs and tempfiles ==" 24 | system "rm -f log/*" 25 | system "rm -rf tmp/cache" 26 | 27 | puts "\n== Restarting application server ==" 28 | system "touch tmp/restart.txt" 29 | end 30 | -------------------------------------------------------------------------------- /bin/spring: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # This file loads spring without using Bundler, in order to be fast. 4 | # It gets overwritten when you run the `spring binstub` command. 5 | 6 | unless defined?(Spring) 7 | require "rubygems" 8 | require "bundler" 9 | 10 | if match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m) 11 | Gem.paths = { "GEM_PATH" => [Bundler.bundle_path.to_s, *Gem.path].uniq } 12 | gem "spring", match[1] 13 | require "spring/binstub" 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require ::File.expand_path('../config/environment', __FILE__) 4 | run Rails.application 5 | -------------------------------------------------------------------------------- /config/application.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../boot', __FILE__) 2 | 3 | require 'pp' 4 | require 'rails/all' 5 | 6 | # Require the gems listed in Gemfile, including any gems 7 | # you've limited to :test, :development, or :production. 8 | Bundler.require(*Rails.groups) 9 | 10 | module Refresher 11 | class Application < Rails::Application 12 | # Settings in config/environments/* take precedence over those specified here. 13 | # Application configuration should go into files in config/initializers 14 | # -- all .rb files in that directory are automatically loaded. 15 | 16 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. 17 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. 18 | # config.time_zone = 'Central Time (US & Canada)' 19 | 20 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. 21 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] 22 | # config.i18n.default_locale = :de 23 | 24 | # Do not swallow errors in after_commit/after_rollback callbacks. 25 | config.active_record.raise_in_transactional_callbacks = true 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 2 | 3 | require 'bundler/setup' # Set up gems listed in the Gemfile. 4 | -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: postgresql 3 | database: enhancer 4 | pool: 5 5 | timeout: 5000 6 | 7 | test: 8 | adapter: sqlite3 9 | database: db/test.sqlite3 10 | pool: 5 11 | timeout: 5000 12 | 13 | production: 14 | adapter: postgresql 15 | database: my_database_production 16 | pool: 5 17 | timeout: 5000 18 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require File.expand_path('../application', __FILE__) 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /config/environments/development.rb: -------------------------------------------------------------------------------- 1 | # Helps foreman output Rails logging immediately instead of buffering it 2 | $stdout.sync = true 3 | 4 | Rails.application.configure do 5 | # Settings specified here will take precedence over those in config/application.rb. 6 | 7 | # In the development environment your application's code is reloaded on 8 | # every request. This slows down response time but is perfect for development 9 | # since you don't have to restart the web server when you make code changes. 10 | config.cache_classes = false 11 | 12 | # Do not eager load code on boot. 13 | config.eager_load = false 14 | 15 | # Show full error reports and disable caching. 16 | config.consider_all_requests_local = true 17 | config.action_controller.perform_caching = false 18 | 19 | # Don't care if the mailer can't send. 20 | config.action_mailer.raise_delivery_errors = false 21 | 22 | # Print deprecation notices to the Rails logger. 23 | config.active_support.deprecation = :log 24 | 25 | # Raise an error on page load if there are pending migrations. 26 | config.active_record.migration_error = :page_load 27 | 28 | # Debug mode disables concatenation and preprocessing of assets. 29 | # This option may cause significant delays in view rendering with a large 30 | # number of complex assets. 31 | config.assets.debug = true 32 | 33 | # Asset digests allow you to set far-future HTTP expiration dates on all assets, 34 | # yet still be able to expire them through the digest params. 35 | config.assets.digest = true 36 | 37 | # Adds additional error checking when serving assets at runtime. 38 | # Checks for improperly declared sprockets dependencies. 39 | # Raises helpful error messages. 40 | config.assets.raise_runtime_errors = true 41 | 42 | # Raises error for missing translations 43 | # config.action_view.raise_on_missing_translations = true 44 | end 45 | -------------------------------------------------------------------------------- /config/environments/production.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # Code is not reloaded between requests. 5 | config.cache_classes = true 6 | 7 | # Eager load code on boot. This eager loads most of Rails and 8 | # your application in memory, allowing both threaded web servers 9 | # and those relying on copy on write to perform better. 10 | # Rake tasks automatically ignore this option for performance. 11 | config.eager_load = true 12 | 13 | # Full error reports are disabled and caching is turned on. 14 | config.consider_all_requests_local = false 15 | config.action_controller.perform_caching = true 16 | 17 | # Enable Rack::Cache to put a simple HTTP cache in front of your application 18 | # Add `rack-cache` to your Gemfile before enabling this. 19 | # For large-scale production use, consider using a caching reverse proxy like 20 | # NGINX, varnish or squid. 21 | # config.action_dispatch.rack_cache = true 22 | 23 | # Disable serving static files from the `/public` folder by default since 24 | # Apache or NGINX already handles this. 25 | config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present? 26 | 27 | # Compress JavaScripts and CSS. 28 | config.assets.js_compressor = :uglifier 29 | # config.assets.css_compressor = :sass 30 | 31 | # Do not fallback to assets pipeline if a precompiled asset is missed. 32 | config.assets.compile = false 33 | 34 | # Asset digests allow you to set far-future HTTP expiration dates on all assets, 35 | # yet still be able to expire them through the digest params. 36 | config.assets.digest = true 37 | 38 | # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb 39 | 40 | # Specifies the header that your server uses for sending files. 41 | # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache 42 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX 43 | 44 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. 45 | # config.force_ssl = true 46 | 47 | # Use the lowest log level to ensure availability of diagnostic information 48 | # when problems arise. 49 | config.log_level = :debug 50 | 51 | # Prepend all log lines with the following tags. 52 | # config.log_tags = [ :subdomain, :uuid ] 53 | 54 | # Use a different logger for distributed setups. 55 | # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) 56 | 57 | # Use a different cache store in production. 58 | # config.cache_store = :mem_cache_store 59 | 60 | # Enable serving of images, stylesheets, and JavaScripts from an asset server. 61 | # config.action_controller.asset_host = 'http://assets.example.com' 62 | 63 | # Ignore bad email addresses and do not raise email delivery errors. 64 | # Set this to true and configure the email server for immediate delivery to raise delivery errors. 65 | # config.action_mailer.raise_delivery_errors = false 66 | 67 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to 68 | # the I18n.default_locale when a translation cannot be found). 69 | config.i18n.fallbacks = true 70 | 71 | # Send deprecation notices to registered listeners. 72 | config.active_support.deprecation = :notify 73 | 74 | # Use default logging formatter so that PID and timestamp are not suppressed. 75 | config.log_formatter = ::Logger::Formatter.new 76 | 77 | # Do not dump schema after migrations. 78 | config.active_record.dump_schema_after_migration = false 79 | end 80 | -------------------------------------------------------------------------------- /config/environments/test.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # The test environment is used exclusively to run your application's 5 | # test suite. You never need to work with it otherwise. Remember that 6 | # your test database is "scratch space" for the test suite and is wiped 7 | # and recreated between test runs. Don't rely on the data there! 8 | config.cache_classes = true 9 | 10 | # Do not eager load code on boot. This avoids loading your whole application 11 | # just for the purpose of running a single test. If you are using a tool that 12 | # preloads Rails for running tests, you may have to set it to true. 13 | config.eager_load = false 14 | 15 | # Configure static file server for tests with Cache-Control for performance. 16 | config.serve_static_files = true 17 | config.static_cache_control = 'public, max-age=3600' 18 | 19 | # Show full error reports and disable caching. 20 | config.consider_all_requests_local = true 21 | config.action_controller.perform_caching = false 22 | 23 | # Raise exceptions instead of rendering exception templates. 24 | config.action_dispatch.show_exceptions = false 25 | 26 | # Disable request forgery protection in test environment. 27 | config.action_controller.allow_forgery_protection = false 28 | 29 | # Tell Action Mailer not to deliver emails to the real world. 30 | # The :test delivery method accumulates sent emails in the 31 | # ActionMailer::Base.deliveries array. 32 | config.action_mailer.delivery_method = :test 33 | 34 | # Randomize the order test cases are executed. 35 | config.active_support.test_order = :random 36 | 37 | # Print deprecation notices to the stderr. 38 | config.active_support.deprecation = :stderr 39 | 40 | # Raises error for missing translations 41 | # config.action_view.raise_on_missing_translations = true 42 | end 43 | -------------------------------------------------------------------------------- /config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Version of your assets, change this if you want to expire all your assets. 4 | Rails.application.config.assets.version = '1.0' 5 | 6 | # Add additional assets to the asset load path 7 | # Rails.application.config.assets.paths << Emoji.images_path 8 | 9 | # Precompile additional assets. 10 | # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. 11 | # Rails.application.config.assets.precompile += %w( search.js ) 12 | -------------------------------------------------------------------------------- /config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.action_dispatch.cookies_serializer = :json 4 | -------------------------------------------------------------------------------- /config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [:password] 5 | -------------------------------------------------------------------------------- /config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, '\1en' 8 | # inflect.singular /^(ox)en/i, '\1' 9 | # inflect.irregular 'person', 'people' 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym 'RESTful' 16 | # end 17 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | -------------------------------------------------------------------------------- /config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.session_store :cookie_store, key: '_refresher_session' 4 | -------------------------------------------------------------------------------- /config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] if respond_to?(:wrap_parameters) 9 | end 10 | 11 | # To enable root element in JSON for ActiveRecord objects. 12 | # ActiveSupport.on_load(:active_record) do 13 | # self.include_root_in_json = true 14 | # end 15 | -------------------------------------------------------------------------------- /config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization 2 | # and are automatically loaded by Rails. If you want to use locales other 3 | # than English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t 'hello' 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t('hello') %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # To learn more, please read the Rails Internationalization guide 20 | # available at http://guides.rubyonrails.org/i18n.html. 21 | 22 | en: 23 | hello: "Hello world" 24 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | resources :bacons 3 | 4 | root to: 'bacons#stats' 5 | get 'index' => 'bacons#stats' 6 | post 'did_launch' => 'bacons#did_launch' 7 | get 'stability' => 'stability#index' 8 | get 'okrs' => 'stability#okrs' 9 | end 10 | -------------------------------------------------------------------------------- /config/secrets.yml: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Your secret key is used for verifying the integrity of signed cookies. 4 | # If you change this key, all old signed cookies will become invalid! 5 | 6 | # Make sure the secret is at least 30 characters and all random, 7 | # no regular words or you'll be exposed to dictionary attacks. 8 | # You can use `rake secret` to generate a secure secret key. 9 | 10 | # Make sure the secrets in this file are kept private 11 | # if you're sharing your code publicly. 12 | 13 | development: 14 | secret_key_base: 8671db248b9f290fa66938b0f19f5e1d0c6d97e20954937cbc2bace56e9c61240a5f25207517cf17e2e91428e30d7c07fefafa67349e30f8564dbd6f1658151d 15 | 16 | test: 17 | secret_key_base: a97278c93179043d1e3ceef5a0619c5a9b05c14f5ff642efe837c6804c012c0d89ae571c5349b1bdd787de57072d088f64ea9478b1c65623400f2a74d115b265 18 | 19 | # Do not keep production secrets in the repository, 20 | # instead read values from the environment. 21 | production: 22 | secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> -------------------------------------------------------------------------------- /db/migrate/20150413194641_create_bacons.rb: -------------------------------------------------------------------------------- 1 | class CreateBacons < ActiveRecord::Migration 2 | def change 3 | create_table :bacons do |t| 4 | t.string :action_name 5 | t.date :launch_date 6 | t.integer :launches 7 | t.integer :number_errors 8 | 9 | t.timestamps null: false 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20160509194220_add_tool_version_and_number_crashes_to_bacons.rb: -------------------------------------------------------------------------------- 1 | class AddToolVersionAndNumberCrashesToBacons < ActiveRecord::Migration 2 | def up 3 | add_column :bacons, :tool_version, :string, default: 'unknown', null: false, limit: 50 4 | add_column :bacons, :number_crashes, :integer, default: 0, null: false 5 | 6 | change_column :bacons, :number_errors, :integer, default: 0, null: false 7 | change_column :bacons, :launches, :integer, default: 0, null: false 8 | change_column :bacons, :action_name, :string, null: false, limit: 255 9 | change_column :bacons, :launch_date, :date, null: false 10 | end 11 | 12 | def down 13 | remove_column :bacons, :tool_version, :string, limit: nil 14 | remove_column :bacons, :number_crashes, :integer 15 | 16 | change_column :bacons, :number_errors, :integer, default: nil, null: true 17 | change_column :bacons, :launches, :integer, default: nil, null: true 18 | change_column :bacons, :action_name, :string, null: true, limit: nil 19 | change_column :bacons, :launch_date, :date, null: true 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /db/migrate/20170427183242_add_index_to_bacons.rb: -------------------------------------------------------------------------------- 1 | class AddIndexToBacons < ActiveRecord::Migration 2 | def change 3 | add_index :bacons, [:action_name, :launch_date, :tool_version] 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/schema.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | # This file is auto-generated from the current state of the database. Instead 3 | # of editing this file, please use the migrations feature of Active Record to 4 | # incrementally modify your database, and then regenerate this schema definition. 5 | # 6 | # Note that this schema.rb definition is the authoritative source for your 7 | # database schema. If you need to create the application database on another 8 | # system, you should be using db:schema:load, not running all the migrations 9 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations 10 | # you'll amass, the slower it'll run and the greater likelihood for issues). 11 | # 12 | # It's strongly recommended that you check this file into your version control system. 13 | 14 | ActiveRecord::Schema.define(version: 20170427183242) do 15 | 16 | # These are extensions that must be enabled in order to support this database 17 | enable_extension "plpgsql" 18 | 19 | create_table "bacons", force: :cascade do |t| 20 | t.string "action_name", limit: 255, null: false 21 | t.date "launch_date", null: false 22 | t.integer "launches", default: 0, null: false 23 | t.integer "number_errors", default: 0, null: false 24 | t.datetime "created_at", null: false 25 | t.datetime "updated_at", null: false 26 | t.string "tool_version", limit: 50, default: "unknown", null: false 27 | t.integer "number_crashes", default: 0, null: false 28 | end 29 | 30 | add_index "bacons", ["action_name", "launch_date", "tool_version"], name: "index_bacons_on_action_name_and_launch_date_and_tool_version", using: :btree 31 | 32 | end 33 | -------------------------------------------------------------------------------- /db/seeds.rb: -------------------------------------------------------------------------------- 1 | # This file should contain all the record creation needed to seed the database with its default values. 2 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). 3 | # 4 | # Examples: 5 | # 6 | # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }]) 7 | # Mayor.create(name: 'Emanuel', city: cities.first) 8 | -------------------------------------------------------------------------------- /lib/assets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastlane-old/enhancer/d041a2ad01d52d56ce48c77ce8c886ab16837abd/lib/assets/.keep -------------------------------------------------------------------------------- /lib/tasks/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastlane-old/enhancer/d041a2ad01d52d56ce48c77ce8c886ab16837abd/lib/tasks/.keep -------------------------------------------------------------------------------- /public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The page you were looking for doesn't exist (404) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The page you were looking for doesn't exist.

62 |

You may have mistyped the address or the page may have moved.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /public/422.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The change you wanted was rejected (422) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The change you wanted was rejected.

62 |

Maybe you tried to change something you didn't have access to.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /public/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | We're sorry, but something went wrong (500) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

We're sorry, but something went wrong.

62 |
63 |

If you are the application owner check the logs for more information.

64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastlane-old/enhancer/d041a2ad01d52d56ce48c77ce8c886ab16837abd/public/favicon.ico -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | # 3 | # To ban all spiders from the entire site uncomment the next two lines: 4 | # User-agent: * 5 | # Disallow: / 6 | -------------------------------------------------------------------------------- /vendor/assets/javascripts/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastlane-old/enhancer/d041a2ad01d52d56ce48c77ce8c886ab16837abd/vendor/assets/javascripts/.keep -------------------------------------------------------------------------------- /vendor/assets/stylesheets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastlane-old/enhancer/d041a2ad01d52d56ce48c77ce8c886ab16837abd/vendor/assets/stylesheets/.keep --------------------------------------------------------------------------------