app_drone 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. data/.gitignore +17 -0
  2. data/Gemfile +4 -0
  3. data/Gemfile~ +4 -0
  4. data/LICENSE +22 -0
  5. data/README.md +205 -0
  6. data/README.md~ +205 -0
  7. data/Rakefile +11 -0
  8. data/Rakefile~ +11 -0
  9. data/TODO~ +7 -0
  10. data/app_drone.gemspec +20 -0
  11. data/app_drone.gemspec~ +20 -0
  12. data/lib/app_drone/drone.rb +81 -0
  13. data/lib/app_drone/drone.rb~ +81 -0
  14. data/lib/app_drone/drones/bundle/bundle.rb +23 -0
  15. data/lib/app_drone/drones/bundle/bundle.rb~ +23 -0
  16. data/lib/app_drone/drones/bundle/gem.rb~ +23 -0
  17. data/lib/app_drone/drones/bundle/gem_entries.erb +6 -0
  18. data/lib/app_drone/drones/bundle/gem_entries.erb~ +6 -0
  19. data/lib/app_drone/drones/bundle/gems.rb~ +23 -0
  20. data/lib/app_drone/drones/cleanup/cleanup.erb +3 -0
  21. data/lib/app_drone/drones/cleanup/cleanup.rb +9 -0
  22. data/lib/app_drone/drones/cleanup/cleanup.rb~ +9 -0
  23. data/lib/app_drone/drones/javascript/application_coffee.erb +12 -0
  24. data/lib/app_drone/drones/javascript/javascript.rb +25 -0
  25. data/lib/app_drone/drones/javascript/javascript.rb~ +25 -0
  26. data/lib/app_drone/drones/javascript/javascripts.rb~ +23 -0
  27. data/lib/app_drone/drones/slim_view/application_slim.erb +15 -0
  28. data/lib/app_drone/drones/slim_view/slim_view.rb +15 -0
  29. data/lib/app_drone/drones/slim_view/slim_view.rb~ +15 -0
  30. data/lib/app_drone/drones/slim_view/slim_views.rb~ +14 -0
  31. data/lib/app_drone/drones/stylesheet/application_sass.erb +12 -0
  32. data/lib/app_drone/drones/stylesheet/application_sass.erb~ +12 -0
  33. data/lib/app_drone/drones/stylesheet/stylesheet.rb +29 -0
  34. data/lib/app_drone/drones/stylesheet/stylesheet.rb~ +29 -0
  35. data/lib/app_drone/drones/stylesheet/stylesheets.rb~ +30 -0
  36. data/lib/app_drone/drones/zzz/bootstrap/bootstrap.rb +29 -0
  37. data/lib/app_drone/drones/zzz/bootstrap/bootstrap.rb~ +29 -0
  38. data/lib/app_drone/drones/zzz/chosen/chosen.rb +13 -0
  39. data/lib/app_drone/drones/zzz/chosen/chosen.rb~ +13 -0
  40. data/lib/app_drone/drones/zzz/factory_girl/factory_girl.rb +13 -0
  41. data/lib/app_drone/drones/zzz/factory_girl/factory_girl.rb~ +13 -0
  42. data/lib/app_drone/drones/zzz/git/git.rb +9 -0
  43. data/lib/app_drone/drones/zzz/git/git.rb~ +8 -0
  44. data/lib/app_drone/drones/zzz/git/install.erb +3 -0
  45. data/lib/app_drone/drones/zzz/guard/guard.rb +16 -0
  46. data/lib/app_drone/drones/zzz/guard/guard.rb~ +15 -0
  47. data/lib/app_drone/drones/zzz/ranked_model/ranked_model.rb +9 -0
  48. data/lib/app_drone/drones/zzz/ranked_model/ranked_model.rb~ +9 -0
  49. data/lib/app_drone/drones/zzz/rspec/install.erb +1 -0
  50. data/lib/app_drone/drones/zzz/rspec/rspec.rb +13 -0
  51. data/lib/app_drone/drones/zzz/rspec/rspec.rb~ +13 -0
  52. data/lib/app_drone/drones/zzz/simple_form/install.erb +1 -0
  53. data/lib/app_drone/drones/zzz/simple_form/simple_form.rb +15 -0
  54. data/lib/app_drone/drones/zzz/simple_form/simple_form.rb~ +15 -0
  55. data/lib/app_drone/integration.rb~ +48 -0
  56. data/lib/app_drone/object_extensions.rb +11 -0
  57. data/lib/app_drone/object_extensions.rb~ +5 -0
  58. data/lib/app_drone/template.erb +33 -0
  59. data/lib/app_drone/template.erb~ +33 -0
  60. data/lib/app_drone/template.rb +62 -0
  61. data/lib/app_drone/template.rb~ +62 -0
  62. data/lib/app_drone/version.rb +3 -0
  63. data/lib/app_drone/version.rb~ +3 -0
  64. data/lib/app_drone.rb +17 -0
  65. data/lib/app_drone.rb~ +17 -0
  66. data/out.rb +93 -0
  67. data/test/app_drone_test.rb~ +19 -0
  68. data/test/test_app_drone.rb +30 -0
  69. data/test/test_app_drone.rb~ +30 -0
  70. metadata +128 -0
