careacademy-runbook 1.2.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 (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 %>"