careacademy-runbook 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +7 -0
  2. data/.dockerignore +17 -0
  3. data/.github/workflows/ruby.yml +43 -0
  4. data/.gitignore +16 -0
  5. data/.rspec +2 -0
  6. data/.ruby-gemset +1 -0
  7. data/.ruby-version +1 -0
  8. data/Appraisals +8 -0
  9. data/CHANGELOG.md +143 -0
  10. data/CODE_OF_CONDUCT.md +74 -0
  11. data/Gemfile +6 -0
  12. data/LICENSE.txt +21 -0
  13. data/README.md +1272 -0
  14. data/Rakefile +12 -0
  15. data/TODO.md +316 -0
  16. data/bin/console +16 -0
  17. data/bin/setup +8 -0
  18. data/dockerfiles/Dockerfile-runbook +18 -0
  19. data/dockerfiles/Dockerfile-sshd +4 -0
  20. data/examples/hooks_runbook.rb +72 -0
  21. data/examples/layout_runbook.rb +26 -0
  22. data/examples/restart_nginx.rb +26 -0
  23. data/examples/simple_runbook.rb +41 -0
  24. data/examples/suppress_capture_output.rb +47 -0
  25. data/exe/runbook +5 -0
  26. data/gemfiles/.bundle/config +2 -0
  27. data/gemfiles/activesupport_5.gemfile +7 -0
  28. data/gemfiles/activesupport_6.gemfile +7 -0
  29. data/images/runbook_anatomy_diagram.png +0 -0
  30. data/images/runbook_example.gif +0 -0
  31. data/images/runbook_execution_modes.png +0 -0
  32. data/lib/hacks/ssh_kit.rb +58 -0
  33. data/lib/runbook/airbrussh_context.rb +25 -0
  34. data/lib/runbook/cli.rb +115 -0
  35. data/lib/runbook/cli_base.rb +38 -0
  36. data/lib/runbook/configuration.rb +120 -0
  37. data/lib/runbook/dsl.rb +21 -0
  38. data/lib/runbook/entities/book.rb +17 -0
  39. data/lib/runbook/entities/section.rb +7 -0
  40. data/lib/runbook/entities/setup.rb +7 -0
  41. data/lib/runbook/entities/step.rb +7 -0
  42. data/lib/runbook/entity.rb +129 -0
  43. data/lib/runbook/errors.rb +7 -0
  44. data/lib/runbook/extensions/add.rb +14 -0
  45. data/lib/runbook/extensions/description.rb +14 -0
  46. data/lib/runbook/extensions/sections.rb +19 -0
  47. data/lib/runbook/extensions/setup.rb +17 -0
  48. data/lib/runbook/extensions/shared_variables.rb +51 -0
  49. data/lib/runbook/extensions/ssh_config.rb +78 -0
  50. data/lib/runbook/extensions/statements.rb +31 -0
  51. data/lib/runbook/extensions/steps.rb +24 -0
  52. data/lib/runbook/extensions/tmux.rb +13 -0
  53. data/lib/runbook/generator.rb +38 -0
  54. data/lib/runbook/generators/base.rb +45 -0
  55. data/lib/runbook/generators/dsl_extension/dsl_extension.rb +29 -0
  56. data/lib/runbook/generators/dsl_extension/templates/dsl_extension.tt +25 -0
  57. data/lib/runbook/generators/generator/generator.rb +43 -0
  58. data/lib/runbook/generators/generator/templates/generator.tt +53 -0
  59. data/lib/runbook/generators/project/project.rb +301 -0
  60. data/lib/runbook/generators/project/templates/Gemfile.tt +6 -0
  61. data/lib/runbook/generators/project/templates/README.md.tt +29 -0
  62. data/lib/runbook/generators/project/templates/Runbookfile.tt +11 -0
  63. data/lib/runbook/generators/project/templates/base_file.rb.tt +8 -0
  64. data/lib/runbook/generators/runbook/runbook.rb +22 -0
  65. data/lib/runbook/generators/runbook/templates/runbook.tt +20 -0
  66. data/lib/runbook/generators/statement/statement.rb +18 -0
  67. data/lib/runbook/generators/statement/templates/statement.tt +34 -0
  68. data/lib/runbook/helpers/format_helper.rb +11 -0
  69. data/lib/runbook/helpers/ssh_kit_helper.rb +143 -0
  70. data/lib/runbook/helpers/tmux_helper.rb +176 -0
  71. data/lib/runbook/hooks.rb +88 -0
  72. data/lib/runbook/initializer.rb +85 -0
  73. data/lib/runbook/node.rb +33 -0
  74. data/lib/runbook/run.rb +290 -0
  75. data/lib/runbook/runner.rb +66 -0
  76. data/lib/runbook/runs/ssh_kit.rb +193 -0
  77. data/lib/runbook/statement.rb +20 -0
  78. data/lib/runbook/statements/ask.rb +12 -0
  79. data/lib/runbook/statements/assert.rb +34 -0
  80. data/lib/runbook/statements/capture.rb +14 -0
  81. data/lib/runbook/statements/capture_all.rb +14 -0
  82. data/lib/runbook/statements/command.rb +11 -0
  83. data/lib/runbook/statements/confirm.rb +10 -0
  84. data/lib/runbook/statements/description.rb +9 -0
  85. data/lib/runbook/statements/download.rb +12 -0
  86. data/lib/runbook/statements/layout.rb +10 -0
  87. data/lib/runbook/statements/note.rb +10 -0
  88. data/lib/runbook/statements/notice.rb +10 -0
  89. data/lib/runbook/statements/ruby_command.rb +9 -0
  90. data/lib/runbook/statements/tmux_command.rb +11 -0
  91. data/lib/runbook/statements/upload.rb +12 -0
  92. data/lib/runbook/statements/wait.rb +10 -0
  93. data/lib/runbook/toolbox.rb +37 -0
  94. data/lib/runbook/util/repo.rb +57 -0
  95. data/lib/runbook/util/runbook.rb +43 -0
  96. data/lib/runbook/util/sticky_hash.rb +26 -0
  97. data/lib/runbook/util/stored_pose.rb +55 -0
  98. data/lib/runbook/version.rb +3 -0
  99. data/lib/runbook/view.rb +24 -0
  100. data/lib/runbook/viewer.rb +24 -0
  101. data/lib/runbook/views/markdown.rb +117 -0
  102. data/lib/runbook.rb +140 -0
  103. data/runbook.gemspec +53 -0
  104. metadata +419 -0