@@ -0,0 +1,23 @@
1
+ # Complete!
2
+ module AppDrone
3
+ class Bundle < Drone
4
+ desc "Manages gem installations"
5
+ owns_generator_method :gemfile
6
+
7
+ attr_accessor :gems
8
+ @@gem = Struct.new('Gem', :name, :opts)
9
+
10
+ def setup
11
+ self.gems = []
12
+ end
13
+
14
+ def add(g,*opts)
15
+ self.gems << @@gem.new(g,*opts)
16
+ end
17
+
18
+ def execute
19
+ do! :gem_entries
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # Complete!
2
+ module AppDrone
3
+ class Bundle < Drone
4
+ desc "Manages gem installations"
5
+ owns_generator_method :gemfile
6
+
7
+ attr_accessor :gems
8
+ @@gem = Struct.new('Gem', :name, :opts)
9
+
10
+ def setup
11
+ self.gems = []
12
+ end
13
+
14
+ def add(g,*opts)
15
+ self.gems << @@gem.new(g,*opts)
16
+ end
17
+
18
+ def execute
19
+ do! :gem_entries
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # Complete!
2
+ module AppDrone
3
+ class Gems < Drone
4
+ desc "Manages gem installations"
5
+ owns_generator_method :gemfile
6
+
7
+ attr_accessor :gems
8
+ @@gem = Struct.new('Gem', :name, :opts)
9
+
10
+ def setup
11
+ self.gems = []
12
+ end
13
+
14
+ def add(g,*opts)
15
+ self.gems << @@gem.new(g,*opts)
16
+ end
17
+
18
+ def execute
19
+ do! :gem_entries
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,6 @@
1
+ <% gems.each { |g| %>@generator.gem '<%= g.name %>'<%= g.opts.to_s.gsub('{',', ').gsub('}','') %>
2
+ <% } %>
3
+ run_bundle
4
+ @generator.options = @generator.options.dup
5
+ @generator.options[:skip_bundle] = true
6
+ @generator.options.freeze
@@ -0,0 +1,6 @@
1
+ <% gems.each { |g| %>@generator.gem '<%= g.name %>'<%= g.opts.to_s.gsub('{',', ').gsub('}','') %>
2
+ <% } %>
3
+ run_bundle
4
+ @generator.options = @generator.options.dup
5
+ @generator.options[:skip_bundle] = true
6
+ @generator.options.freeze
@@ -0,0 +1,23 @@
1
+ # Complete!
2
+ module AppDrone
3
+ class Gems < Drone
4
+ desc "Manages gem installations"
5
+ owns_generator_method :gemfile
6
+
7
+ attr_accessor :gems
8
+ @@gem = Struct.new('Gem', :name, :opts)
9
+
10
+ def setup
11
+ self.gems = []
12
+ end
13
+
14
+ def add(g,*opts)
15
+ self.gems << @@gem.new(g,*opts)
16
+ end
17
+
18
+ def execute
19
+ do! :gem_entries
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,3 @@
1
+ @generator.remove_file File.join %w(public index.html)
2
+ @generator.remove_file File.join %w(app assets images rails.png)
3
+ @generator.remove_file File.join %w(README.rdoc)
@@ -0,0 +1,9 @@
1
+ # Complete!
2
+ module AppDrone
3
+ class Cleanup < Drone
4
+ desc "Removes some default Rails files that aren't very useful"
5
+ def execute
6
+ do! :cleanup
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # Complete!
2
+ module AppDrone
3
+ class Cleanup < Drone
4
+ desc "Removes some default Rails files that aren't very useful"
5
+ def execute
6
+ do! :cleanup
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ js_asset_path = File.join %w(app assets javascripts application.js)
2
+ @generator.remove_file(js_asset_path)
3
+ @coffee_asset_path = File.join %w(app assets javascripts application.js.coffee)
4
+ @generator.create_file @coffee_asset_path, <<-COFFEE
5
+ <% requires.each { |r| %>//= require <%= r %>
6
+ <% } %>//= require_tree .
7
+
8
+ $(document).ready ->
9
+ <% onreadies.each { |r| %><%= r %>
10
+ <% } %>
11
+
12
+ COFFEE
@@ -0,0 +1,25 @@
1
+ # Incomplete
2
+ module AppDrone
3
+ class Javascript < Drone
4
+ desc "Generates application.js.coffee with manifest options and jQuery load hooks"
5
+ attr_accessor :requires, :onreadies
6
+
7
+ def setup
8
+ self.requires = []
9
+ self.onreadies = []
10
+ self.add_require 'jquery'
11
+ self.add_require 'jquery_ujs'
12
+
13
+ # TODO ui gem / vendor (for customisation)
14
+ # self.add_require 'jquery-ui'
15
+ end
16
+
17
+ def add_require(r); self.requires << r end
18
+ def add_onready(r); self.onreadies << r end
19
+
20
+ def execute
21
+ do! :application_coffee
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ # Incomplete
2
+ module AppDrone
3
+ class Javascript < Drone
4
+ desc "Generates application.js.coffee with manifest options and jQuery load hooks"
5
+ attr_accessor :requires, :onreadies
6
+
7
+ def setup
8
+ self.requires = []
9
+ self.onreadies = []
10
+ self.add_require 'jquery'
11
+ self.add_require 'jquery_ujs'
12
+
13
+ # TODO ui gem / vendor (for customisation)
14
+ # self.add_require 'jquery-ui'
15
+ end
16
+
17
+ def add_require(r); self.requires << r end
18
+ def add_onready(r); self.onreadies << r end
19
+
20
+ def execute
21
+ do! :application_coffee
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,23 @@
1
+ # Incomplete
2
+ module AppDrone
3
+ class Javascripts < Drone
4
+ desc "Generates application.js.coffee with manifest and jQuery load hooks"
5
+ attr_accessor :requires, :onreadies
6
+
7
+ def setup
8
+ self.requires = []
9
+ self.onreadies = []
10
+ self.add_require 'jquery'
11
+ self.add_require 'jquery_ujs'
12
+ self.add_require 'jquery-ui' # TODO if ui, otherwise vendor
13
+ end
14
+
15
+ def add_require(r); self.requires << r end
16
+ def add_onready(r); self.onreadies << r end
17
+
18
+ def execute
19
+ do! :application_coffee
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,15 @@
1
+ erb_index_path = File.join %w(app views layouts application.html.erb)
2
+ @generator.remove_file(erb_index_path)
3
+ slim_index_path = File.join %w(app views layouts application.html.slim)
4
+ @generator.create_file slim_index_path, <<-SLIM
5
+ doctype 5
6
+ html
7
+ head
8
+ title #{app_name}
9
+ = stylesheet_link_tag 'application', media: 'all'
10
+ = javascript_include_tag 'application'
11
+ = csrf_meta_tags
12
+
13
+ body class=controller_name
14
+ = yield
15
+ SLIM
@@ -0,0 +1,15 @@
1
+ # Incomplete
2
+ module AppDrone
3
+ class SlimView < Drone
4
+ desc "Sets up application.html.slim with shiny goodness"
5
+ # TODO accepts :options # header etc.
6
+
7
+ def align
8
+ bundle.add 'slim-rails'
9
+ end
10
+
11
+ def execute
12
+ do! :application_slim
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # Incomplete
2
+ module AppDrone
3
+ class SlimView < Drone
4
+ desc "Sets up application.html.slim with shiny goodness"
5
+ # TODO accepts :options # header etc.
6
+
7
+ def align
8
+ gem.add 'slim-rails'
9
+ end
10
+
11
+ def execute
12
+ do! :application_slim
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ # Incomplete
2
+ module AppDrone
3
+ class SlimViews < Drone
4
+ # TODO accepts :options # header etc.
5
+
6
+ def align
7
+ (self >> Gems).add 'slim-rails'
8
+ end
9
+
10
+ def execute
11
+ do! :application_slim
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,12 @@
1
+ @css_asset_path = File.join %w(app assets stylesheets application.css)
2
+ @generator.remove_file(@css_asset_path)
3
+ @sass_asset_path = File.join %w(app assets stylesheets application.css.scss)
4
+ @generator.create_file @sass_asset_path, <<-SASS
5
+ /*
6
+ <% requires.each { |r| %>/*= require <%= r %>
7
+ <% } %>/*= require_self
8
+ */
9
+
10
+ <% imports.each { |i| %>@import '<%= i %>';
11
+ <% } %>
12
+ SASS
@@ -0,0 +1,12 @@
1
+ @css_asset_path = File.join %w(app assets stylesheets application.css)
2
+ @generator.remove_file(@css_asset_path)
3
+ @sass_asset_path = File.join %w(app assets stylesheets application.css.scss)
4
+ @generator.create_file @sass_asset_path, <<-SASS
5
+ /*
6
+ <% requires.each { |r| %>/*= require <%= r %>
7
+ <% } %>/*= require_self
8
+ */
9
+
10
+ <% imports.each { |i| %>@import '<%= i %>';
11
+ <% } %>
12
+ SASS
@@ -0,0 +1,29 @@
1
+ # Incomplete
2
+ module AppDrone
3
+ class Stylesheet < Drone
4
+ desc "Generates application.css.sass with manifest options and imports"
5
+ # TODO are manifests necessary? Favor @import
6
+
7
+ attr_accessor :requires, :imports
8
+ def add_require(r); self.requires << r end
9
+ def add_import(i); self.imports << i end
10
+
11
+ def setup
12
+ self.requires = []
13
+ self.imports = []
14
+ end
15
+
16
+ def align
17
+ bundle.add 'therubyracer'
18
+ bundle.add 'compass-rails'
19
+ self.add_import 'compass'
20
+ end
21
+
22
+ def execute
23
+ do! :application_sass
24
+ # TODO currently using .scss and not .sass, switch to the cleaner syntax
25
+ # TODO render css utils (or make this a separate integration)
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ # Incomplete
2
+ module AppDrone
3
+ class Stylesheet < Drone
4
+ desc "Generates application.css.sass with manifest options and imports"
5
+ # TODO are manifests necessary? Favor @import
6
+
7
+ attr_accessor :requires, :imports
8
+ def add_require(r); self.requires << r end
9
+ def add_import(i); self.imports << i end
10
+
11
+ def setup
12
+ self.requires = []
13
+ self.imports = []
14
+ end
15
+
16
+ def align
17
+ bundle.add 'therubyracer'
18
+ bundle.add 'compass-rails'
19
+ self.add_import 'compass'
20
+ end
21
+
22
+ def execute
23
+ do! :application_sass
24
+ # TODO currently using .scss and not .sass, switch to the cleaner syntax
25
+ # TODO render css utils (or make this a separate integration)
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,30 @@
1
+ # Incomplete
2
+ module AppDrone
3
+ class Stylesheet < Drone
4
+ desc "Generates application.css.sass with manifest options and imports"
5
+ # TODO are manifests necessary? Favor @import
6
+
7
+ attr_accessor :requires, :imports
8
+
9
+ def setup
10
+ self.requires = []
11
+ self.imports = []
12
+ (self >> Gems).add 'compass-rails'
13
+ self.add_import 'compass'
14
+ end
15
+
16
+ def add_require(r); self.requires << r end
17
+ def add_import(i); self.imports << i end
18
+
19
+ def align
20
+ (self >> Gems).add 'therubyracer'
21
+ end
22
+
23
+ def execute
24
+ do! :application_sass
25
+ # TODO currently using .scss and not .sass, switch to the cleaner syntax
26
+ # TODO render css utils (or make this a separate integration)
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,29 @@
1
+ # Incomplete
2
+ module AppDrone
3
+ class Bootstrap < Drone
4
+ desc "Installs Twitter Bootstrap stylesheets and javascripts"
5
+ param :vendor, :boolean, info: 'download a local copy into the repo'
6
+ param :responsive, :boolean, info: 'include responsive grid'
7
+
8
+ depends_on :bundle, :stylesheet, :javascript
9
+
10
+ def align
11
+ bundle.add 'compass_twitter_bootstrap', group: :assets
12
+
13
+ if params[:vendor]
14
+ # TODO different require paths for stylesheet
15
+ else
16
+ stylesheet.add_import 'compass_twitter_bootstrap'
17
+ stylesheet.add_import 'compass_twitter_bootstrap_responsive' if params[:responsive]
18
+ # TODO js imports - based on options
19
+ end
20
+ end
21
+
22
+ def execute
23
+ if params[:vendor]
24
+ # TODO pull files in via github
25
+ end
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ # Incomplete
2
+ module AppDrone
3
+ class Bootstrap < Drone
4
+ desc "Installs Twitter Bootstrap stylesheets and javascripts"
5
+ param :vendor, :boolean, info: 'download a local copy into the repo'
6
+ param :responsive, :boolean, info: 'include responsive grid'
7
+
8
+ depends_on :bundle, :stylesheet, :javascript
9
+
10
+ def align
11
+ bundle.add 'compass_twitter_bootstrap', group: :assets
12
+
13
+ if params[:vendor]
14
+ # TODO different require paths for stylesheet
15
+ else
16
+ stylesheet.add_import 'compass_twitter_bootstrap'
17
+ stylesheet.add_import 'compass_twitter_bootstrap_responsive' if params[:responsive]
18
+ # TODO js imports - based on options
19
+ end
20
+ end
21
+
22
+ def execute
23
+ if params[:vendor]
24
+ # TODO pull files in via github
25
+ end
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,13 @@
1
+ # Complete!
2
+ module AppDrone
3
+ class Chosen < Drone
4
+ desc 'Installs the Chosen plugin from HarvestHQ'
5
+
6
+ def align
7
+ bundle.add 'chosen-rails'
8
+ stylesheet.add_require 'chosen'
9
+ javascript.add_require 'chosen-jquery'
10
+ javascript.add_onready "$('.chzn-select').chosen();"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # Complete!
2
+ module AppDrone
3
+ class Chosen < Drone
4
+ desc 'Installs the Chosen plugin from HarvestHQ'
5
+
6
+ def align
7
+ gem.add 'chosen-rails'
8
+ stylesheet.add_require 'chosen'
9
+ javascript.add_require 'chosen-jquery'
10
+ javascript.add_onready "$('.chzn-select').chosen();"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # Incomplete
2
+ module AppDrone
3
+ class FactoryGirl < Drone
4
+ desc "Installs Factory Girl for test fixtures"
5
+ def align
6
+ bundle.add 'factory_girl_rails', group: :test
7
+ end
8
+
9
+ def execute
10
+ #TODO insert hook into rspec
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # Incomplete
2
+ module AppDrone
3
+ class FactoryGirl < Drone
4
+ desc "Installs Factory Girl for test fixtures"
5
+ def align
6
+ gem.add 'factory_girl_rails', group: :test
7
+ end
8
+
9
+ def execute
10
+ #TODO insert hook into rspec
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ # Incomplete
2
+ module AppDrone
3
+ class Git < Drone
4
+ desc "Sets up a fresh git repo"
5
+ def execute
6
+ do! :install
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ module AppDrone
2
+ class Git < Drone
3
+ desc "Sets up a fresh git repo"
4
+ def execute
5
+ do! :install
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ git :init
2
+ git add: '.'
3
+ git commit: "-m \"AppBuilder: #{app_name}\""
@@ -0,0 +1,16 @@
1
+ # Incomplete
2
+ module AppDrone
3
+ class Guard < Drone
4
+ desc "Installs Guard & watcher scripts"
5
+ # TODO accepts :guard_ties
6
+
7
+ def align
8
+ #
9
+ end
10
+
11
+ def execute
12
+ # set up guardfile etc.
13
+ # set up files for dependencies
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ module AppDrone
2
+ class Guard < Drone
3
+ desc "Installs Guard & watcher scripts"
4
+ # TODO accepts :guard_ties
5
+
6
+ def align
7
+ #
8
+ end
9
+
10
+ def execute
11
+ # set up guardfile etc.
12
+ # set up files for dependencies
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ # Incomplete
2
+ module AppDrone
3
+ class RankedModel < Drone
4
+ desc "Installs RankedModel"
5
+ def align
6
+ bundle.add 'ranked_model'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # Incomplete
2
+ module AppDrone
3
+ class RankedModel < Drone
4
+ desc "Installs RankedModel"
5
+ def align
6
+ gem.add 'ranked_model'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1 @@
1
+ generate 'rspec:install'
@@ -0,0 +1,13 @@
1
+ # Complete?
2
+ module AppDrone
3
+ class Rspec < Drone
4
+ desc "Installs RSpec for testing"
5
+ def align
6
+ bundle.add 'rspec-rails', group: :test
7
+ end
8
+
9
+ def execute
10
+ do! :install
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # Complete?
2
+ module AppDrone
3
+ class Rspec < Drone
4
+ desc "Installs RSpec for testing"
5
+ def align
6
+ gem.add 'rspec-rails', group: :test
7
+ end
8
+
9
+ def execute
10
+ do! :install
11
+ end
12
+ end
13
+ end
@@ -0,0 +1 @@
1
+ generate "simple_form:install<%= ' --bootstrap' if @use_bootstrap %>"
@@ -0,0 +1,15 @@
1
+ # Incomplete
2
+ module AppDrone
3
+ class SimpleForm < Drone
4
+ desc "Installs SimpleForm (with custom Bootstrap integration)"
5
+ def align
6
+ bundle.add 'simple_form'
7
+ bundle.add 'country_select'
8
+ end
9
+
10
+ def execute
11
+ # TODO bootstrap cross-integration
12
+ do! :install
13
+ end
14
+ end
15
+ end