mobilis 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,261 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fileutils"
4
+ require "json"
5
+ require "yaml"
6
+
7
+ require 'mobilis/actions_projects_take'
8
+ require "mobilis/docker_compose_projector"
9
+ require "mobilis/mysql_instance"
10
+ require "mobilis/new_relic"
11
+ require "mobilis/postgresql_instance"
12
+ require "mobilis/rails_project"
13
+ require "mobilis/rack_project"
14
+ require "mobilis/redis_instance"
15
+
16
+ module Mobilis
17
+
18
+ ##
19
+ # this is NOT a GenericProject, this is the metaproject
20
+ # TODO: s/Project/Meta/g
21
+ class Project
22
+ include ActionsProjectsTake
23
+ include Mobilis::NewRelic
24
+
25
+ attr_reader :name
26
+
27
+ def initialize
28
+ @data = {
29
+ projects: [],
30
+ username: ENV.fetch('USER', ENV.fetch('USERNAME', '')),
31
+ starting_port_no: 10000,
32
+ port_gap: 100
33
+ }
34
+ end
35
+
36
+ def attributes
37
+ generate_attributes
38
+ end
39
+
40
+ def username
41
+ @data[:username]
42
+ end
43
+
44
+ def generate_files
45
+ if Dir.exist? 'generate'
46
+ puts "Removing existing generate directory"
47
+ FileUtils.rm_rf('generate')
48
+ end
49
+
50
+ Dir.mkdir 'generate'
51
+
52
+ Dir.chdir 'generate' do
53
+ save_project
54
+ create_rails_builder if has_rails_project?
55
+ projects.each_with_index do |project, index|
56
+ project.generate
57
+ end
58
+ save_docker_compose
59
+ end
60
+ end
61
+
62
+ def create_rails_builder
63
+ Dir.mkdir 'rails-builder'
64
+ Dir.chdir 'rails-builder' do
65
+ create_rails_builder_dockerfile
66
+ create_rails_builder_gemfile
67
+ build_rails_builder
68
+ end
69
+ end
70
+
71
+ def create_rails_builder_dockerfile
72
+ set_file_contents 'Dockerfile', <<EOF
73
+ FROM ruby:latest
74
+ RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
75
+ # Common dependencies
76
+ RUN apt-get update -qq \\
77
+ && DEBIAN_FRONTEND=noninteractive apt-get install -yq --no-install-recommends \\
78
+ build-essential \\
79
+ gnupg2 \\
80
+ curl \\
81
+ less \\
82
+ git \\
83
+ nodejs \\
84
+ postgresql-client \\
85
+ && apt-get clean \\
86
+ && rm -rf /var/cache/apt/archives/* \\
87
+ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \\
88
+ && truncate -s 0 /var/log/*log
89
+ RUN gem update bundle
90
+ RUN gem update --system
91
+ COPY Gemfile .
92
+ RUN bundle install
93
+ EOF
94
+ end
95
+
96
+ def create_rails_builder_gemfile
97
+ set_file_contents 'Gemfile', <<EOF
98
+ source "https://rubygems.org"
99
+ # FIXME
100
+ #git_source(:github) { |repo| "https://github.com/repo.git" }
101
+
102
+ ruby "3.1.2"
103
+
104
+ gem "rails", "~> 7.0.3", ">= 7.0.3.1"
105
+ gem "sqlite3", "~> 1.4"
106
+ gem "puma", "~> 5.0"
107
+ gem "jbuilder"
108
+ gem "redis", "~> 4.0"
109
+ gem "kredis"
110
+ gem "bcrypt", "~> 3.1.7"
111
+ gem "bootsnap", require: false
112
+ gem "image_processing", "~> 1.2"
113
+ gem "rack-cors"
114
+ gem "pg"
115
+ gem "mysql2"
116
+ gem "minitest"
117
+
118
+ group :development, :test do
119
+ gem "debug", platforms: %i[ mri mingw x64_mingw ]
120
+ end
121
+
122
+ group :development do
123
+ gem "spring"
124
+ end
125
+
126
+ gem "rspec-rails", group: [:development, :test]
127
+ EOF
128
+
129
+ end
130
+
131
+ def has_rails_project?
132
+ projects.each do |p|
133
+ return true if p.type == :rails
134
+ end
135
+ return false
136
+ end
137
+
138
+ def generate_attributes
139
+ attributes = {projects: {}, new_relic_license_key: ENV.fetch("NEW_RELIC_LICENSE_KEY", "some_invalid_key_NREAL")}
140
+ projects.each_with_index do |project, index|
141
+ attributes["#{project.name}_internal_port_no".to_sym] =
142
+ @data[:starting_port_no] + (index * @data[:port_gap])
143
+ end
144
+ attributes
145
+ end
146
+
147
+ def build
148
+ # logger.info "# build"
149
+ Dir.chdir 'generate' do
150
+ run_command "docker compose build"
151
+ end
152
+ end
153
+
154
+ def rails_builder_image
155
+ "#{ username }/rails-builder"
156
+ end
157
+
158
+ def build_rails_builder
159
+ run_docker "build -t #{ rails_builder_image } ."
160
+ end
161
+
162
+ def save_project
163
+ File.open("mproj.json", "w") do |f|
164
+ f.write(JSON.pretty_generate(@data))
165
+ end
166
+ end
167
+
168
+ def save_docker_compose
169
+ docker = DockerComposeProjector.project self
170
+
171
+ File.open("docker-compose.yml", "w") do |f|
172
+ f.write(docker.to_yaml)
173
+ end
174
+ end
175
+
176
+ def projects
177
+ mapping = {
178
+ rails: RailsProject,
179
+ postgresql: PostgresqlInstance,
180
+ mysql: MysqlInstance,
181
+ redis: RedisInstance,
182
+ rack: RackProject
183
+ }
184
+ @data[:projects].map {|p| mapping[p[:type]].new p, self}
185
+ end
186
+
187
+ def project_by_name name
188
+ projects.find {|p| p.name == name }
189
+ end
190
+
191
+ def display
192
+ ap @data
193
+ end
194
+
195
+ def add_prime_stack_rails_project name
196
+ add_rails_project name, [:rspec, :api, :simplecov, :standard, :factorybot]
197
+ end
198
+
199
+ def add_omakase_stack_rails_project name
200
+ add_rails_project name, [:simplecov, :standard, :api]
201
+ end
202
+
203
+ def add_postgresql_instance name
204
+ data = {
205
+ name: name,
206
+ type: :postgresql
207
+ }
208
+ @data[:projects] << data
209
+ GenericProject.new data, self
210
+ end
211
+
212
+ def add_mysql_instance name
213
+ data = {
214
+ name: name,
215
+ type: :mysql
216
+ }
217
+ @data[:projects] << data
218
+ GenericProject.new data, self
219
+ end
220
+
221
+ def add_redis_instance name
222
+ data = {
223
+ name: name,
224
+ type: :redis,
225
+ }
226
+ @data[:projects] << data
227
+ RedisInstance.new data, self
228
+ end
229
+
230
+ def add_rails_project name, options
231
+ data = {
232
+ name: name,
233
+ type: :rails,
234
+ controllers: [],
235
+ models: [],
236
+ options: options.clone,
237
+ attributes: {}
238
+ }
239
+ @data[:projects] << data
240
+ RailsProject.new data, self
241
+ end
242
+
243
+ def add_rack_project name
244
+ data = {
245
+ name: name,
246
+ type: :rack,
247
+ attributes: {}
248
+ }
249
+ @data[:projects] << data
250
+ RackProject.new data, self
251
+ end
252
+
253
+ def getwd
254
+ wd = Dir.getwd
255
+ return wd unless wd[1] == ":"
256
+ return "/#{wd[0]}#{wd[2...]}"
257
+ end
258
+
259
+
260
+ end
261
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "mobilis/generic_project"
4
+ require "mobilis/os"
5
+
6
+ module Mobilis
7
+ class RackProject < GenericProject
8
+
9
+ def name
10
+ @data[:name]
11
+ end
12
+
13
+ def generate
14
+ Dir.mkdir name
15
+ Dir.chdir name do
16
+ generate_config_ru
17
+ generate_Gemfile
18
+ generate_Gemfile_lock
19
+ generate_Dockerfile
20
+ end
21
+ end
22
+
23
+ def generate_config_ru
24
+ set_file_contents "config.ru", '# config.ru
25
+ app = Proc.new {
26
+ [
27
+ 200,
28
+ { "content-type" => "text/html" },
29
+ ["Hello, Rack"]
30
+ ]
31
+ }
32
+ run app
33
+ '
34
+ end
35
+
36
+ def generate_Gemfile
37
+ set_file_contents "Gemfile", '# frozen_string_literal: true
38
+
39
+ source "https://rubygems.org"
40
+
41
+ # gem "rails"
42
+
43
+ gem "rack", "= 3.0.0.beta1"
44
+
45
+ gem "rackup", "~> 0.2.2"
46
+ '
47
+ end
48
+
49
+ def generate_Gemfile_lock
50
+ set_file_contents "Gemfile.lock", 'GEM
51
+ remote: https://rubygems.org/
52
+ specs:
53
+ rack (3.0.0.beta1)
54
+ rackup (0.2.2)
55
+ rack (>= 3.0.0.beta1)
56
+ webrick
57
+ webrick (1.7.0)
58
+
59
+ PLATFORMS
60
+ x64-mingw-ucrt
61
+
62
+ DEPENDENCIES
63
+ rack (= 3.0.0.beta1)
64
+ rackup (~> 0.2.2)
65
+
66
+ BUNDLED WITH
67
+ 2.3.16
68
+ '
69
+ end
70
+
71
+ def generate_Dockerfile
72
+ set_file_contents "Dockerfile", '
73
+ FROM ruby:latest
74
+ RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
75
+ WORKDIR /myapp
76
+ COPY Gemfile /myapp/Gemfile
77
+ COPY Gemfile.lock /myapp/Gemfile.lock
78
+ RUN bundle install
79
+ COPY . /myapp
80
+
81
+ # Add a script to be executed every time the container starts.
82
+ ENTRYPOINT ["rackup"]
83
+ EXPOSE 9292
84
+
85
+ '
86
+ end
87
+
88
+ end
89
+ end
@@ -0,0 +1,179 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "mobilis/generic_project"
4
+ require "mobilis/os"
5
+
6
+ module Mobilis
7
+ class RailsProject < GenericProject
8
+
9
+ def child_env_vars
10
+ [
11
+ "#{ name.upcase }_HOST=#{ name }"
12
+ ]
13
+ end
14
+
15
+ def controllers
16
+ @data[:controllers]
17
+ end
18
+
19
+ def models
20
+ @data[:models]
21
+ end
22
+
23
+ def database
24
+ links.each do |link|
25
+ project = @metaproject.project_by_name link
26
+ return project if project.instance_of? Mobilis::PostgresqlInstance
27
+ return project if project.instance_of? Mobilis::MysqlInstance
28
+ end
29
+ return nil
30
+ end
31
+
32
+ def toggle_rails_api_mode
33
+ if options.include? :api then
34
+ remove_rails_option :api
35
+ add_rails_option :haml
36
+ else
37
+ add_rails_option :api
38
+ remove_rails_option :haml
39
+ end
40
+ end
41
+
42
+ def add_rails_option option
43
+ remove_rails_option option
44
+ options << option
45
+ end
46
+
47
+ def remove_rails_option option
48
+ options.reject! {|x| x == option }
49
+ end
50
+
51
+ def add_controller name
52
+ controller = {name: name, actions: []}
53
+ @data[:controllers] << controller
54
+ controller
55
+ end
56
+
57
+ def add_model name
58
+ model = {name: name, fields: []}
59
+ @data[:models] << model
60
+ model
61
+ end
62
+
63
+ def rails_builder_image
64
+ "#{ @metaproject.username }/rails-builder"
65
+ end
66
+
67
+ def rails_run_command command
68
+ run_docker "run --rm -v #{ getwd }:/usr/src/app -w /usr/src/app #{ rails_builder_image } #{ command }"
69
+ end
70
+
71
+ def bundle_run command
72
+ rails_run_command "./bundle_run.sh #{ command }"
73
+ end
74
+
75
+ def generate
76
+ rails_run_command rails_new_command_line
77
+ Dir.chdir name do
78
+ git_commit_all "rails new"
79
+ generate_bundle_run
80
+ read_rails_master_key
81
+ install_rspec if options.include? :rspec
82
+ install_factory_bot if options.include? :factory_bot
83
+ git_commit_all "add Gems"
84
+ generate_Dockerfile
85
+ generate_entrypoint_sh
86
+ generate_build_sh
87
+ git_commit_all "add Dockerfile and build script etc"
88
+ end
89
+ end
90
+
91
+ def read_rails_master_key
92
+ @data[:attributes][:rails_master_key] = File.read("config/master.key")
93
+ end
94
+
95
+ def rails_master_key
96
+ @data[:attributes][:rails_master_key]
97
+ end
98
+
99
+ def generate_Dockerfile
100
+ set_file_contents "Dockerfile", 'FROM ruby:latest
101
+ RUN apt-get update -qq && apt-get install -y nodejs postgresql-client dos2unix
102
+ WORKDIR /myapp
103
+ COPY Gemfile /myapp/Gemfile
104
+ COPY Gemfile.lock /myapp/Gemfile.lock
105
+ RUN bundle install
106
+ COPY . /myapp
107
+
108
+ # Add a script to be executed every time the container starts.
109
+ RUN chmod +x /myapp/entrypoint.sh
110
+ ENTRYPOINT ["/myapp/entrypoint.sh"]
111
+ EXPOSE 3000
112
+ RUN dos2unix /myapp/entrypoint.sh
113
+
114
+ # Configure the main process to run when running the image
115
+ CMD ["rails", "server", "-b", "0.0.0.0"]
116
+ '
117
+ end
118
+
119
+ def generate_entrypoint_sh
120
+ set_file_contents "entrypoint.sh", "#!/bin/sh
121
+
122
+ # https://stackoverflow.com/a/38732187/1935918
123
+ set -e
124
+
125
+ if [ -f /app/tmp/pids/server.pid ]; then
126
+ rm /app/tmp/pids/server.pid
127
+ fi
128
+
129
+ bundle exec rake db:migrate 2>/dev/null || bundle exec rake db:setup
130
+
131
+ exec bundle exec \"$@\"
132
+ "
133
+ end
134
+
135
+ def install_rspec
136
+ Mobilis.logger.info "Installing rspec"
137
+ append_line "Gemfile", 'gem "rspec-rails", group: [:development, :test]'
138
+ bundle_run "rails generate rspec:install"
139
+ end
140
+
141
+ def install_factory_bot
142
+ Mobilis.logger.info "Installing FactoryBot"
143
+ append_line "Gemfile", "gem 'factory_bot_rails'"
144
+ set_file_contents "spec/support/factory_bot.rb", "RSpec.configure do |config|
145
+ config.include FactoryBot::Syntax::Methods
146
+ end
147
+ "
148
+ end
149
+
150
+ def generate_bundle_run
151
+ Mobilis.logger.info "Installing bundle_run.sh"
152
+
153
+ set_file_contents "bundle_run.sh", "#!/bin/bash
154
+ set -euo pipefail
155
+ bundle install
156
+ $@
157
+ "
158
+ end
159
+
160
+ def install_super_diff
161
+ append_line "Gemfile", "gem 'super_diff', group: [:development]"
162
+ set_second_line 'spec/spec_helper.rb', 'require "super_diff/rspec"'
163
+ end
164
+
165
+ def rails_new_command_line
166
+ pieces = ["bundle", "exec", "rails", "new", name, "."]
167
+ pieces << "--api" if options.include? :api
168
+ my_db = database
169
+ if my_db then
170
+ pieces << "--database=#{ my_db.type }"
171
+ end
172
+ if Mobilis::OS.linux?
173
+ pieces << "-u #{ Process.uid }:#{ Process.gid }"
174
+ end
175
+ pieces.join " "
176
+ end
177
+
178
+ end
179
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "mobilis/generic_project"
4
+
5
+ module Mobilis
6
+ class RedisInstance < GenericProject
7
+
8
+ def generate
9
+ FileUtils.mkdir_p data_dir
10
+ end
11
+
12
+ def child_env_vars
13
+ [
14
+ "REDIS_HOST=#{ name }",
15
+ "REDIS_PORT=6379",
16
+ "REDIS_PASSWORD=#{ password }"
17
+ ]
18
+ end
19
+
20
+ def data_dir
21
+ "./data/#{ name }"
22
+ end
23
+
24
+ def has_local_build
25
+ false
26
+ end
27
+
28
+ def username
29
+ name
30
+ end
31
+
32
+ def password
33
+ "#{name}_password"
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mobilis
4
+ VERSION = "0.0.1"
5
+ end
data/lib/mobilis.rb ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "mobilis/version"
4
+ require_relative "mobilis/project"
5
+ require_relative "mobilis/docker_compose_projector"
6
+
7
+ module Mobilis
8
+ class Error < StandardError; end
9
+ end
data/sig/mobilis.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module Mobilis
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mobilis
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Meleneth
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2022-08-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: awesome_print
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: state_machine
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: tty-prompt
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: super_diff
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description:
70
+ email:
71
+ - meleneth@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".rspec"
77
+ - ".rubocop.yml"
78
+ - CHANGELOG.md
79
+ - Gemfile
80
+ - Gemfile.lock
81
+ - README.md
82
+ - Rakefile
83
+ - lib/mobilis.rb
84
+ - lib/mobilis/actions_projects_take.rb
85
+ - lib/mobilis/command_line.rb
86
+ - lib/mobilis/docker_compose_projector.rb
87
+ - lib/mobilis/generic_project.rb
88
+ - lib/mobilis/interactive_designer.rb
89
+ - lib/mobilis/logger.rb
90
+ - lib/mobilis/mysql_instance.rb
91
+ - lib/mobilis/new_relic.rb
92
+ - lib/mobilis/os.rb
93
+ - lib/mobilis/postgresql_instance.rb
94
+ - lib/mobilis/project.rb
95
+ - lib/mobilis/rack_project.rb
96
+ - lib/mobilis/rails_project.rb
97
+ - lib/mobilis/redis_instance.rb
98
+ - lib/mobilis/version.rb
99
+ - sig/mobilis.rbs
100
+ homepage: https://github.com/meleneth/mobilis
101
+ licenses: []
102
+ metadata:
103
+ homepage_uri: https://github.com/meleneth/mobilis
104
+ source_code_uri: https://github.com/meleneth/mobilis
105
+ changelog_uri: https://github.com/meleneth/mobilis/CHANGELOG.md
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: 2.6.0
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ requirements: []
121
+ rubygems_version: 3.3.7
122
+ signing_key:
123
+ specification_version: 4
124
+ summary: Generate and scaffold multiple projects and a docker compose file
125
+ test_files: []