roro 0.3.17 → 0.3.18
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +11 -10
- data/.gitignore +3 -2
- data/Guardfile +8 -10
- data/README.md +2 -1
- data/lib/roro.rb +1 -0
- data/lib/roro/cli.rb +13 -7
- data/lib/roro/cli/generate/story.rb +18 -0
- data/lib/roro/cli/greenfield/rails.rb +2 -24
- data/lib/roro/cli/rollon.rb +135 -8
- data/lib/roro/cli/rollon/rails/base/base.rb +4 -0
- data/lib/roro/cli/{base → rollon/rails/base}/insert_gems.rb +2 -10
- data/lib/roro/cli/{base → rollon/rails/base}/insertions.rb +8 -0
- data/lib/roro/cli/rollon/rails/database.rb +4 -8
- data/lib/roro/cli/rollon/rails/database/with_mysql.rb +2 -2
- data/lib/roro/cli/rollon/rails/database/with_postgresql.rb +3 -4
- data/lib/roro/cli/rollon/ruby_gem/with_ci_cd.rb +7 -7
- data/lib/roro/configurator.rb +15 -0
- data/lib/roro/configurator/eligibility.rb +137 -0
- data/lib/roro/configurator/okonomi.rb +28 -0
- data/lib/roro/configurator/omakase.rb +170 -0
- data/lib/roro/stories/greenfield.yml +1 -0
- data/lib/roro/stories/greenfield/rails.yml +9 -0
- data/lib/roro/stories/rollon.yml +42 -0
- data/lib/roro/stories/rollon/rails.yml +76 -0
- data/lib/roro/stories/rollon/rails/ci_cd.yml +1 -0
- data/lib/roro/stories/rollon/rails/ci_cd/circleci.yml +2 -0
- data/lib/roro/stories/rollon/rails/database.yml +9 -0
- data/lib/roro/stories/rollon/rails/database/mysql.yml +17 -0
- data/lib/roro/stories/rollon/rails/database/postgresql.yml +15 -0
- data/lib/roro/stories/rollon/rails/kubernetes.yml +1 -0
- data/lib/roro/stories/rollon/rails/kubernetes/postgresql.yml +10 -0
- data/lib/roro/stories/rollon/rails/kubernetes/postgresql/default.yml +1 -0
- data/lib/roro/stories/rollon/rails/kubernetes/postgresql/edge.yml +1 -0
- data/lib/roro/stories/rollon/ruby_gem.yml +5 -0
- data/lib/roro/{cli/templates/rails → templates/base}/.circleci/_aliases.yml +0 -0
- data/lib/roro/templates/base/.circleci/_commands.yml +31 -0
- data/lib/roro/templates/base/.circleci/_defaults.yml +5 -0
- data/lib/roro/templates/base/.circleci/_executors.yml +11 -0
- data/lib/roro/templates/base/.circleci/_major_only.yml +4 -0
- data/lib/roro/templates/base/.circleci/_version.yml +1 -0
- data/lib/roro/{cli/templates → templates}/base/.circleci/_workflow.yml +0 -0
- data/lib/roro/{cli/templates → templates}/base/.circleci/config.job-example.yml +5 -5
- data/lib/roro/{cli/templates → templates}/base/.circleci/jobs/_build.yml +0 -0
- data/lib/roro/{cli/templates → templates}/base/.circleci/jobs/_release.yml +0 -0
- data/lib/roro/{cli/templates → templates}/base/.circleci/workflows/_build_release.yml +0 -0
- data/lib/roro/{cli/templates → templates}/base/.dockerignore +0 -0
- data/lib/roro/{cli/templates → templates}/base/dotenv +0 -0
- data/lib/roro/{cli/templates → templates}/base/jumpstart/.keep +0 -0
- data/lib/roro/{cli/templates → templates}/base/jumpstart/Dockerfile.tt +0 -0
- data/lib/roro/{cli/templates → templates}/base/jumpstart/docker-compose.yml +0 -0
- data/lib/roro/{cli/templates → templates}/base/jumpstart/docker-entrypoint.sh +0 -0
- data/lib/roro/{cli/templates → templates}/base/livereload/hosts.example +0 -0
- data/lib/roro/{cli/templates → templates}/base/roro/.keep +0 -0
- data/lib/roro/{cli/templates → templates}/base/roro/roro/.keep +0 -0
- data/lib/roro/{cli/templates → templates}/base/roro/roro/containers/.keep +0 -0
- data/lib/roro/{cli/templates → templates}/base/roro/roro/containers/app/.keep +0 -0
- data/lib/roro/{cli/templates → templates}/base/roro/roro/containers/frontend/.keep +0 -0
- data/lib/roro/{cli/templates → templates}/base/roro/roro/docker-entrypoint.sh.tt +0 -0
- data/lib/roro/{cli/templates → templates}/rails/.circleci/.keep +0 -0
- data/lib/roro/{cli/templates → templates}/rails/.circleci/config.yml.tt +4 -6
- data/lib/roro/{cli/templates → templates}/rails/.circleci/jobs/_build.yml +4 -6
- data/lib/roro/templates/rails/.circleci/jobs/_push.yml +11 -0
- data/lib/roro/templates/rails/.circleci/jobs/_test.yml +12 -0
- data/lib/roro/{cli/templates → templates}/rails/.circleci/setup-gem-credentials.sh +0 -0
- data/lib/roro/templates/rails/.circleci/workflows/_build_test_push.yml +12 -0
- data/lib/roro/{cli/templates → templates}/rails/.keep +0 -0
- data/lib/roro/templates/rails/Dockerfile.greenfield.tt +51 -0
- data/lib/roro/{cli/templates → templates}/rails/config/database.mysql.yml +0 -0
- data/lib/roro/{cli/templates → templates}/rails/config/database.pg.yml +2 -3
- data/lib/roro/{cli/templates/stories → templates/rails/database}/with_mysql/_service.yml +0 -0
- data/lib/roro/{cli/templates → templates}/rails/database/with_postgresql/.keep +0 -0
- data/lib/roro/{cli/templates/stories → templates/rails/database}/with_postgresql/_service.yml +0 -0
- data/lib/roro/{cli/templates → templates}/rails/docker-compose.yml.tt +3 -3
- data/lib/roro/{cli/templates → templates}/rails/dotenv/.keep +0 -0
- data/lib/roro/templates/rails/dotenv/database.mysql.env.tt +6 -0
- data/lib/roro/templates/rails/dotenv/database.pg.env.tt +4 -0
- data/lib/roro/{cli/templates → templates}/rails/dotenv/web.env.tt +0 -0
- data/lib/roro/templates/rails/kube.rake.tt +114 -0
- data/lib/roro/{cli/templates → templates}/rails/roro/.keep +0 -0
- data/lib/roro/{cli/templates → templates}/rails/roro/containers/.keep +0 -0
- data/lib/roro/{cli/templates → templates}/rails/roro/containers/app/.keep +0 -0
- data/lib/roro/templates/rails/roro/containers/app/Dockerfile.tt +34 -0
- data/lib/roro/{cli/templates → templates}/rails/roro/containers/frontend/.keep +0 -0
- data/lib/roro/{cli/templates/rails/roro/docker-entrypoint.sh.tt → templates/rails/roro/docker-entrypoint.sh} +0 -0
- data/lib/roro/{cli/templates/rails/roro/roro → templates/rails/roro/kube}/.keep +0 -0
- data/lib/roro/{cli/templates/rails/roro/roro/containers/.keep → templates/rails/roro/kube/certificate.yml.tt} +0 -0
- data/lib/roro/{cli/templates/rails/roro/roro/containers/app/.keep → templates/rails/roro/kube/cluster-issuer.yml.tt} +0 -0
- data/lib/roro/templates/rails/roro/kube/deployment.yml.tt +50 -0
- data/lib/roro/templates/rails/roro/kube/deployments/postgres_deploy.yaml +47 -0
- data/lib/roro/templates/rails/roro/kube/deployments/rails_deploy.yaml +62 -0
- data/lib/roro/templates/rails/roro/kube/deployments/redis_deploy.yaml +23 -0
- data/lib/roro/templates/rails/roro/kube/deployments/sidekiq_deploy.yaml +56 -0
- data/lib/roro/{cli/templates/rails/roro/roro/containers/frontend/.keep → templates/rails/roro/kube/ingress.yml.tt} +0 -0
- data/lib/roro/templates/rails/roro/kube/ingresses/ingress.yaml +13 -0
- data/lib/roro/{cli/templates/ruby_gem/.circleci/.keep → templates/rails/roro/kube/job-migrate.yml.tt} +0 -0
- data/lib/roro/templates/rails/roro/kube/jobs/setup.yaml +42 -0
- data/lib/roro/templates/rails/roro/kube/secret-digital-ocean.yml.tt +4 -0
- data/lib/roro/templates/rails/roro/kube/service.yml.tt +10 -0
- data/lib/roro/templates/rails/roro/kube/services/postgres_svc.yaml +13 -0
- data/lib/roro/templates/rails/roro/kube/services/rails_svc.yaml +13 -0
- data/lib/roro/templates/rails/roro/kube/services/redis_svc.yaml +13 -0
- data/lib/roro/templates/rails/roro/kube/volumes/postgres_volumes.yaml +25 -0
- data/lib/roro/{cli/templates/ruby_gem/roro/containers → templates/ruby_gem/.circleci}/.keep +0 -0
- data/lib/roro/{cli/templates → templates}/ruby_gem/.circleci/config.yml.tt +4 -4
- data/lib/roro/templates/ruby_gem/.circleci/jobs/_test.yml +4 -0
- data/lib/roro/{cli/templates → templates}/ruby_gem/.circleci/setup-gem-credentials.sh +0 -0
- data/lib/roro/{cli/templates → templates}/ruby_gem/docker-compose.yml +0 -0
- data/lib/roro/{cli/templates/ruby_gem/roro/keys → templates/ruby_gem/roro/containers}/.keep +0 -0
- data/lib/roro/{cli/templates → templates}/ruby_gem/roro/containers/ruby_image/Dockerfile.tt +1 -1
- data/lib/roro/templates/ruby_gem/roro/containers/ruby_image/ci.env.tt +1 -0
- data/lib/roro/{cli/templates/stories → templates/ruby_gem/roro/keys}/.keep +0 -0
- data/lib/roro/version.rb +1 -1
- metadata +101 -80
- data/lib/roro/cli/base/base.rb +0 -8
- data/lib/roro/cli/base/base_files.rb +0 -24
- data/lib/roro/cli/base/check_dependencies.rb +0 -97
- data/lib/roro/cli/base/continuous_integration.rb +0 -13
- data/lib/roro/cli/base/utilities.rb +0 -38
- data/lib/roro/cli/configuration.rb +0 -69
- data/lib/roro/cli/generate/config.rb +0 -11
- data/lib/roro/cli/generate/config/rails.rb +0 -17
- data/lib/roro/cli/rollon/rails.rb +0 -47
- data/lib/roro/cli/rollon/stories/stories.rb +0 -3
- data/lib/roro/cli/roro_configurator.yml +0 -157
- data/lib/roro/cli/templates/base/.circleci/_defaults.yml +0 -17
- data/lib/roro/cli/templates/base/.roro_config.yml +0 -15
- data/lib/roro/cli/templates/rails/.circleci/jobs/_push.yml +0 -23
- data/lib/roro/cli/templates/rails/.circleci/jobs/_test.yml +0 -13
- data/lib/roro/cli/templates/rails/.circleci/workflows/_build_test_push.yml +0 -9
- data/lib/roro/cli/templates/rails/Dockerfile.greenfield.tt +0 -47
- data/lib/roro/cli/templates/rails/database/with_mysql/_service.yml +0 -10
- data/lib/roro/cli/templates/rails/database/with_postgresql/_service.yml +0 -7
- data/lib/roro/cli/templates/rails/dotenv/database.mysql.env.tt +0 -3
- data/lib/roro/cli/templates/rails/dotenv/database.pg.env.tt +0 -4
- data/lib/roro/cli/templates/rails/roro/containers/app/Dockerfile.tt +0 -88
- data/lib/roro/cli/templates/rails/roro/roro/docker-entrypoint.sh.tt +0 -8
- data/lib/roro/cli/templates/ruby_gem/roro/containers/ruby_image/ci.env.tt +0 -1
- data/lib/roro/cli/templates/stories/ruby_gem/with_ci_cd/_build.yml +0 -11
- data/lib/roro/cli/templates/stories/with_postgresql/.keep +0 -0
- data/lib/tasks/deploy.rake +0 -126
@@ -15,17 +15,17 @@ module Roro
|
|
15
15
|
'./roro/containers/ruby_gem/ci.env' \n\nlater, or we'll try to add it here:",
|
16
16
|
default: '')
|
17
17
|
rubygems_api_key = (answer.eql?("") ? 'some-key' : answer)
|
18
|
-
@config.
|
19
|
-
@config.
|
18
|
+
@config.env[:rubygems_api_key] = rubygems_api_key
|
19
|
+
@config.env[:rubies] = []
|
20
20
|
3.times do |index|
|
21
|
-
newruby = @config.
|
22
|
-
@config.
|
21
|
+
newruby = @config.env[:ruby_version].gsub('.', '').to_i - index
|
22
|
+
@config.env[:rubies] << newruby.to_s.split('').join('.')
|
23
23
|
end
|
24
|
-
directory 'ruby_gem/roro', './roro', @config.
|
25
|
-
directory 'ruby_gem/.circleci', './.circleci', @config.
|
24
|
+
directory 'ruby_gem/roro', './roro', @config.env
|
25
|
+
directory 'ruby_gem/.circleci', './.circleci', @config.env
|
26
26
|
copy_file 'ruby_gem/docker-compose.yml', './docker-compose.yml'
|
27
27
|
|
28
|
-
@config.
|
28
|
+
@config.env[:rubies].each do |ruby|
|
29
29
|
file = '.circleci/config.yml'
|
30
30
|
spacer = "\n - run: "
|
31
31
|
rv = "RUBY_VERSION=#{ruby} docker-compose "
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'roro/configurator/eligibility'
|
2
|
+
require 'roro/configurator/okonomi'
|
3
|
+
require 'roro/configurator/omakase'
|
4
|
+
|
5
|
+
module Roro
|
6
|
+
module Configurator
|
7
|
+
include Eligibility
|
8
|
+
include Okonomi
|
9
|
+
include Omakase
|
10
|
+
end
|
11
|
+
|
12
|
+
class Configuration < Thor
|
13
|
+
include Roro::Configurator
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
module Roro
|
4
|
+
module Configurator
|
5
|
+
module Eligibility
|
6
|
+
|
7
|
+
def screen_target_directory
|
8
|
+
@structure[:greenfield] ? confirm_directory_empty : confirm_directory_app
|
9
|
+
handle_roro_artifacts
|
10
|
+
end
|
11
|
+
|
12
|
+
def confirm_directory_app
|
13
|
+
confirm_dependency({
|
14
|
+
system_query: "ls -A",
|
15
|
+
warning: "This is an empty directory. You can generate a new and fully
|
16
|
+
dockerized Rails app using the 'greenfield' command here here but if
|
17
|
+
you want to containerize an existing app -- which is what the 'rollon'
|
18
|
+
command is for -- you'll need to navigate to a directory with an app we
|
19
|
+
can roll onto.",
|
20
|
+
suggestion: "$ roro greenfield",
|
21
|
+
conditional: "!Dir.glob('*').empty?"})
|
22
|
+
end
|
23
|
+
|
24
|
+
def confirm_directory_empty
|
25
|
+
confirm = confirm_dependency({
|
26
|
+
system_query: "ls -A",
|
27
|
+
warning: "this is not an empty directory. Roro will not greenfield a new Rails app unless either a) the current directory is empty or b) you run greenfield with the --force flag",
|
28
|
+
suggestion: "$ roro greenfield --force",
|
29
|
+
conditional: "Dir.glob('*').empty?" # || (Dir.glob('*').size.eql?(1) && Dir.glob('roro_configurator.yml'))"
|
30
|
+
})
|
31
|
+
confirm || true
|
32
|
+
end
|
33
|
+
|
34
|
+
def artifacts?
|
35
|
+
@appname = @env[:main_app_name]
|
36
|
+
@artifacts = {}
|
37
|
+
hash = {
|
38
|
+
containers: {
|
39
|
+
list: "docker ps --filter name=#{@appname}\ -a",
|
40
|
+
remove: " -q | xargs docker stop | xargs docker rm -f"
|
41
|
+
},
|
42
|
+
volumes: {
|
43
|
+
list: "docker volume ls --filter name=#{@appname}*",
|
44
|
+
remove: " -q | xargs docker volume rm -f"
|
45
|
+
},
|
46
|
+
networks: {
|
47
|
+
list: "docker network ls --filter name=#{@appname}",
|
48
|
+
remove: " -q | xargs docker network rm"
|
49
|
+
},
|
50
|
+
images: {
|
51
|
+
list: "docker image ls #{@appname}*",
|
52
|
+
remove: " -q | xargs docker rmi -f"
|
53
|
+
}
|
54
|
+
}
|
55
|
+
hash.each do |k, v|
|
56
|
+
check = IO.popen(v[:list] + ' -q').count > 0
|
57
|
+
@artifacts[k] = v if check
|
58
|
+
end
|
59
|
+
true if @artifacts.empty?
|
60
|
+
end
|
61
|
+
|
62
|
+
def handle_roro_artifacts
|
63
|
+
return if artifacts?
|
64
|
+
question = [
|
65
|
+
"\n\nThis machine has some docker artifacts which may clash with ",
|
66
|
+
"RoRo moving forward. You can verify their existence with:\n"
|
67
|
+
]
|
68
|
+
@artifacts.each { |k,v| question << "\t$ #{v[:list]}" }
|
69
|
+
question << "\nYou can remove these artifacts with something like:\n"
|
70
|
+
@artifacts.each { |k,v| question << "\t$ #{v[:list]} #{v[:remove]}" }
|
71
|
+
question << "\nWould you like RoRo to attempt to remove them for you?"
|
72
|
+
choices = {'y' => 'Yes', 'n' => 'No'}
|
73
|
+
|
74
|
+
choices.each { |k,v| question << "(#{k}) #{v.to_s}" }
|
75
|
+
|
76
|
+
prompt = question.join
|
77
|
+
answer = ask(prompt, default: 'y', limited_to: choices.keys)
|
78
|
+
|
79
|
+
if answer.eql?('y')
|
80
|
+
|
81
|
+
@artifacts.each do |k,v|
|
82
|
+
puts "Attempting to remove #{k}"
|
83
|
+
system( v[:list] + v[:remove] )
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def confirm_dependency(options)
|
89
|
+
msg = []
|
90
|
+
msg << ""
|
91
|
+
msg << delineator
|
92
|
+
msg << "It looks like #{options[:warning]}. The following bash command returns false:"
|
93
|
+
msg << "\t$ #{options[:system_query]}"
|
94
|
+
msg << "Try this:"
|
95
|
+
msg << ("\t" + options[:suggestion])
|
96
|
+
msg << delineator
|
97
|
+
conditional = options[:conditional] ? eval(options[:conditional]) : system(options[:system_query])
|
98
|
+
query = options[:system_query]
|
99
|
+
if conditional == false
|
100
|
+
|
101
|
+
raise(Roro::Error.new(msg.join("\n\n")))
|
102
|
+
else
|
103
|
+
true
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def confirm_dependencies
|
108
|
+
dependencies.each do |dependency|
|
109
|
+
confirm_dependency(dependency)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def delineator
|
116
|
+
("-" * 80)
|
117
|
+
end
|
118
|
+
|
119
|
+
def dependencies
|
120
|
+
[
|
121
|
+
{
|
122
|
+
system_query: "which docker",
|
123
|
+
warning: "Docker isn't installed",
|
124
|
+
suggestion: "https://docs.docker.com/install/"
|
125
|
+
}, {
|
126
|
+
system_query: "which docker-compose",
|
127
|
+
warning: "Docker Compose isn't installed",
|
128
|
+
suggestion: "https://docs.docker.com/compose/install/"
|
129
|
+
}, {
|
130
|
+
system_query: "docker info",
|
131
|
+
warning: "the Docker daemon isn't running",
|
132
|
+
suggestion: "https://docs.docker.com/config/daemon/#start-the-daemon-manually"
|
133
|
+
} ]
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Roro
|
5
|
+
module Configurator
|
6
|
+
module Okonomi
|
7
|
+
|
8
|
+
def take_order
|
9
|
+
ask_questions
|
10
|
+
end
|
11
|
+
|
12
|
+
def ask_questions
|
13
|
+
choices = @structure[:choices]
|
14
|
+
choices.each do |key, value|
|
15
|
+
@structure[:intentions][key] = ask_question(value)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def ask_question(question)
|
20
|
+
prompt = question[:question]
|
21
|
+
default = question[:default]
|
22
|
+
choices = question[:choices].keys
|
23
|
+
answer = ask(prompt, default: default, limited_to: choices)
|
24
|
+
answer
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
module Roro
|
2
|
+
module Configurator
|
3
|
+
module Omakase
|
4
|
+
attr_reader :structure, :intentions, :env, :options, :story
|
5
|
+
|
6
|
+
def initialize(args={}, options={})
|
7
|
+
|
8
|
+
@options = sanitize(args)
|
9
|
+
@structure = {
|
10
|
+
intentions: {},
|
11
|
+
choices: {},
|
12
|
+
env_vars: {}
|
13
|
+
}
|
14
|
+
@story = @options[:story] ? { rollon: @options[:story] } : default_story
|
15
|
+
build_story
|
16
|
+
@intentions = @structure[:intentions]
|
17
|
+
@env = @structure[:env_vars]
|
18
|
+
@env[:main_app_name] = Dir.pwd.split('/').last
|
19
|
+
@env[:ruby_version] = RUBY_VERSION
|
20
|
+
@env[:force] = true
|
21
|
+
@env[:verbose] = false
|
22
|
+
@env[:roro_version] = VERSION
|
23
|
+
screen_target_directory
|
24
|
+
end
|
25
|
+
|
26
|
+
def build_story
|
27
|
+
layer_greenfield
|
28
|
+
layer_rollon
|
29
|
+
layer_story
|
30
|
+
layer_okonomi
|
31
|
+
end
|
32
|
+
|
33
|
+
def layer_okonomi
|
34
|
+
return unless @options.keys.include?(:okonomi)
|
35
|
+
@structure[:okonomi] = true
|
36
|
+
take_order
|
37
|
+
end
|
38
|
+
|
39
|
+
def layer_greenfield
|
40
|
+
return unless @options.keys.include?(:greenfield)
|
41
|
+
@structure[:greenfield] = true
|
42
|
+
build_layers( { greenfield: :rails } )
|
43
|
+
end
|
44
|
+
|
45
|
+
def layer_rollon
|
46
|
+
build_layers(@story)
|
47
|
+
end
|
48
|
+
|
49
|
+
def layer_story
|
50
|
+
file = '.roro_story'
|
51
|
+
return unless File.exist?("#{file}.yml")
|
52
|
+
overlay(get_layer(file))
|
53
|
+
end
|
54
|
+
|
55
|
+
def build_layers(story, location=nil)
|
56
|
+
story = story.is_a?(Hash) ? story : { story => {}}
|
57
|
+
story.each do |key, value|
|
58
|
+
location = location ? "#{location}/#{key}" : key
|
59
|
+
case value
|
60
|
+
when Array
|
61
|
+
value.each {|value| build_layers(value, location) }
|
62
|
+
when true
|
63
|
+
when
|
64
|
+
build_layers(value, location)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
overlay(get_layer("#{Roro::CLI.story_root}/#{location}"))
|
68
|
+
end
|
69
|
+
|
70
|
+
def overlay(layer)
|
71
|
+
layer.each do |key, value|
|
72
|
+
@structure[key] ||= value
|
73
|
+
end
|
74
|
+
overlay_choices(layer) if layer[:choices]
|
75
|
+
overlay_env_vars(layer) if layer[:env_vars]
|
76
|
+
overlay_actions(layer) if layer[:actions]
|
77
|
+
end
|
78
|
+
|
79
|
+
def overlay_actions(layer)
|
80
|
+
@structure[:actions].concat(layer[:actions])
|
81
|
+
end
|
82
|
+
|
83
|
+
def overlay_env_vars(layer)
|
84
|
+
layer[:env_vars].each do |key, value|
|
85
|
+
@structure[:env_vars][key] = value
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def overlay_choices(layer)
|
90
|
+
@structure[:intentions] ||= {}
|
91
|
+
layer[:choices].each do |key, value|
|
92
|
+
@structure[:choices][key] = value
|
93
|
+
@structure[:intentions][key] = value[:default]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def overlay_intentions(layer)
|
98
|
+
layer[:intentions].each do |key, value|
|
99
|
+
@structure[:intentions][key] = value
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def sanitize(options)
|
104
|
+
options ||= {}
|
105
|
+
options.transform_keys!{|k| k.to_sym}
|
106
|
+
options.each do |key, value|
|
107
|
+
case value
|
108
|
+
when Array
|
109
|
+
value.each { |vs| sanitize(vs) }
|
110
|
+
when Hash
|
111
|
+
sanitize(value)
|
112
|
+
when true
|
113
|
+
options[key] = true
|
114
|
+
when String || Symbol
|
115
|
+
options[key] = value.to_sym
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def get_layer(filedir)
|
121
|
+
filepath = filedir + '.yml'
|
122
|
+
if !File.exist?(filepath)
|
123
|
+
key = filedir.split('/').last
|
124
|
+
error_msg = "Cannot find that story #{key} at #{filepath}. Has it been written?"
|
125
|
+
raise (Roro::Error.new(error_msg))
|
126
|
+
end
|
127
|
+
json = JSON.parse(YAML.load_file(filepath).to_json, symbolize_names: true)
|
128
|
+
json ? json : ( raise (Roro::Error.new(error_msg)))
|
129
|
+
end
|
130
|
+
|
131
|
+
def story_map(story='stories')
|
132
|
+
array ||= []
|
133
|
+
loc = Roro::CLI.story_root + "/#{story}"
|
134
|
+
validate_story(loc)
|
135
|
+
stories = Dir.glob(loc + "/*.yml")
|
136
|
+
stories.each do |ss|
|
137
|
+
name = ss.split('/').last.split('.yml').first
|
138
|
+
array << { name.to_sym => story_map([story, name].join('/'))}
|
139
|
+
end
|
140
|
+
array
|
141
|
+
end
|
142
|
+
|
143
|
+
def default_story(story='rollon', loc=nil)
|
144
|
+
hash = {}
|
145
|
+
loc = [(loc ||= Roro::CLI.story_root), story].join('/')
|
146
|
+
substory = get_layer(loc)[:stories]
|
147
|
+
if substory.is_a?(Array)
|
148
|
+
array = []
|
149
|
+
substory.each do |s|
|
150
|
+
ss = get_layer([loc, s].join('/'))[:stories]
|
151
|
+
array << (ss.is_a?(String) ? { s.to_sym => ss.to_sym } : default_story( s, loc ) )
|
152
|
+
end
|
153
|
+
hash[story.to_sym] = array
|
154
|
+
else
|
155
|
+
hash[story.to_sym] = default_story(substory, loc)
|
156
|
+
end
|
157
|
+
hash
|
158
|
+
end
|
159
|
+
|
160
|
+
def validate_story(story)
|
161
|
+
substories = get_layer(story)[:stories]
|
162
|
+
if substories.is_a? String
|
163
|
+
File.exist?(story + substories + '.yml')
|
164
|
+
elsif substories.is_a? Array
|
165
|
+
substories.each { |substory| validate_story(story + '/' + substory) }
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
stories: rails
|
@@ -0,0 +1,9 @@
|
|
1
|
+
greenfield_actions:
|
2
|
+
- "@config.env['force'] = true"
|
3
|
+
- |
|
4
|
+
src = 'rails/Dockerfile.greenfield.tt'
|
5
|
+
dest = 'roro/containers/app/Dockerfile'
|
6
|
+
template src, dest, @config.env
|
7
|
+
|
8
|
+
greenfield_commands:
|
9
|
+
- system "DOCKER_BUILDKIT=1 docker build --file roro/containers/app/Dockerfile --output . ."
|
@@ -0,0 +1,42 @@
|
|
1
|
+
stories: rails
|
2
|
+
|
3
|
+
intentions:
|
4
|
+
|
5
|
+
env_vars:
|
6
|
+
main_app_name:
|
7
|
+
developer:
|
8
|
+
name: your-name
|
9
|
+
email: your.email@example.com
|
10
|
+
docker_email: your-docker-registry-email
|
11
|
+
docker_org: your-docker-registry-org-name
|
12
|
+
docker_password: your-docker-registry-password
|
13
|
+
docker_token: your-docker-registry-token
|
14
|
+
docker_username: your-docker-registry-user-name
|
15
|
+
|
16
|
+
choices:
|
17
|
+
|
18
|
+
generate_config_story:
|
19
|
+
question: |
|
20
|
+
Would you like to create a Roro Config file to help with debugging,
|
21
|
+
sharing your desired story, or both?
|
22
|
+
choices:
|
23
|
+
y: 'Yes'
|
24
|
+
n: 'No'
|
25
|
+
default: y
|
26
|
+
|
27
|
+
backup_existing_files:
|
28
|
+
question: |
|
29
|
+
RoRo will be generating a number of files, some of which will
|
30
|
+
replace existing ones. Would you like to back them up?
|
31
|
+
choices:
|
32
|
+
y: 'Yes'
|
33
|
+
n: 'No'
|
34
|
+
default: n
|
35
|
+
|
36
|
+
copy_dockerignore:
|
37
|
+
question: |
|
38
|
+
Would you like to create a .dockerignore file?
|
39
|
+
choices:
|
40
|
+
y: 'Yes'
|
41
|
+
n: 'No'
|
42
|
+
default: y
|
@@ -0,0 +1,76 @@
|
|
1
|
+
stories:
|
2
|
+
- database
|
3
|
+
- ci_cd
|
4
|
+
- kubernetes
|
5
|
+
|
6
|
+
actions:
|
7
|
+
- template 'rails/.circleci/config.yml.tt', './.circleci/config.yml'
|
8
|
+
- template 'rails/docker-compose.yml.tt', './docker-compose.yml', @config.env
|
9
|
+
- template 'base/dotenv', './.env', @config.env
|
10
|
+
- directory 'rails/roro', './roro', @config.env
|
11
|
+
- chmod "roro/docker-entrypoint.sh", 0755
|
12
|
+
|
13
|
+
|
14
|
+
startup:
|
15
|
+
success: "Your app should be available at http://localhost:3000"
|
16
|
+
commands:
|
17
|
+
- docker-compose build --no-cache
|
18
|
+
- docker-compose up -d
|
19
|
+
- docker-compose run app bin/rails db:create
|
20
|
+
- docker-compose run app bin/rails db:migrate
|
21
|
+
- 'docker-compose run app echo #{success_msg}'
|
22
|
+
|
23
|
+
env_vars:
|
24
|
+
ruby_version: '2.7'
|
25
|
+
database_host: database
|
26
|
+
frontend_service: frontend
|
27
|
+
database_service: database
|
28
|
+
|
29
|
+
choices:
|
30
|
+
config_std_out_true:
|
31
|
+
question: |
|
32
|
+
The team at Heroku, among others, recommend logging to STDOUT
|
33
|
+
and treating your logs as streams. We'll set this to
|
34
|
+
true as an environment variable but it may also be helpful
|
35
|
+
to configure './config/boot.rb' with '$stdout.sync = true'
|
36
|
+
just in case that doesn't work.
|
37
|
+
Would you like to configure this?
|
38
|
+
choices:
|
39
|
+
y: 'Yes'
|
40
|
+
n: 'No'
|
41
|
+
default: y
|
42
|
+
|
43
|
+
insert_roro_gem_into_gemfile:
|
44
|
+
question: |
|
45
|
+
Many developers believe it's good idea to secure sensitive
|
46
|
+
environment files and variables. You can use RoRo to
|
47
|
+
generate secret keys known only to you for use in any
|
48
|
+
environment, and then use them to encrypt and decrypt
|
49
|
+
these files. Would you like to add RoRo to your Gemfile?
|
50
|
+
choices:
|
51
|
+
y: 'Yes'
|
52
|
+
n: 'No'
|
53
|
+
default: n
|
54
|
+
|
55
|
+
gitignore_sensitive_files:
|
56
|
+
question: |
|
57
|
+
If you plan to use the environment files RoRo generates for
|
58
|
+
your own environment variables, it's a good idea to keep
|
59
|
+
these files out of source control. Would you like RoRo to
|
60
|
+
modify your .gitignore file to accomplish this for you ?
|
61
|
+
choices:
|
62
|
+
y: 'Yes'
|
63
|
+
n: 'No'
|
64
|
+
default: y
|
65
|
+
|
66
|
+
insert_hfci_gem_into_gemfile:
|
67
|
+
question: |
|
68
|
+
Jim Weirich passed too soon and remains missed. In addition
|
69
|
+
to Rake, Jim wrote a beautiful gem called 'Given' that makes
|
70
|
+
Rspec and Minitest less ugly and thus your tests more easy to
|
71
|
+
write. Would you like to install a gem called
|
72
|
+
handsome_fencer-test that allows you to try it out?
|
73
|
+
choices:
|
74
|
+
y: 'Yes'
|
75
|
+
n: 'No'
|
76
|
+
default: n
|