railsdock 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +7 -0
  5. data/CHANGELOG.md +0 -0
  6. data/CODE_OF_CONDUCT.md +74 -0
  7. data/Gemfile +3 -0
  8. data/Gemfile.lock +173 -0
  9. data/LICENSE.txt +20 -0
  10. data/README.md +55 -0
  11. data/Rakefile +14 -0
  12. data/bin/console +14 -0
  13. data/bin/setup +8 -0
  14. data/exe/railsdock +18 -0
  15. data/ext/railsdock/extconf.rb +3 -0
  16. data/ext/railsdock/railsdock.c +9 -0
  17. data/ext/railsdock/railsdock.h +6 -0
  18. data/lib/railsdock.rb +6 -0
  19. data/lib/railsdock/cli.rb +33 -0
  20. data/lib/railsdock/command.rb +101 -0
  21. data/lib/railsdock/commands/install.rb +142 -0
  22. data/lib/railsdock/logo.rb +49 -0
  23. data/lib/railsdock/templates/install/default/Dockerfile +101 -0
  24. data/lib/railsdock/templates/install/default/default.env.erb +44 -0
  25. data/lib/railsdock/templates/install/default/docker-compose.mac.yml +7 -0
  26. data/lib/railsdock/templates/install/default/docker-compose.yml.erb +51 -0
  27. data/lib/railsdock/templates/install/memcached/Dockerfile +7 -0
  28. data/lib/railsdock/templates/install/memcached/docker-compose.yml.erb +11 -0
  29. data/lib/railsdock/templates/install/mysql/Dockerfile +7 -0
  30. data/lib/railsdock/templates/install/mysql/database.yml.erb +18 -0
  31. data/lib/railsdock/templates/install/mysql/docker-compose.yml.erb +13 -0
  32. data/lib/railsdock/templates/install/postgres/Dockerfile +7 -0
  33. data/lib/railsdock/templates/install/postgres/database.yml.erb +18 -0
  34. data/lib/railsdock/templates/install/postgres/docker-compose.yml.erb +11 -0
  35. data/lib/railsdock/templates/install/redis/Dockerfile +7 -0
  36. data/lib/railsdock/templates/install/redis/docker-compose.yml.erb +11 -0
  37. data/lib/railsdock/version.rb +3 -0
  38. data/railsdock.gemspec +60 -0
  39. data/railsdock.png +0 -0
  40. metadata +393 -0