@@ -0,0 +1,78 @@
1
+ module Runbook::Extensions
2
+ module SSHConfig
3
+ def self.blank_ssh_config
4
+ {
5
+ servers: [],
6
+ parallelization: {},
7
+ }
8
+ end
9
+
10
+ def ssh_config
11
+ @ssh_config ||= Runbook::Extensions::SSHConfig.blank_ssh_config
12
+ end
13
+
14
+ module DSL
15
+ def ssh_config(&block)
16
+ config = Class.new do
17
+ attr_reader :dsl
18
+ prepend Runbook::Extensions::SSHConfig
19
+ end.new
20
+ dsl_class = Runbook::DSL.class(
21
+ Runbook::Extensions::SSHConfig::DSL,
22
+ )
23
+ config.instance_variable_set(:@dsl, dsl_class.new(config))
24
+ config.dsl.instance_eval(&block)
25
+ config.ssh_config
26
+ end
27
+
28
+ def parallelization(strategy: , limit: 2, wait: 2)
29
+ parent.ssh_config[:parallelization] = {
30
+ strategy: strategy,
31
+ limit: limit,
32
+ wait: wait,
33
+ }
34
+ end
35
+
36
+ def server(server)
37
+ parent.ssh_config[:servers].clear
38
+ parent.ssh_config[:servers] << server
39
+ end
40
+
41
+ def servers(*servers)
42
+ parent.ssh_config[:servers].clear
43
+ servers.flatten.each do |server|
44
+ parent.ssh_config[:servers] << server
45
+ end
46
+ end
47
+
48
+ def path(path)
49
+ parent.ssh_config[:path] = path
50
+ end
51
+
52
+ def user(user)
53
+ parent.ssh_config[:user] = user
54
+ end
55
+
56
+ def group(group)
57
+ parent.ssh_config[:group] = group
58
+ end
59
+
60
+ def env(env)
61
+ parent.ssh_config[:env] = env
62
+ end
63
+
64
+ def umask(umask)
65
+ parent.ssh_config[:umask] = umask
66
+ end
67
+ end
68
+ end
69
+
70
+ Runbook::Entities::Step.prepend(SSHConfig)
71
+ Runbook::Entities::Step::DSL.prepend(SSHConfig::DSL)
72
+ Runbook::Entities::Section.prepend(SSHConfig)
73
+ Runbook::Entities::Section::DSL.prepend(SSHConfig::DSL)
74
+ Runbook::Entities::Setup.prepend(SSHConfig)
75
+ Runbook::Entities::Setup::DSL.prepend(SSHConfig::DSL)
76
+ Runbook::Entities::Book.prepend(SSHConfig)
77
+ Runbook::Entities::Book::DSL.prepend(SSHConfig::DSL)
78
+ end
@@ -0,0 +1,31 @@
1
+ module Runbook::Extensions
2
+ module Statements
3
+ module DSL
4
+ ruby2_keywords def method_missing(name, *args, &block)
5
+ if (klass = Statements::DSL._statement_class(name))
6
+ klass.new(*args, &block).tap do |statement|
7
+ parent.add(statement)
8
+
9
+ if statement.respond_to?(:into)
10
+ Runbook.runtime_methods << statement.into
11
+ end
12
+ end
13
+ else
14
+ super
15
+ end
16
+ end
17
+
18
+ def respond_to?(name, include_private = false)
19
+ !!(Statements::DSL._statement_class(name) || super)
20
+ end
21
+
22
+ def self._statement_class(name)
23
+ "Runbook::Statements::#{name.to_s.camelize}".constantize
24
+ rescue NameError
25
+ end
26
+ end
27
+ end
28
+
29
+ Runbook::Entities::Setup::DSL.prepend(Statements::DSL)
30
+ Runbook::Entities::Step::DSL.prepend(Statements::DSL)
31
+ end
@@ -0,0 +1,24 @@
1
+ module Runbook::Extensions
2
+ module Steps
3
+ module DSL
4
+ def step(title=nil, *tags, labels: {}, &block)
5
+ if title.is_a?(Symbol)
6
+ tags.unshift(title)
7
+ title = nil
8
+ end
9
+
10
+ Runbook::Entities::Step.new(
11
+ title,
12
+ tags: tags,
13
+ labels: labels,
14
+ ).tap do |step|
15
+ parent.add(step)
16
+ step.dsl.instance_eval(&block) if block
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ Runbook::Entities::Book::DSL.prepend(Steps::DSL)
23
+ Runbook::Entities::Section::DSL.prepend(Steps::DSL)
24
+ end
@@ -0,0 +1,13 @@
1
+ module Runbook::Extensions
2
+ module Tmux
3
+ module LayoutDSL
4
+ def layout(layout)
5
+ Runbook::Statements::Layout.new(layout).tap do |layout|
6
+ parent.add(layout)
7
+ end
8
+ end
9
+ end
10
+ end
11
+
12
+ Runbook::Entities::Book::DSL.prepend(Tmux::LayoutDSL)
13
+ end
@@ -0,0 +1,38 @@
1
+ module Runbook
2
+ class Generator < Thor
3
+ include Runbook::CLIBase
4
+ include Thor::Actions
5
+
6
+ Runbook::Generators::Base.set_base_options(self)
7
+
8
+ def self._unique_class_options(generator)
9
+ generator.class_options.values.reject do |class_option|
10
+ class_option.group == "Runtime" ||
11
+ class_option.group == "Base"
12
+ end
13
+ end
14
+
15
+ Runbook.generators.each do |generator|
16
+ desc(generator.usage, generator.description, generator.options)
17
+
18
+ long_desc(generator.long_description)
19
+
20
+ _unique_class_options(generator).each do |co|
21
+ method_option(
22
+ co.name,
23
+ desc: co.description,
24
+ required: co.required,
25
+ default: co.default,
26
+ aliases: co.aliases,
27
+ type: co.type,
28
+ banner: co.banner,
29
+ hide: co.hide,
30
+ )
31
+ end
32
+
33
+ define_method(generator.command) do |*args|
34
+ invoke(generator, args)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,45 @@
1
+ module Runbook::Generators
2
+ module Base
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ base.include(Thor::Actions)
6
+
7
+ set_base_options(base)
8
+ base.check_unknown_options!
9
+ end
10
+
11
+ def self.set_base_options(base)
12
+ base.class_option(
13
+ :root,
14
+ group: :base,
15
+ default: ".",
16
+ desc: "The root directory for your generated code",
17
+ )
18
+ base.add_runtime_options!
19
+ end
20
+
21
+ module ClassMethods
22
+ def command
23
+ self.to_s.gsub("Runbook::Generators::", "").underscore
24
+ end
25
+
26
+ def usage
27
+ args = arguments.map(&:banner).join(" ")
28
+ args += " " unless args.empty?
29
+ "#{command} #{args}[options]"
30
+ end
31
+
32
+ def description
33
+ "Generate a #{command}"
34
+ end
35
+
36
+ def long_description
37
+ description
38
+ end
39
+
40
+ def options
41
+ {}
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,29 @@
1
+ module Runbook::Generators
2
+ class DslExtension < Thor::Group
3
+ include ::Runbook::Generators::Base
4
+
5
+ source_root File.dirname(__FILE__)
6
+
7
+ def self.description
8
+ "Generate a dsl_extension for adding custom runbook DSL functionality"
9
+ end
10
+
11
+ def self.long_description
12
+ <<-LONG_DESC
13
+ This generator provides a template for extending Runbook's DSL. Using a
14
+ DSL extension, you can add custom commands to a book, section, or step
15
+ that can be used in your runbooks.
16
+ LONG_DESC
17
+ end
18
+
19
+ argument :name, desc: "The name of your dsl_extension, e.x. rollback_section"
20
+
21
+ def create_dsl_extension
22
+ target = File.join(
23
+ parent_options[:root],
24
+ "#{name.underscore}.rb",
25
+ )
26
+ template('templates/dsl_extension.tt', target)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,25 @@
1
+ # Remember to require this file in a runbook config file
2
+ # or in your project so it is available in your runbooks
3
+ # See https://github.com/braintree/runbook/tree/master/lib/runbook/extensions
4
+ # for examples of DSL extensions
5
+ module MyProject::RunbookExtensions
6
+ module <%= name.classify %>
7
+ module DSL
8
+ # def description(msg)
9
+ # Runbook::Statements::Description.new(msg).tap do |desc|
10
+ # # All DSLs can reference their parent object using
11
+ # # the parent method. This allows you to modify the
12
+ # # parent book, section, or step of the DSL
13
+ # parent.add(desc)
14
+ # end
15
+ # end
16
+ end
17
+ end
18
+
19
+ # Uncomment the below statements to add the the DSL methods to
20
+ # Book, Section, and Step DSLs respectively. Now this method can
21
+ # be called from the corresponding DSL in your runbooks
22
+ # Runbook::Entities::Book::DSL.prepend(<%= name.classify %>::DSL)
23
+ # Runbook::Entities::Section::DSL.prepend(<%= name.classify %>::DSL)
24
+ # Runbook::Entities::Step::DSL.prepend(<%= name.classify %>::DSL)
25
+ end
@@ -0,0 +1,43 @@
1
+ module Runbook::Generators
2
+ class Generator < Thor::Group
3
+ include ::Runbook::Generators::Base
4
+
5
+ source_root File.dirname(__FILE__)
6
+
7
+ def self.usage
8
+ "generator NAME [options]"
9
+ end
10
+
11
+ def self.description
12
+ "Generate a runbook generator named NAME, e.x. acme_runbook"
13
+ end
14
+
15
+ argument :name, desc: "The name of your generator for populating boilerplate"
16
+
17
+ def create_generator_directory
18
+ target = File.join(
19
+ parent_options[:root],
20
+ name.underscore,
21
+ )
22
+ empty_directory(target)
23
+ end
24
+
25
+ def create_templates_directory
26
+ target = File.join(
27
+ parent_options[:root],
28
+ name.underscore,
29
+ "templates",
30
+ )
31
+ empty_directory(target)
32
+ end
33
+
34
+ def create_generator
35
+ target = File.join(
36
+ parent_options[:root],
37
+ name.underscore,
38
+ "#{name.underscore}.rb",
39
+ )
40
+ template('templates/generator.tt', target)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,53 @@
1
+ module Runbook::Generators
2
+ # Remember to require this class in a runbook config file such as your
3
+ # Runbookfile so it can be used from the command line. Note that you cannot
4
+ # require this generator from a config file specified on the command line.
5
+ class <%= name.classify %> < Thor::Group
6
+ include ::Runbook::Generators::Base
7
+
8
+ source_root File.dirname(__FILE__)
9
+
10
+ # Uncomment this method to customize the generator's usage
11
+ # description in runbook's help description.
12
+ #
13
+ # def self.usage
14
+ # args = arguments.map(&:banner).join(" ")
15
+ # args += " " unless args.empty?
16
+ # "<%= name.underscore %> #{args}[options]"
17
+ # end
18
+
19
+ # Uncomment this method to customize the generator's
20
+ # description in runbook's help message.
21
+ #
22
+ # def self.description
23
+ # "Generate a <%= name %>"
24
+ # end
25
+
26
+ # Uncomment this method to customize the generator's
27
+ # long description in runbook's help message.
28
+ #
29
+ # def self.long_description
30
+ # <<-LONG_DESC
31
+ # Here you can fully describe the options of your generator.
32
+ # LONG_DESC
33
+ # end
34
+
35
+ # Argument example
36
+ # argument :name, desc: "The name of your <%= name.underscore %>, e.x. deploy_nginx"
37
+
38
+ # Option example
39
+ # class_option :include-readme, default: true, type: :boolean
40
+
41
+ # Example of a generator step
42
+ # See: https://github.com/erikhuda/thor/wiki/Generators
43
+ # for further documentation on using thor generators.
44
+ #
45
+ # def create_<%= name.underscore %>
46
+ # target = File.join(
47
+ # parent_options[:root],
48
+ # "#{name.underscore}.rb",
49
+ # )
50
+ # template('templates/<%= name.underscore %>.tt', target)
51
+ # end
52
+ end
53
+ end
@@ -0,0 +1,301 @@
1
+ module Runbook::Generators
2
+ class Project < Thor::Group
3
+ include ::Runbook::Generators::Base
4
+
5
+ source_root File.dirname(__FILE__)
6
+
7
+ def self.description
8
+ "Generate a project for your runbooks"
9
+ end
10
+
11
+ def self.long_description
12
+ <<-LONG_DESC
13
+ This generator generates a project for your runbooks. It creates a
14
+ project skeleton to hold your runbooks, runbook extensions, shared
15
+ code, configuration, tests, and dependencies.
16
+ LONG_DESC
17
+ end
18
+
19
+ argument :name, desc: "The name of your project, e.x. acme_runbooks"
20
+
21
+ class_option :"shared-lib-dir", type: :string,
22
+ desc: "Target directory for shared runbook code"
23
+ class_option :test, type: :string, enum: ["rspec", "minitest"],
24
+ default: "rspec", desc: %Q{Test-suite, "rspec" or "minitest"}
25
+ class_option :ci, type: :string, enum: ["github", "travis", "gitlab", "circle"],
26
+ default: "github", desc: %Q{CI Service, "github", "travis", "gitlab", or "circle"}
27
+
28
+ def init_gem
29
+ bundle_exists = "which bundle 2>&1 1>/dev/null"
30
+ raise "Please ensure bundle is installed" unless system(bundle_exists)
31
+ bundler_version = Gem::Version.new(Bundler::VERSION)
32
+
33
+ inside(parent_options[:root]) do
34
+ test = "--test #{options[:test]}"
35
+ ci = "--ci #{options[:ci]}"
36
+ changelog = "--no-changelog" if bundler_version >= Gem::Version.new("2.2.8")
37
+ continue = (
38
+ run("bundle gem #{_name} #{test} #{ci} --rubocop #{changelog} --no-coc --no-mit") ||
39
+ options[:pretend]
40
+ )
41
+ exit 1 unless continue
42
+ end
43
+ end
44
+
45
+ def remove_unneeded_files
46
+ dirs = [
47
+ parent_options[:root],
48
+ _name,
49
+ ]
50
+
51
+ gemspec_file = File.join(*dirs, "#{_name}.gemspec")
52
+ if File.exist?(gemspec_file)
53
+ @gemspec_file_contents = File.readlines(gemspec_file)
54
+ end
55
+ remove_file(gemspec_file)
56
+
57
+ readme = File.join(*dirs, "README.md")
58
+ remove_file(readme)
59
+
60
+ gemfile = File.join(*dirs, "Gemfile")
61
+ if File.exist?(gemfile)
62
+ @gemfile_file_contents = File.readlines(gemfile)
63
+ end
64
+ remove_file(gemfile)
65
+
66
+ base_file = File.join(*dirs, "lib", "#{_name}.rb")
67
+ remove_file(base_file)
68
+
69
+ version_file_path = [
70
+ "lib",
71
+ _name,
72
+ "version.rb",
73
+ ]
74
+ version_file = File.join(*dirs, *version_file_path)
75
+ remove_file(version_file)
76
+ end
77
+
78
+ def shared_lib_dir
79
+ msg = [
80
+ "Where should shared runbook code live?",
81
+ "Use `lib/#{_name}` for runbook-only projects",
82
+ "Use `lib/#{_name}/runbook` for projects used for non-runbook tasks",
83
+ "Shared runbook code path:",
84
+ ]
85
+
86
+ if options.has_key?("shared-lib-dir")
87
+ @shared_lib_dir = options["shared-lib-dir"]
88
+ else
89
+ @shared_lib_dir = ask(msg.join("\n"))
90
+ end
91
+ end
92
+
93
+ def create_readme
94
+ target = File.join(
95
+ parent_options[:root],
96
+ _name,
97
+ "README.md",
98
+ )
99
+
100
+ template("templates/README.md.tt", target)
101
+ end
102
+
103
+ def create_gemfile
104
+ target = File.join(
105
+ parent_options[:root],
106
+ _name,
107
+ "Gemfile",
108
+ )
109
+
110
+ template("templates/Gemfile.tt", target)
111
+
112
+ # Add development dependencies from gemspec
113
+ if @gemspec_file_contents
114
+ gems = @gemspec_file_contents.select do |line|
115
+ line =~ / spec.add_development_dependency/
116
+ end.map do |line|
117
+ line.gsub(/ spec.add_development_dependency/, "gem")
118
+ end.join
119
+
120
+ append_to_file(target, "\n#{gems}", verbose: false)
121
+ end
122
+
123
+ # Add gemfile gems
124
+ if @gemfile_file_contents
125
+ gems = @gemfile_file_contents.select do |line|
126
+ line =~ /^gem /
127
+ end.join
128
+
129
+ append_to_file(target, "\n#{gems}", verbose: false)
130
+ end
131
+
132
+ end
133
+
134
+ def create_base_file
135
+ target = File.join(
136
+ parent_options[:root],
137
+ _name,
138
+ "lib",
139
+ "#{_name}.rb",
140
+ )
141
+
142
+ template("templates/base_file.rb.tt", target)
143
+ end
144
+
145
+ def modify_rakefile
146
+ target = File.join(
147
+ parent_options[:root],
148
+ _name,
149
+ "Rakefile",
150
+ )
151
+
152
+ gsub_file(target, /^require "bundler\/gem_tasks"\n/, "", verbose: false)
153
+ end
154
+
155
+ def create_ruby_version
156
+ target = File.join(
157
+ parent_options[:root],
158
+ _name,
159
+ ".ruby-version",
160
+ )
161
+
162
+ create_file(target, "ruby-#{RUBY_VERSION}\n")
163
+ end
164
+
165
+ def create_ruby_gemset
166
+ target = File.join(
167
+ parent_options[:root],
168
+ _name,
169
+ ".ruby-gemset",
170
+ )
171
+
172
+ create_file(target, "#{_name}\n")
173
+ end
174
+
175
+ def create_runbookfile
176
+ target = File.join(
177
+ parent_options[:root],
178
+ _name,
179
+ "Runbookfile",
180
+ )
181
+
182
+ template("templates/Runbookfile.tt", target)
183
+ end
184
+
185
+ def create_runbooks_directory
186
+ dirs = [
187
+ parent_options[:root],
188
+ _name,
189
+ "runbooks",
190
+ ]
191
+ target = File.join(*dirs)
192
+
193
+ empty_directory(target)
194
+ _keep_dir(target)
195
+ end
196
+
197
+ def create_extensions_directory
198
+ dirs = [
199
+ parent_options[:root],
200
+ _name,
201
+ "lib",
202
+ "runbook",
203
+ "extensions",
204
+ ]
205
+ target = File.join(*dirs)
206
+
207
+ empty_directory(target)
208
+ _keep_dir(target)
209
+ end
210
+
211
+ def create_generators_directory
212
+ dirs = [
213
+ parent_options[:root],
214
+ _name,
215
+ "lib",
216
+ "runbook",
217
+ "generators",
218
+ ]
219
+ target = File.join(*dirs)
220
+
221
+ empty_directory(target)
222
+ _keep_dir(target)
223
+ end
224
+
225
+ def create_lib_directory
226
+ dirs = [
227
+ parent_options[:root],
228
+ _name,
229
+ @shared_lib_dir,
230
+ ]
231
+ target = File.join(*dirs)
232
+
233
+ empty_directory(target)
234
+ _keep_dir(target)
235
+ end
236
+
237
+ def update_bin_console
238
+ path = [
239
+ parent_options[:root],
240
+ _name,
241
+ "bin",
242
+ "console",
243
+ ]
244
+ target = File.join(*path)
245
+
246
+ old_require = /require "#{_name}"/
247
+ new_require = %Q(require_relative "../lib/#{_name}")
248
+ new_require += "\n\nRunbook::Configuration.load_config"
249
+ gsub_file(target, old_require, new_require, verbose: false)
250
+
251
+ old_require = /require "#{_name}"/
252
+ new_require = %Q(require_relative "../lib/#{_name}")
253
+ gsub_file(target, old_require, new_require, verbose: false)
254
+ end
255
+
256
+ def remove_bad_test
257
+ path = [
258
+ parent_options[:root],
259
+ _name,
260
+ ]
261
+
262
+ case options["test"]
263
+ when "rspec"
264
+ path << "spec"
265
+ path << "#{_name}_spec.rb"
266
+ when "minitest"
267
+ path << "test"
268
+ path << "#{_name}_test.rb"
269
+ end
270
+ target = File.join(*path)
271
+
272
+ bad_test = / .*version.*\n.*\n end\n\n/m
273
+ gsub_file(target, bad_test, "", verbose: false)
274
+ end
275
+
276
+ def runbook_project_overview
277
+ msg = [
278
+ "",
279
+ "Your runbook project was successfully created.",
280
+ "Remember to run `./bin/setup` in your project to install dependencies.",
281
+ "Add runbooks to the `runbooks` directory.",
282
+ "Add shared code to `#{@shared_lib_dir}`.",
283
+ "Execute runbooks using `bundle exec runbook exec <RUNBOOK_PATH>` from your project root.",
284
+ "See the README.md for more details.",
285
+ "\n",
286
+ ]
287
+
288
+ say(msg.join("\n"))
289
+ end
290
+
291
+ private
292
+
293
+ def _name
294
+ @name ||= name.underscore
295
+ end
296
+
297
+ def _keep_dir(dir)
298
+ create_file(File.join(dir, ".keep"), verbose: false)
299
+ end
300
+ end
301
+ end
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
3
+
4
+ ruby "<%= RUBY_VERSION %>"
5
+
6
+ gem "runbook", "~> <%= Runbook::VERSION %>"