gated_release 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +6 -0
- data/CHANGELOG.md +22 -0
- data/Gemfile.lock +54 -6
- data/MIT-LICENSE +20 -0
- data/README.md +32 -1
- data/Rakefile +25 -2
- data/app/assets/config/gated_release_manifest.js +2 -0
- data/app/assets/images/gated_release/.keep +0 -0
- data/app/assets/javascripts/gated_release/application.js +13 -0
- data/app/assets/stylesheets/gated_release/application.css +15 -0
- data/app/assets/stylesheets/gated_release/gates.css +131 -0
- data/app/controllers/gated_release/application_controller.rb +5 -0
- data/app/controllers/gated_release/gates_controller.rb +47 -0
- data/app/helpers/gated_release/application_helper.rb +12 -0
- data/app/jobs/gated_release/application_job.rb +4 -0
- data/app/mailers/gated_release/application_mailer.rb +6 -0
- data/app/models/gated_release/application_record.rb +5 -0
- data/{lib → app/models}/gated_release/gate.rb +9 -2
- data/app/views/gated_release/gates/index.html.erb +64 -0
- data/app/views/layouts/gated_release/application.html.erb +18 -0
- data/config/routes.rb +11 -0
- data/gated_release.gemspec +6 -3
- data/lib/gated_release.rb +1 -1
- data/lib/gated_release/engine.rb +13 -0
- data/lib/gated_release/version.rb +1 -1
- data/lib/tasks/gated_release_tasks.rake +4 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/config/manifest.js +5 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/javascripts/cable.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/channels/application_cable/channel.rb +4 -0
- data/spec/dummy/app/channels/application_cable/connection.rb +4 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/jobs/application_job.rb +2 -0
- data/spec/dummy/app/mailers/application_mailer.rb +4 -0
- data/spec/dummy/app/models/application_record.rb +3 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
- data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +34 -0
- data/spec/dummy/bin/update +29 -0
- data/spec/dummy/config.ru +5 -0
- data/spec/dummy/config/application.rb +15 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/cable.yml +9 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +54 -0
- data/spec/dummy/config/environments/production.rb +86 -0
- data/spec/dummy/config/environments/test.rb +42 -0
- data/spec/dummy/config/initializers/application_controller_renderer.rb +6 -0
- data/spec/dummy/config/initializers/assets.rb +11 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/new_framework_defaults.rb +24 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/puma.rb +47 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/config/spring.rb +6 -0
- data/spec/dummy/db/schema.rb +15 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
- data/spec/dummy/public/apple-touch-icon.png +0 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/gated_release_spec.rb +8 -0
- data/spec/generators/install/install_generator_spec.rb +25 -0
- data/spec/models/gated_release/gate_spec.rb +293 -0
- data/spec/spec_helper.rb +36 -0
- metadata +160 -4
@@ -0,0 +1,47 @@
|
|
1
|
+
module GatedRelease
|
2
|
+
class GatesController < ApplicationController
|
3
|
+
before_filter :find_gate, except: [:index]
|
4
|
+
|
5
|
+
def index
|
6
|
+
@gates = Gate.search(params[:q] || '')
|
7
|
+
end
|
8
|
+
|
9
|
+
def close
|
10
|
+
@gate.close!
|
11
|
+
flash[:notice] = "Gate '#{@gate.name}' closed"
|
12
|
+
redirect_to action: :index
|
13
|
+
end
|
14
|
+
|
15
|
+
def open
|
16
|
+
@gate.open!
|
17
|
+
flash[:notice] = "Gate '#{@gate.name}' opened"
|
18
|
+
redirect_to action: :index
|
19
|
+
end
|
20
|
+
|
21
|
+
def limit
|
22
|
+
@gate.limit!
|
23
|
+
flash[:notice] = "Gate '#{@gate.name}' limited"
|
24
|
+
redirect_to action: :index
|
25
|
+
end
|
26
|
+
|
27
|
+
def percentage
|
28
|
+
value = params[:value].to_i
|
29
|
+
@gate.percentage!(value)
|
30
|
+
flash[:notice] = "Gate '#{@gate.name}' #{value}% open"
|
31
|
+
redirect_to action: :index
|
32
|
+
end
|
33
|
+
|
34
|
+
def allow_more
|
35
|
+
more = params[:more].to_i
|
36
|
+
@gate.allow_more!(more)
|
37
|
+
flash[:notice] = "Allowed #{more} more, for gate '#{@gate.name}'"
|
38
|
+
redirect_to action: :index
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def find_gate
|
44
|
+
@gate = Gate.find(params[:id])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require "active_record"
|
2
2
|
|
3
3
|
module GatedRelease
|
4
|
-
class Gate <
|
4
|
+
class Gate < ApplicationRecord
|
5
5
|
self.table_name = "gated_release_gates"
|
6
6
|
|
7
7
|
OPEN = 'open'
|
@@ -14,6 +14,13 @@ module GatedRelease
|
|
14
14
|
validates :state, inclusion: { in: STATES }
|
15
15
|
validates :percent_open, :inclusion => 0..100
|
16
16
|
|
17
|
+
scope :newest_first, -> { order("created_at DESC") }
|
18
|
+
|
19
|
+
def self.search(query)
|
20
|
+
query = "%#{query.tr('*','%')}%"
|
21
|
+
where('name like ?', query).newest_first
|
22
|
+
end
|
23
|
+
|
17
24
|
def self.get(name)
|
18
25
|
find_or_create_by(name: name)
|
19
26
|
end
|
@@ -60,7 +67,7 @@ module GatedRelease
|
|
60
67
|
|
61
68
|
def run_open_code(args)
|
62
69
|
get_open_code(args).call
|
63
|
-
rescue StandardError, ScriptError
|
70
|
+
rescue StandardError, ScriptError
|
64
71
|
close! if args[:close_on_error]
|
65
72
|
raise
|
66
73
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
<div id="gates">
|
2
|
+
<h2 class="gated-release-heading">Gated Releases <%= "-- Results for \"#{params[:q]}\"" unless params[:q].blank? %></h2>
|
3
|
+
<%= form_tag gates_path, method: 'GET', class: "gated-release-search-form" do %>
|
4
|
+
<%= text_field_tag :q, params[:q] %>
|
5
|
+
<%= submit_tag "Search" %>
|
6
|
+
<% end %>
|
7
|
+
<table cellspacing="0" cellpadding="0" class="gated-releases-table">
|
8
|
+
<thead>
|
9
|
+
<tr>
|
10
|
+
<th>Name</th>
|
11
|
+
<th>State</th>
|
12
|
+
<th>Attempts</th>
|
13
|
+
<th>Max Attempts</th>
|
14
|
+
<th>Open/Close</th>
|
15
|
+
<th>Limited</th>
|
16
|
+
<th>Percentage</th>
|
17
|
+
</tr>
|
18
|
+
</thead>
|
19
|
+
<tbody>
|
20
|
+
<% @gates.each_with_index do |gate, index| %>
|
21
|
+
<%= content_tag 'tr' do %>
|
22
|
+
<td><%= gate.name %></td>
|
23
|
+
<td><%= gate_state(gate) %></td>
|
24
|
+
<td><%= gate.attempts %></td>
|
25
|
+
<td><%= gate.max_attempts %></td>
|
26
|
+
<td>
|
27
|
+
<% unless gate.state == 'open' %>
|
28
|
+
<%= form_for gate, :url => open_gate_path(gate), :html => {:method => :post, style: 'float: left'} do |f| %>
|
29
|
+
<%= submit_tag 'Open Gate', :class => 'green', data: {confirm: "This will open the gate. Proceed?"} %>
|
30
|
+
<% end %>
|
31
|
+
<% end %>
|
32
|
+
<% unless gate.state == 'closed' %>
|
33
|
+
<%= form_for gate, :url => close_gate_path(gate), :html => {:method => :post} do |f| %>
|
34
|
+
<%= submit_tag 'Close Gate', :class => 'red', data: {confirm: "This will close the gate. Proceed?"} %>
|
35
|
+
<% end %>
|
36
|
+
<% end %>
|
37
|
+
</td>
|
38
|
+
<td>
|
39
|
+
<% if gate.state == 'limited' %>
|
40
|
+
<%= form_for gate, :url => allow_more_gate_path(gate), :html => {:method => :post} do |f| %>
|
41
|
+
|
42
|
+
<%= label_tag :more, "Amount to increment" %>
|
43
|
+
<%= number_field_tag :more, '', min: 1 %>
|
44
|
+
<%= submit_tag 'Allow More', :class => 'green', data: {confirm: "This will open the gate for x more executions. Proceed?"} %>
|
45
|
+
<% end %>
|
46
|
+
<% else %>
|
47
|
+
<%= form_for gate, :url => limit_gate_path(gate), :html => {:method => :post} do |f| %>
|
48
|
+
<%= submit_tag 'Limit Gate', data: {confirm: "This will set the gate to limited mode. Proceed?"} %>
|
49
|
+
<% end %>
|
50
|
+
<% end %>
|
51
|
+
</td>
|
52
|
+
<td>
|
53
|
+
<%= form_for gate, :url => percentage_gate_path(gate), :html => {:method => :post} do |f| %>
|
54
|
+
|
55
|
+
<%= label_tag :value, "Set to" %>
|
56
|
+
<%= number_field_tag :value, gate.percent_open, within: 0..100 %>
|
57
|
+
<%= submit_tag 'Percentage', data: {confirm: "This will open the gate for x% of executions. Proceed?"} %>
|
58
|
+
<% end %>
|
59
|
+
</td>
|
60
|
+
<% end %>
|
61
|
+
<% end %>
|
62
|
+
</tbody>
|
63
|
+
</table>
|
64
|
+
</div>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Gated release</title>
|
5
|
+
<%= stylesheet_link_tag "gated_release/application", media: "all" %>
|
6
|
+
<%= javascript_include_tag "gated_release/application" %>
|
7
|
+
<%= csrf_meta_tags %>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
|
11
|
+
<% flash.each do |key, value| %>
|
12
|
+
<div class="alert alert-<%= key %>"><%= value %></div>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<%= yield %>
|
16
|
+
|
17
|
+
</body>
|
18
|
+
</html>
|
data/config/routes.rb
ADDED
data/gated_release.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
lib = File.expand_path(
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
4
|
+
require "gated_release/version"
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "gated_release"
|
@@ -16,14 +16,17 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
17
|
f.match(%r{^(test|spec|features|vendor|bin)/})
|
18
18
|
end
|
19
|
+
spec.test_files = Dir["spec/**/*"]
|
20
|
+
|
19
21
|
spec.bindir = "exe"
|
20
22
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
23
|
spec.require_paths = ["lib"]
|
22
24
|
|
23
25
|
spec.add_dependency "activerecord", ">= 4.0", "< 6"
|
26
|
+
spec.add_dependency "rails", ">= 4.0", "< 6"
|
24
27
|
spec.add_development_dependency "bundler", "~> 1.14"
|
25
28
|
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
-
spec.add_development_dependency "rspec", "~> 3.0"
|
29
|
+
spec.add_development_dependency "rspec-rails", "~> 3.0"
|
27
30
|
spec.add_development_dependency "sqlite3", "~> 1.3"
|
28
31
|
spec.add_development_dependency "database_cleaner", "~> 1.5"
|
29
32
|
spec.add_development_dependency "generator_spec", "~> 0.9.0"
|
data/lib/gated_release.rb
CHANGED
data/spec/dummy/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
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. JavaScript code in this file should be added after the last require_* statement.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
//= require_tree .
|
@@ -0,0 +1,13 @@
|
|
1
|
+
// Action Cable provides the framework to deal with WebSockets in Rails.
|
2
|
+
// You can generate new channels where WebSocket features live using the rails generate channel command.
|
3
|
+
//
|
4
|
+
//= require action_cable
|
5
|
+
//= require_self
|
6
|
+
//= require_tree ./channels
|
7
|
+
|
8
|
+
(function() {
|
9
|
+
this.App || (this.App = {});
|
10
|
+
|
11
|
+
App.cable = ActionCable.createConsumer();
|
12
|
+
|
13
|
+
}).call(this);
|
@@ -0,0 +1,15 @@
|
|
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 other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Dummy</title>
|
5
|
+
<%= csrf_meta_tags %>
|
6
|
+
|
7
|
+
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
|
8
|
+
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
|
9
|
+
</head>
|
10
|
+
|
11
|
+
<body>
|
12
|
+
<%= yield %>
|
13
|
+
</body>
|
14
|
+
</html>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= yield %>
|
data/spec/dummy/bin/rake
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'pathname'
|
3
|
+
require 'fileutils'
|
4
|
+
include FileUtils
|
5
|
+
|
6
|
+
# path to your application root.
|
7
|
+
APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
|
8
|
+
|
9
|
+
def system!(*args)
|
10
|
+
system(*args) || abort("\n== Command #{args} failed ==")
|
11
|
+
end
|
12
|
+
|
13
|
+
chdir APP_ROOT do
|
14
|
+
# This script is a starting point to setup your application.
|
15
|
+
# Add necessary setup steps to this file.
|
16
|
+
|
17
|
+
puts '== Installing dependencies =='
|
18
|
+
system! 'gem install bundler --conservative'
|
19
|
+
system('bundle check') || system!('bundle install')
|
20
|
+
|
21
|
+
# puts "\n== Copying sample files =="
|
22
|
+
# unless File.exist?('config/database.yml')
|
23
|
+
# cp 'config/database.yml.sample', 'config/database.yml'
|
24
|
+
# end
|
25
|
+
|
26
|
+
puts "\n== Preparing database =="
|
27
|
+
system! 'bin/rails db:setup'
|
28
|
+
|
29
|
+
puts "\n== Removing old logs and tempfiles =="
|
30
|
+
system! 'bin/rails log:clear tmp:clear'
|
31
|
+
|
32
|
+
puts "\n== Restarting application server =="
|
33
|
+
system! 'bin/rails restart'
|
34
|
+
end
|