├── .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 |
15 |
16 | -------
17 |
18 | enhancer
19 | ============
20 |
21 | [](https://twitter.com/FastlaneTools)
22 | [](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 |
3 | Error rate
4 |
5 |
6 |
7 |
24 |
25 |
--------------------------------------------------------------------------------
/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 |
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 | |
38 |
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 | |
54 |
55 |
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 |
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 | Metric | Goal | Actual |
12 |
13 |
14 |
15 |
16 | Number of tools being stable |
17 | <%= @okr_status_tools[:goal] %> |
18 |
19 | <%= @okr_status_tools[:actual] %>
20 | |
21 |
22 |
23 | Number of actions being stable |
24 | <%= @okr_status_actions[:goal] %> |
25 |
26 | <%= @okr_status_actions[:actual] %>
27 | |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | Tool | Goal Stability | Actual Stability | State |
37 |
38 |
39 |
40 | <% @okrs_tools.each do |okr| %>
41 |
42 | <%= okr[:action_name] %> |
43 | <%= okr[:goal_value] %> |
44 | <%= okr[:actual_value] %> |
45 | <%= okr[:emoji] %> |
46 |
47 | <% end %>
48 |
49 |
50 |
51 |
52 |
53 | Action | Goal Stability | Actual Stability | State |
54 |
55 |
56 |
57 | <% @okrs_actions.each do |okr| %>
58 |
59 | <%= okr[:action_name] %> |
60 | <%= okr[:goal_value] %> |
61 | <%= okr[:actual_value] %> |
62 | <%= okr[:emoji] %> |
63 |
64 | <% end %>
65 |
66 |
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
--------------------------------------------------------------------------------