@@ -0,0 +1,9 @@
1
+ #include "railsdock.h"
2
+
3
+ VALUE rb_mRailsdock;
4
+
5
+ void
6
+ Init_railsdock(void)
7
+ {
8
+ rb_mRailsdock = rb_define_module("Railsdock");
9
+ }
@@ -0,0 +1,6 @@
1
+ #ifndef RAILSDOCK_H
2
+ #define RAILSDOCK_H 1
3
+
4
+ #include "ruby.h"
5
+
6
+ #endif /* RAILSDOCK_H */
data/lib/railsdock.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'railsdock/version'
2
+ require 'railsdock/cli'
3
+
4
+ module Railsdock
5
+ class Error < StandardError; end
6
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'thor'
4
+
5
+ module Railsdock
6
+ # Handle the application command line parsing
7
+ # and the dispatch to various command objects
8
+ #
9
+ # @api public
10
+ class CLI < Thor
11
+ # Error raised by this runner
12
+ Error = Class.new(StandardError)
13
+
14
+ desc 'version', 'railsdock version'
15
+ def version
16
+ require_relative 'version'
17
+ puts "Railsdock v#{Railsdock::VERSION}"
18
+ end
19
+ map %w[--version -v] => :version
20
+
21
+ desc 'install', 'Install Railsdock in an existing rails application'
22
+ method_option :help, aliases: '-h', type: :boolean,
23
+ desc: 'Display usage information'
24
+ def install(app_name = nil)
25
+ if options[:help]
26
+ invoke :help, ['install']
27
+ else
28
+ require_relative 'commands/install'
29
+ Railsdock::Commands::Install.new(options.merge(app_name: app_name)).execute
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+
5
+ module Railsdock
6
+ class Command
7
+ extend Forwardable
8
+
9
+ def_delegators :command, :run
10
+
11
+ # Execute this command
12
+ #
13
+ # @api public
14
+ def execute(*)
15
+ raise(
16
+ NotImplementedError,
17
+ "#{self.class}##{__method__} must be implemented"
18
+ )
19
+ end
20
+
21
+ # The external commands runner
22
+ #
23
+ # @see http://www.rubydoc.info/gems/tty-command
24
+ #
25
+ # @api public
26
+ def cmd(**options)
27
+ require 'tty-command'
28
+ TTY::Command.new(options)
29
+ end
30
+
31
+ # The cursor movement
32
+ #
33
+ # @see http://www.rubydoc.info/gems/tty-cursor
34
+ #
35
+ # @api public
36
+ def cursor
37
+ require 'tty-cursor'
38
+ TTY::Cursor
39
+ end
40
+
41
+ # The generating config files
42
+ #
43
+ # @see http://www.rubydoc.info/gems/tty-config
44
+ #
45
+ # @api public
46
+ def config
47
+ require 'tty-config'
48
+ TTY::Config
49
+ end
50
+
51
+ # Open a file or text in the user's preferred editor
52
+ #
53
+ # @see http://www.rubydoc.info/gems/tty-editor
54
+ #
55
+ # @api public
56
+ def editor
57
+ require 'tty-editor'
58
+ TTY::Editor
59
+ end
60
+
61
+ # File manipulation utility methods.
62
+ #
63
+ # @see http://www.rubydoc.info/gems/tty-file
64
+ #
65
+ # @api public
66
+ def file
67
+ require 'tty-file'
68
+ TTY::File
69
+ end
70
+
71
+ # Terminal platform and OS properties
72
+ #
73
+ # @see http://www.rubydoc.info/gems/tty-platform
74
+ #
75
+ # @api public
76
+ def platform
77
+ require 'tty-platform'
78
+ TTY::Platform.new
79
+ end
80
+
81
+ # The interactive prompt
82
+ #
83
+ # @see http://www.rubydoc.info/gems/tty-prompt
84
+ #
85
+ # @api public
86
+ def prompt(**options)
87
+ require 'tty-prompt'
88
+ TTY::Prompt.new(options)
89
+ end
90
+
91
+ def progress(*options)
92
+ require 'tty-progressbar'
93
+ TTY::ProgressBar.new(*options)
94
+ end
95
+
96
+ def color
97
+ require 'pastel'
98
+ Pastel.new
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ostruct'
4
+ require 'erb'
5
+ require_relative '../command'
6
+ require_relative '../logo'
7
+
8
+ module Railsdock
9
+ module Commands
10
+ class Install < Railsdock::Command
11
+ OPTIONS_HASH = {
12
+ database: {
13
+ name: 'Database',
14
+ options: %i[postgres mysql]
15
+ },
16
+ mem_store: {
17
+ name: 'In-Memory Store',
18
+ options: %i[redis memcached]
19
+ }
20
+ }.freeze
21
+
22
+ POST_INSTALL_MESSAGE =<<~PIM
23
+ Railsdock successfully installed
24
+
25
+ Run `docker-compose build` then `docker-compose up` to start your app,
26
+
27
+ PIM
28
+
29
+ BASE_TEMPLATE_DIR = File.expand_path("#{__dir__}/../templates/install").freeze
30
+
31
+ def initialize(options)
32
+ @options = options
33
+ @variables = OpenStruct.new(
34
+ app_name: options[:app_name] || get_app_name,
35
+ is_windows?: platform.windows?,
36
+ is_mac?: platform.mac?,
37
+ uid: cmd.run('id -u').out.chomp
38
+ )
39
+ end
40
+
41
+ def execute(input: $stdin, output: $stdout)
42
+ output.puts Railsdock::Logo.call
43
+ @variables[:dockerfile_dir] = prompt_for_dockerfile_directory
44
+ copy_default_files
45
+ service_hash = collect_service_selections
46
+ service_hash.each do |type, service|
47
+ file.copy_file("#{BASE_TEMPLATE_DIR}/#{service}/Dockerfile", [@variables.dockerfile_dir, service, "/Dockerfile"].join)
48
+ inject_driver_config(service)
49
+ append_erb_to_compose_file(service)
50
+ file.inject_into_file('./docker-compose.yml', "\n #{service}:", after: "\nvolumes:")
51
+ append_service_config_to_env(service)
52
+ copy_db_yml("#{BASE_TEMPLATE_DIR}/#{service}/database.yml.erb") if type == :database
53
+ end
54
+ output.puts POST_INSTALL_MESSAGE
55
+ end
56
+
57
+ private
58
+
59
+ def get_app_name
60
+ ::File.open('./config/application.rb').read.match(/module (.+)\s/)[1].downcase
61
+ end
62
+
63
+ def copy_db_yml(erb_file)
64
+ file.copy_file(erb_file, './config/database.yml', context: @variables)
65
+ end
66
+
67
+ def collect_service_selections
68
+ prompt.collect do
69
+ OPTIONS_HASH.each do |key, value|
70
+ key(key).select("Select the #{value[:name]} used by your application:", value[:options])
71
+ end
72
+ end
73
+ end
74
+
75
+ def inject_driver_config(service)
76
+ file.inject_into_file('./docker-compose.yml', after: " node_modules:\n driver: ${VOLUMES_DRIVER}\n") do
77
+ <<-YAML
78
+ #{service}:
79
+ driver: ${VOLUMES_DRIVER}
80
+ YAML
81
+ end
82
+ end
83
+
84
+ def generate_erb(source_path)
85
+ template = if ERB.version.scan(/\d+\.\d+\.\d+/)[0].to_f >= 2.2
86
+ ERB.new(::File.binread(source_path), trim_mode: '-', eoutvar: '@output_buffer')
87
+ else
88
+ ERB.new(::File.binread(source_path), nil, '-', '@output_buffer')
89
+ end
90
+ template.result(@variables.instance_eval('binding'))
91
+ end
92
+
93
+ def create_or_append_to_file(source_path, destination_path)
94
+ if ::File.exist?(destination_path) && generate_erb(source_path) != ::File.binread(destination_path)
95
+ file.safe_append_to_file(destination_path, generate_erb(source_path))
96
+ else
97
+ file.copy_file(source_path, destination_path, context: @variables)
98
+ end
99
+ end
100
+
101
+ def append_erb_to_compose_file(service)
102
+ file.safe_append_to_file('./docker-compose.yml') do
103
+ generate_erb("#{BASE_TEMPLATE_DIR}/#{service}/docker-compose.yml.erb")
104
+ end
105
+ end
106
+
107
+ def append_service_config_to_env(service)
108
+ file.safe_append_to_file('./.env') do
109
+ ::File.binread("#{BASE_TEMPLATE_DIR}/#{service}/#{service}.env")
110
+ end
111
+ end
112
+
113
+ def prompt_for_dockerfile_directory
114
+ prompt.ask('Where would you like your docker container configuration files to live?') do |q|
115
+ q.default './docker/'
116
+ q.validate(%r{\.\/[A-z\/]+\/})
117
+ q.modify :remove
118
+ q.messages[:valid?] = 'Invalid directory path (should start with ./ and end with /)'
119
+ end
120
+ end
121
+
122
+ def copy_default_files
123
+ Dir["#{BASE_TEMPLATE_DIR}/default/*"].each do |path|
124
+ destination_file(path)
125
+ end
126
+ end
127
+
128
+ def destination_file(path)
129
+ case File.basename(path)
130
+ when 'Dockerfile'
131
+ file.copy_file(path, "#{@variables.dockerfile_dir}ruby/Dockerfile", context: @variables)
132
+ when 'docker-compose.yml.erb'
133
+ file.copy_file(path, './docker-compose.yml', context: @variables)
134
+ when 'default.env.erb'
135
+ create_or_append_to_file(path, './.env')
136
+ else
137
+ file.copy_file(path, "./#{File.basename(path)}", context: @variables)
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,49 @@
1
+ require 'pastel'
2
+
3
+ module Railsdock
4
+ class Logo
5
+ def self.call
6
+ color = Pastel.new
7
+ color.red(" `yy: `.
8
+ -oo` .-/+ooyysooo//-/sy
9
+ `+ooyyhhhhhhhhhhhhhhhys/-`
10
+ `-oyhhhhhhhhhhhhhhhyyyyyhhhys/-
11
+ .- .:yhhhhhhhhhhhhysoo+````:os-:/oyyy+.
12
+ :yy:/yhhhhhhhhhhhyo-` :o/ `.- ``:oss:`
13
+ .+shhhhhhhhhhhho++ `-+o.
14
+ `oyhhhhhhhhhhhy-.so` `
15
+ .shhhhhhhhhhhhy. `
16
+ ` -yhhhhhhhhhhhhh/:`", color.cyan(" -+/. "), color.red("
17
+ :ys/-yhhhhhhhhhhhhho/hs"), color.cyan(" -oooo/. "), color.red("
18
+ /os:yhhhhhhhhhhhhhh:`::"), color.cyan(" `ooooooo: "), color.red("
19
+ `ohhhhhhhhhhhhhhh."), color.cyan(" :oooooooo: "), color.red("
20
+ :hhhhhhhhhhhhhhhh...`"), color.cyan(" /ooooooooo:////::.` "), color.red("
21
+ `yhhhhhhhhhhhhhhhh-sys"), color.cyan(" -oooooooooooooooooo:"), color.red("
22
+ -yyyyyyyyyyyyyyyyy/-/+."), color.cyan(" /oooooooooooooooo+.
23
+ .-------"), color.red("/////////////////:"), color.cyan("---------------------------:/+oooooooooooooo+:`
24
+ :oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo++/-`
25
+ +oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo-..``
26
+ /ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo-
27
+ :oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo-
28
+ .ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo-
29
+ +ooooooooooooooooooooooooooooooooooooooooooooooooooooooooo-
30
+ .ooooooooooooooooooooooooooooooooooooooooooooooooooooooo+.
31
+ :ooooooooooooooooooooooooooooooooooooooooooooooooooooo:`
32
+ /oooooooooooooooooooooooooooooooooooooooooooooooooo:`
33
+ /ooooooooooooooooooooooooooooooooooooooooooooooo/`
34
+ -+oooooooooooooooooooooooooooooooooooooooooo+-`
35
+ -+ooooooooooooooooooooooooooooooooooooo/-`
36
+ .:/ooooooooooooooooooooooooooooo+/-.
37
+ `.-:/++oooooooooooo++//:-.`
38
+
39
+ ╠╬ ╠╬
40
+ ╠░ ╠░"), color.red("
41
+ ████████▖ ▄██████▄ ███ ███ ▟█████▌"), color.cyan(" ╓φ╬╬░╬╦╬░ ,φ╬╬░╬▒╦ ╦╬╬░╬▒╦ ╠░ ,╦╬╬"), color.red("
42
+ ███ ▐███ ███ ███ ███ ███ ▐██▙▄▄"), color.cyan(" ╠░╩ `╬░ ╔░╩ ╬╬ ╒╬╩ ` ╠░╓φ╬╩╜"), color.red("
43
+ ███▄▄███▘ ███▄▄███ ███ ███ ▀▀████▙"), color.cyan(" ░░ ╠░ ╠░ ░░⌐░░⌐ ╠░╜╙╬╦"), color.red("
44
+ ███▀███▄ ███▀▀███ ███ ███▄▄▄▄ ▄▄▄▄▄██"), color.cyan(" ╙╬╬╖, ╓φ░╩ ╬╬╦, ,φ░╩ ╠╠╦, ,╦╦ ╠░ ╙░╦"), color.red("
45
+ ▀▀▀ ▝▀▀▀ ▀▀▀ ▀▀▀ ▀▀▀ ▀▀▀▀▀▀▀ ▀▀▀▀▀▀▘"), color.cyan(" `╙╨╩╜^ `╙╨╩╜╜ ╙╙╨╜╜ ╙╜ ╙╜"))
46
+
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,101 @@
1
+ ARG RAILSDOCK_RUBY_VERSION=2.6
2
+
3
+ FROM ruby:$RAILSDOCK_RUBY_VERSION
4
+
5
+ LABEL maintainer="Nate Vick <nate.vick@hint.io>"
6
+
7
+ ARG DEBIAN_FRONTEND=noninteractive
8
+
9
+ ###############################################################################
10
+ # Base Software Install
11
+ ###############################################################################
12
+
13
+ ARG RAILSDOCK_NODE_VERSION=11
14
+
15
+ RUN curl -sL https://deb.nodesource.com/setup_$RAILSDOCK_NODE_VERSION.x | bash -
16
+
17
+ RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
18
+ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
19
+
20
+ RUN apt-get update && apt-get install -y \
21
+ build-essential \
22
+ nodejs \
23
+ yarn \
24
+ locales \
25
+ git \
26
+ netcat \
27
+ vim \
28
+ sudo
29
+
30
+ ###############################################################################
31
+ # Railsdock non-root user
32
+ ###############################################################################
33
+
34
+ ARG RUBY_UID
35
+ ENV RUBY_UID $RUBY_UID
36
+ ARG RUBY_GID
37
+ ENV RUBY_GID $RUBY_GID
38
+ ARG USER=ruby
39
+ ENV USER $USER
40
+
41
+ RUN groupadd -g $RUBY_GID $USER && \
42
+ useradd -u $RUBY_UID -g $USER -m $USER && \
43
+ usermod -p "*" $USER && \
44
+ usermod -aG sudo $USER && \
45
+ echo "$USER ALL=NOPASSWD: ALL" >> /etc/sudoers.d/50-$USER
46
+
47
+ ###############################################################################
48
+ # Ruby, Rubygems, and Bundler Defaults
49
+ ###############################################################################
50
+
51
+ ENV LANG C.UTF-8
52
+
53
+ # Point Bundler at /gems. This will cause Bundler to re-use gems that have already been installed on the gems volume
54
+ ENV BUNDLE_PATH /gems
55
+ ENV BUNDLE_HOME /gems
56
+
57
+ # Increase how many threads Bundler uses when installing. Optional!
58
+ ARG RAILSDOCK_BUNDLE_JOBS=20
59
+ ENV BUNDLE_JOBS $RAILSDOCK_BUNDLE_JOBS
60
+
61
+ # How many times Bundler will retry a gem download. Optional!
62
+ ARG RAILSDOCK_BUNDLE_RETRY=5
63
+ ENV BUNDLE_RETRY $RAILSDOCK_BUNDLE_RETRY
64
+
65
+ # Where Rubygems will look for gems, similar to BUNDLE_ equivalents.
66
+ ENV GEM_HOME /gems
67
+ ENV GEM_PATH /gems
68
+
69
+ # Add /gems/bin to the path so any installed gem binaries are runnable from bash.
70
+ ENV PATH /gems/bin:$PATH
71
+
72
+ ###############################################################################
73
+ # Optional Software Install
74
+ ###############################################################################
75
+
76
+ #------------------------------------------------------------------------------
77
+ # Postgres Client:
78
+ #------------------------------------------------------------------------------
79
+
80
+ ARG INSTALL_PG_CLIENT=false
81
+
82
+ RUN if [ "$INSTALL_PG_CLIENT" = true ]; then \
83
+ # Install the pgsql client
84
+ apt-get install -y postgresql-client \
85
+ ;fi
86
+
87
+ ###############################################################################
88
+ # Final Touches
89
+ ###############################################################################
90
+
91
+ RUN mkdir -p "$GEM_HOME" && chown $USER:$USER "$GEM_HOME"
92
+
93
+ RUN mkdir -p /app
94
+ WORKDIR /app
95
+
96
+ RUN mkdir -p node_modules && chown $USER:$USER node_modules
97
+
98
+ USER $USER
99
+
100
+ # Install latest bundler
101
+ RUN gem install bundler