careacademy-runbook 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.dockerignore +17 -0
- data/.github/workflows/ruby.yml +43 -0
- data/.gitignore +16 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Appraisals +8 -0
- data/CHANGELOG.md +143 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +1272 -0
- data/Rakefile +12 -0
- data/TODO.md +316 -0
- data/bin/console +16 -0
- data/bin/setup +8 -0
- data/dockerfiles/Dockerfile-runbook +18 -0
- data/dockerfiles/Dockerfile-sshd +4 -0
- data/examples/hooks_runbook.rb +72 -0
- data/examples/layout_runbook.rb +26 -0
- data/examples/restart_nginx.rb +26 -0
- data/examples/simple_runbook.rb +41 -0
- data/examples/suppress_capture_output.rb +47 -0
- data/exe/runbook +5 -0
- data/gemfiles/.bundle/config +2 -0
- data/gemfiles/activesupport_5.gemfile +7 -0
- data/gemfiles/activesupport_6.gemfile +7 -0
- data/images/runbook_anatomy_diagram.png +0 -0
- data/images/runbook_example.gif +0 -0
- data/images/runbook_execution_modes.png +0 -0
- data/lib/hacks/ssh_kit.rb +58 -0
- data/lib/runbook/airbrussh_context.rb +25 -0
- data/lib/runbook/cli.rb +115 -0
- data/lib/runbook/cli_base.rb +38 -0
- data/lib/runbook/configuration.rb +120 -0
- data/lib/runbook/dsl.rb +21 -0
- data/lib/runbook/entities/book.rb +17 -0
- data/lib/runbook/entities/section.rb +7 -0
- data/lib/runbook/entities/setup.rb +7 -0
- data/lib/runbook/entities/step.rb +7 -0
- data/lib/runbook/entity.rb +129 -0
- data/lib/runbook/errors.rb +7 -0
- data/lib/runbook/extensions/add.rb +14 -0
- data/lib/runbook/extensions/description.rb +14 -0
- data/lib/runbook/extensions/sections.rb +19 -0
- data/lib/runbook/extensions/setup.rb +17 -0
- data/lib/runbook/extensions/shared_variables.rb +51 -0
- data/lib/runbook/extensions/ssh_config.rb +78 -0
- data/lib/runbook/extensions/statements.rb +31 -0
- data/lib/runbook/extensions/steps.rb +24 -0
- data/lib/runbook/extensions/tmux.rb +13 -0
- data/lib/runbook/generator.rb +38 -0
- data/lib/runbook/generators/base.rb +45 -0
- data/lib/runbook/generators/dsl_extension/dsl_extension.rb +29 -0
- data/lib/runbook/generators/dsl_extension/templates/dsl_extension.tt +25 -0
- data/lib/runbook/generators/generator/generator.rb +43 -0
- data/lib/runbook/generators/generator/templates/generator.tt +53 -0
- data/lib/runbook/generators/project/project.rb +301 -0
- data/lib/runbook/generators/project/templates/Gemfile.tt +6 -0
- data/lib/runbook/generators/project/templates/README.md.tt +29 -0
- data/lib/runbook/generators/project/templates/Runbookfile.tt +11 -0
- data/lib/runbook/generators/project/templates/base_file.rb.tt +8 -0
- data/lib/runbook/generators/runbook/runbook.rb +22 -0
- data/lib/runbook/generators/runbook/templates/runbook.tt +20 -0
- data/lib/runbook/generators/statement/statement.rb +18 -0
- data/lib/runbook/generators/statement/templates/statement.tt +34 -0
- data/lib/runbook/helpers/format_helper.rb +11 -0
- data/lib/runbook/helpers/ssh_kit_helper.rb +143 -0
- data/lib/runbook/helpers/tmux_helper.rb +176 -0
- data/lib/runbook/hooks.rb +88 -0
- data/lib/runbook/initializer.rb +85 -0
- data/lib/runbook/node.rb +33 -0
- data/lib/runbook/run.rb +290 -0
- data/lib/runbook/runner.rb +66 -0
- data/lib/runbook/runs/ssh_kit.rb +193 -0
- data/lib/runbook/statement.rb +20 -0
- data/lib/runbook/statements/ask.rb +12 -0
- data/lib/runbook/statements/assert.rb +34 -0
- data/lib/runbook/statements/capture.rb +14 -0
- data/lib/runbook/statements/capture_all.rb +14 -0
- data/lib/runbook/statements/command.rb +11 -0
- data/lib/runbook/statements/confirm.rb +10 -0
- data/lib/runbook/statements/description.rb +9 -0
- data/lib/runbook/statements/download.rb +12 -0
- data/lib/runbook/statements/layout.rb +10 -0
- data/lib/runbook/statements/note.rb +10 -0
- data/lib/runbook/statements/notice.rb +10 -0
- data/lib/runbook/statements/ruby_command.rb +9 -0
- data/lib/runbook/statements/tmux_command.rb +11 -0
- data/lib/runbook/statements/upload.rb +12 -0
- data/lib/runbook/statements/wait.rb +10 -0
- data/lib/runbook/toolbox.rb +37 -0
- data/lib/runbook/util/repo.rb +57 -0
- data/lib/runbook/util/runbook.rb +43 -0
- data/lib/runbook/util/sticky_hash.rb +26 -0
- data/lib/runbook/util/stored_pose.rb +55 -0
- data/lib/runbook/version.rb +3 -0
- data/lib/runbook/view.rb +24 -0
- data/lib/runbook/viewer.rb +24 -0
- data/lib/runbook/views/markdown.rb +117 -0
- data/lib/runbook.rb +140 -0
- data/runbook.gemspec +53 -0
- 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,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
|