roro 0.3.17 → 0.3.18
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.
- 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
|