devbin 0.0.0 → 0.1.0.pre.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6122cb01b698481193232726057771f445c1d13e584c96bff5615569d2ce311e
4
- data.tar.gz: 78ad22eb148758a580f6493d4e2af87d038312565f0cf7efb9be5045b02615ab
3
+ metadata.gz: 0c80700e0199f8e9b8b537e2e40f057db7f38484ace56bbf250b7ac4491b8376
4
+ data.tar.gz: 702113519efb5f87fb2ab2b639c916bc5b1b8fa156e840eeb7c56794ab6d4588
5
5
  SHA512:
6
- metadata.gz: 50735ad47756d0616ebf0ae37ad2cacdd04de4c507034914e6c39b0e9673e00fc31728c77ac8a634aba672b51569bdc3ecba5613ef816e7aad547d94a863666c
7
- data.tar.gz: 8dc2487c98e53f1dbde4c33dbff71870537be6dc358af0f54a0610856502b807cab5c89910ff064d0605f92dbcb12c5b92a82bc3d112fed02884b2fe04e269e8
6
+ metadata.gz: 837717f4f788048c95418eea83afeb6ce5f04398a371d4a30e8ece742c3618546f8250cb753b0a5c200d091027d3b1d6e4538b04fd4d48ad7405cb806318b2f3
7
+ data.tar.gz: 0f7fcc426bae6e7082896bff6e2ebbfce8a9372bff11b2cbe16b3ccbe3bb25d4a737cf44ae25830c2aeabb32869c86b59d46e56f2eadc6aebabd9f95e2d66bd3
data/.gitignore CHANGED
@@ -6,6 +6,11 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ # Ignore any further changes in samples folder. Use git add -f samples to force
10
+ # update its content when necessary
11
+ /samples/*
9
12
 
10
13
  # rspec failure tracking
11
14
  .rspec_status
15
+ *.log
16
+ *.pid
data/Gemfile CHANGED
@@ -7,6 +7,8 @@ gemspec
7
7
 
8
8
 
9
9
  group :development do
10
+ gem "benchmark-ips", require: false
11
+ gem "pry"
10
12
  gem "rubocop-github", require: false
11
13
  gem "rubocop-rspec", require: false
12
14
  end
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- devbin (0.0.0)
4
+ devbin (0.1.0.pre.alpha.1)
5
5
  docker-sync
6
6
  pastel (~> 0.7.2)
7
7
  thor (~> 0.20.0)
@@ -30,6 +30,8 @@ GEM
30
30
  specs:
31
31
  ast (2.4.0)
32
32
  backticks (1.0.2)
33
+ benchmark-ips (2.7.2)
34
+ coderay (1.1.2)
33
35
  daemons (1.3.1)
34
36
  diff-lcs (1.3)
35
37
  docker-compose (1.1.10)
@@ -47,6 +49,7 @@ GEM
47
49
  gem_update_checker (0.2.0)
48
50
  jaro_winkler (1.5.2)
49
51
  kramdown (1.16.2)
52
+ method_source (0.9.2)
50
53
  necromancer (0.4.0)
51
54
  os (1.0.0)
52
55
  parallel (1.12.1)
@@ -56,6 +59,9 @@ GEM
56
59
  equatable (~> 0.5.0)
57
60
  tty-color (~> 0.4.0)
58
61
  powerpack (0.1.2)
62
+ pry (0.12.2)
63
+ coderay (~> 1.1.0)
64
+ method_source (~> 0.9.0)
59
65
  rainbow (3.0.0)
60
66
  rake (10.5.0)
61
67
  rouge (3.3.0)
@@ -159,8 +165,10 @@ PLATFORMS
159
165
  ruby
160
166
 
161
167
  DEPENDENCIES
168
+ benchmark-ips
162
169
  bundler (~> 1.17)
163
170
  devbin!
171
+ pry
164
172
  rake (~> 10.0)
165
173
  rspec (~> 3.0)
166
174
  rubocop-github
data/README.md CHANGED
@@ -1,21 +1,52 @@
1
1
  # devbin
2
2
 
3
3
  Working in multiple containerized environment seamlessly. Within the application folder, type one command, give the name of other application, then it should work.
4
+ - Up and running in minute
5
+ [![asciicast](https://asciinema.org/a/e9nIt1Vmk1ePEeGQXTAtRdzk3.svg)](https://asciinema.org/a/e9nIt1Vmk1ePEeGQXTAtRdzk3)
6
+ - Seamlessly control the stack
7
+ [![asciicast](https://asciinema.org/a/EzYWzB9L7m8NSdEKpnqKozhnU.svg)](https://asciinema.org/a/EzYWzB9L7m8NSdEKpnqKozhnU)
4
8
 
9
+ *P/S: this tool is under active development, commands might be changed until it reached v0.1.0*
5
10
  ## Motivation
6
- When working in a multiple containerized environment, it gets boring to repeatedly make `cd` back and forth between application's folders to execute some commands.
7
- The Convention-Over-Configuration pattern is quite popular this day, we all name our containers, arrange folders base on some predictable rules, then make some command alias for faster integrate with other containers. **devbin** will help us to bootstrapping + managing our environment seamlessly. The idea is: just remember the application name + the command you want to execute, **devbin** do all other boring things.
11
+ When working in a multiple containerized environment, it gets boring to repeatedly make `cd` back and forth between application's folders to execute some commands.
12
+ The Convention-Over-Configuration pattern is quite popular this day, we all name our containers, arrange folders base on some predictable rules, then make some command alias for faster integrate with other containers. **devbin** will help us to bootstrapping + managing our environment seamlessly.
13
+
14
+ The idea is: just remember the application name + the command you want to execute, **devbin** do all other boring things.
15
+
16
+ ```text
17
+ samples
18
+ ├── app-one
19
+ │ ├── Gemfile
20
+ │ ├── Gemfile.lock
21
+ │ └── app.rb
22
+ ├── app-two
23
+ │ ├── Gemfile
24
+ │ ├── Gemfile.lock
25
+ │ └── app.rb
26
+ ├── docker
27
+ │ └── docker-compose.yml
28
+ └── docker-sync.yml
29
+ ```
30
+
31
+ With **devbin**, you can stay at `samples/app-one` or `samples` and control the stack seamlessly:
32
+ ```sh
33
+ $ devbin start app-one --detach
34
+ $ devbin start app-two
35
+ ```
8
36
 
9
37
  ## Installation
10
38
 
11
39
  Install gem as as:
12
-
13
- $ gem install devbin
40
+ ```sh
41
+ $ gem install devbin
42
+ ```
14
43
 
15
44
  ## Usage
16
45
  TL; DR;
17
46
 
18
- $ devbin help
47
+ ```sh
48
+ $ devbin help
49
+ ```
19
50
 
20
51
 
21
52
  ## Development
@@ -34,4 +65,4 @@ Everyone interacting in the Devbin project’s codebases, issue trackers, chat r
34
65
 
35
66
  ## Copyright
36
67
 
37
- Copyright (c) 2019 Phuong 'J' Le H. See [MIT License](LICENSE.txt) for further details.
68
+ Copyright (c) 2019 Phuong 'J' Le H. See [MIT License](LICENSE.txt) for further details.
@@ -7,8 +7,8 @@ require "devbin"
7
7
  # with your gem easier. You can also use a different console, if you like.
8
8
 
9
9
  # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
10
+ require "pry"
11
+ Pry.start
12
12
 
13
- require "irb"
14
- IRB.start(__FILE__)
13
+ # require "irb"
14
+ # IRB.start(__FILE__)
@@ -30,7 +30,9 @@ Gem::Specification.new do |spec|
30
30
  # Specify which files should be added to the gem when it is released.
31
31
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
32
32
  spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
33
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
33
+ `git ls-files -z`.split("\x0").reject do |f|
34
+ f.match(%r{^(test|spec|features|samples|docs)/})
35
+ end
34
36
  end
35
37
  spec.bindir = "exe"
36
38
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
@@ -11,6 +11,9 @@ module Devbin
11
11
  # Error raised by this runner
12
12
  Error = Class.new(StandardError)
13
13
 
14
+ class_option :help, aliases: "-h", type: :boolean,
15
+ desc: "Display usage information"
16
+
14
17
  desc "version", "devbin version"
15
18
  def version
16
19
  require_relative "version"
@@ -18,7 +21,108 @@ module Devbin
18
21
  end
19
22
  map %w(--version -v) => :version
20
23
 
24
+ desc "up [APP_NAME]", "Start the application"
25
+ method_option :detach, aliases: "-d", type: :boolean, required: false, default: false,
26
+ desc: "Start the application with detached mode"
27
+ method_option :sync, aliases: "-s", type: :boolean, default: true,
28
+ desc: "Start the docker-sync also"
29
+ def up(app_name)
30
+ if options[:help]
31
+ invoke :help, ["up"]
32
+ else
33
+ require_relative "commands/up"
34
+ Devbin::Commands::Up.new(app_name, options).execute
35
+ end
36
+ end
37
+
38
+ desc "attach APP_NAME", "Attach to the application"
39
+ def attach(app_name)
40
+ if options[:help]
41
+ invoke :help, ["attach"]
42
+ else
43
+ require_relative "commands/attach"
44
+ Devbin::Commands::Attach.new(app_name, options).execute
45
+ end
46
+ end
47
+
48
+ desc "start [APP_NAME]", "Start the application"
49
+ method_option :sync, aliases: "-s", type: :boolean, default: true,
50
+ desc: "Start the docker-sync also"
51
+ def start(app_name)
52
+ if options[:help]
53
+ invoke :help, ["start"]
54
+ else
55
+ require_relative "commands/start"
56
+ Devbin::Commands::Start.new(app_name, options).execute
57
+ end
58
+ end
59
+
60
+ desc "stop APP_NAME", "Stop the rails application"
61
+ method_option :all, aliases: "-a", type: :boolean, default: false,
62
+ desc: "Stop all applications"
63
+ method_option :sync, aliases: "-s", type: :boolean, default: true,
64
+ desc: "Stop the docker-sync also"
65
+ def stop(app_name = "")
66
+ if options[:help]
67
+ invoke :help, ["stop"]
68
+ else
69
+ require_relative "commands/stop"
70
+ Devbin::Commands::Stop.new(app_name, options).execute
71
+ end
72
+ end
73
+
74
+ desc "restart APP_NAME", "Restart the application"
75
+ # method_option :all, aliases: "-a", type: :boolean, default: false,
76
+ # desc: "Restart all applications"
77
+ method_option :sync, aliases: "-s", type: :boolean, default: true,
78
+ desc: "Restart the docker-sync also"
79
+ def restart(app_name)
80
+ if options[:help]
81
+ invoke :help, ["restart"]
82
+ else
83
+ require_relative "commands/restart"
84
+ Devbin::Commands::Restart.new(app_name, options).execute
85
+ end
86
+ end
87
+
88
+ desc "bash APP_NAME", "Attach to bash for the given app"
89
+ def bash(app_name)
90
+ if options[:help]
91
+ invoke :help, ["bash"]
92
+ else
93
+ require_relative "commands/bash"
94
+ Devbin::Commands::Bash.new(app_name, options).execute
95
+ end
96
+ end
97
+ map %w(sh) => :bash
98
+
99
+ desc "off", "Close all active containers and go home"
100
+ method_option :yes, aliases: "-y", type: :boolean, default: false,
101
+ desc: "No ask, just off"
102
+ def off(*_args)
103
+ if options[:help]
104
+ invoke :help, ["off"]
105
+ else
106
+ require_relative "commands/off"
107
+ Devbin::Commands::Off.new(:all, options).execute
108
+ end
109
+ end
110
+
111
+ desc "navigate APP_NAME", "Quick navigate to the main folder of the app"
112
+ def navigate(app_name)
113
+ if options[:help]
114
+ invoke :help, ["off"]
115
+ else
116
+ require_relative "commands/navigate"
117
+ Devbin::Commands::Navigate.new(:all, options).execute
118
+ end
119
+ end
120
+ map %w(cd) => :navigate
121
+
21
122
  require_relative "commands/rails"
22
123
  register Devbin::Commands::Rails, "rails", "rails [SUBCOMMAND]", "Control the Rails application"
124
+
125
+ require_relative "commands/configure"
126
+ register Devbin::Commands::Configure, "configure", "configure [SUBCOMMAND]", "Configure the workspace"
23
127
  end
24
128
  end
@@ -127,31 +127,61 @@ module Devbin
127
127
  end
128
128
 
129
129
  def find_pwd(file_or_directory_name)
130
- path = [".", file_or_directory_name]
131
- file = nil
132
- results = Dir[path.join("/")]
133
- file = results[0]
134
- return path[0..-2] unless results.empty?
135
- 3.times do
130
+ current_path = Dir.pwd
131
+ path = ["."]
132
+ while Dir.pwd != "/"
133
+ results = Dir[file_or_directory_name]
134
+ unless results.empty?
135
+ Dir.chdir current_path
136
+ return path
137
+ end
136
138
  path.unshift("..")
137
- results = Dir[path.join("/")]
138
- file = results[0]
139
- return path[0..-2] unless results.empty?
139
+ Dir.chdir ".." # Up one level
140
140
  end
141
+ Dir.chdir current_path
141
142
  []
142
143
  end
143
144
 
144
- def docker_sync_pwd
145
- @docker_sync_pwd ||=
146
- begin
147
- path = find_pwd("docker-sync.yml")
148
- if path.empty?
149
- fail "Cannot find the `docker-sync.yml' file"
150
- end
151
- path.join("/")
145
+ def docker_sync_file
146
+ return @docker_sync_file if @docker_sync_file
147
+ find_docker_files()
148
+ @docker_sync_file
149
+ end
150
+
151
+ def docker_compose_file
152
+ return @docker_compose_file if @docker_compose_file
153
+ find_docker_files()
154
+ @docker_compose_file
155
+ end
156
+
157
+ def root
158
+ return @root if @root
159
+ find_docker_files()
160
+ @root
161
+ end
162
+
163
+ def find_docker_files
164
+ current_path = Dir.pwd
165
+ matched_root = ""
166
+ matched_docker_sync_pwd = ""
167
+ matched_docker_compose_pwd = ""
168
+ (config["workspaces"] || {}).each_pair do |_workspace_name, value|
169
+ root = value["root"]
170
+ if current_path.start_with?(root) && root.length >= matched_root.length
171
+ matched_root = root
172
+ matched_docker_sync_pwd = value["docker-sync"]
173
+ matched_docker_compose_pwd = value["docker-compose"]
152
174
  end
175
+ end
176
+ if matched_docker_sync_pwd.empty? || matched_docker_compose_pwd.empty?
177
+ fail "Cannot find the workspace for #{current_path}"
178
+ end
179
+ @root = matched_root
180
+ @docker_sync_file = matched_docker_sync_pwd.gsub(matched_root, ".")
181
+ @docker_compose_file = matched_docker_compose_pwd.gsub(matched_root, ".")
153
182
  end
154
183
 
184
+ # @deprecated
155
185
  def docker_pwd
156
186
  @docker_pwd ||=
157
187
  begin
@@ -162,5 +192,15 @@ module Devbin
162
192
  path.push("docker").join("/")
163
193
  end
164
194
  end
195
+
196
+ def config_file_path
197
+ @config_file_path ||= "#{Dir.home}/.config/devbin/config.yml"
198
+ end
199
+
200
+ def config
201
+ return @config if @config
202
+ require "yaml"
203
+ @config = YAML.load_file config_file_path
204
+ end
165
205
  end
166
206
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../command"
4
+
5
+ module Devbin
6
+ module Commands
7
+ class Attach < Devbin::Command
8
+ def initialize(app_name, options)
9
+ @app_name = app_name
10
+ @options = options
11
+ end
12
+
13
+ def execute(input: $stdin, output: $stdout)
14
+ container_id, _err = run "docker-compose -f #{docker_compose_file} ps -q #{@app_name}", chdir: root
15
+ output.puts pastel.green(
16
+ "Remember to use ",
17
+ pastel.yellow.on_bright_black.bold("Ctrl + C"),
18
+ " to detach from container ( Overrided Ctrl + P Ctrl + Q to work with VSCode )"
19
+ )
20
+ pid = Process.fork {
21
+ exec "docker attach #{container_id.strip} --detach-keys='ctrl-c'"
22
+ }
23
+ Process.wait pid
24
+ output.puts pastel.yellow.bold("OK")
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../command"
4
+
5
+ module Devbin
6
+ module Commands
7
+ class Bash < Devbin::Command
8
+ def initialize(app_name, options)
9
+ @app_name = app_name
10
+ @options = options
11
+ end
12
+
13
+ def execute(input: $stdin, output: $stdout)
14
+ Dir.chdir root do
15
+ pid = Process.fork {
16
+ exec "docker-compose -f #{docker_compose_file} exec #{@app_name} bash"
17
+ }
18
+ Process.wait pid
19
+ output.puts pastel.yellow.bold("OK")
20
+ exit 0
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+
5
+ module Devbin
6
+ module Commands
7
+ class Configure < Thor
8
+
9
+ Error = Class.new(StandardError)
10
+
11
+ namespace :configure
12
+
13
+ class_option :help, aliases: "-h", type: :boolean,
14
+ desc: "Display usage information"
15
+
16
+ desc "add APP_NAME", "Add application to the current workspace"
17
+ def add(app_name)
18
+ if options[:help]
19
+ invoke :help, ["add"]
20
+ else
21
+ require_relative "configure/add"
22
+ Devbin::Commands::Configure::Add.new(app_name, options).execute
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,224 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../command'
4
+ require "yaml"
5
+
6
+ module Devbin
7
+ module Commands
8
+ class Configure
9
+ class Add < Devbin::Command
10
+ require "yaml"
11
+ require "erb"
12
+ require "tty-file"
13
+ require "ostruct"
14
+
15
+ def initialize(app_name, options)
16
+ @app_name = app_name
17
+ @options = options
18
+ end
19
+
20
+ def execute(input: $stdin, output: $stdout)
21
+ check_or_create_config_files()
22
+ root_dir = ask_for_root()
23
+ docker_sync_file = ask_for_docker_sync_file()
24
+ docker_compose_file = ask_for_docker_compose_file()
25
+ add_new_config(
26
+ root_dir: root_dir,
27
+ docker_sync_file: docker_sync_file,
28
+ docker_compose_file: docker_compose_file
29
+ )
30
+ add_new_docker_sync(root_dir: root_dir, docker_sync_file: docker_sync_file)
31
+ add_new_docker_compose(docker_compose_file: docker_compose_file)
32
+
33
+ output.puts pastel.yellow.bold("OK")
34
+ end
35
+
36
+ private
37
+
38
+ def check_or_create_config_files
39
+ unless File.exist? config_file_path
40
+ tree = {
41
+ ".config" => [
42
+ "devbin" => []
43
+ ]
44
+ }
45
+ TTY::File.create_dir tree, Dir.home
46
+ TTY::File.copy_file config_origin_path, config_file_path
47
+ end
48
+ end
49
+
50
+ def ask_for_root(output: $stdout)
51
+ msg = pastel.yellow "Is `", pastel.bold(Dir.pwd), "' the root dir of workspace?"
52
+ if prompt.yes? msg
53
+ Dir.pwd
54
+ else
55
+ output.puts pastel.red "Please navigate to the workspace's root dir and try again"
56
+ exit 1
57
+ end
58
+ end
59
+
60
+ def ask_for_docker_sync_file(output: $stdout)
61
+ default_path = "#{Dir.pwd}/docker-sync.yml"
62
+
63
+ if File.exist? default_path
64
+ output.puts pastel.green(
65
+ "Detected the docker-sync configuration file at ",
66
+ pastel.bold(default_path),
67
+ ". Good to go"
68
+ )
69
+ return default_path
70
+ end
71
+
72
+ msg = pastel.yellow "./docker-sync.yml not found"
73
+ choices = [
74
+ { key: "1", name: "Create new file ./docker-sync.yml", value: :new },
75
+ { key: "2", name: "I will give you a path", value: :input },
76
+ { key: "3", name: "Abort", value: :stop },
77
+ ]
78
+ select_value = prompt.select msg, choices
79
+ case select_value
80
+ when :new
81
+ variables = OpenStruct.new
82
+ variables[:app_name] = @app_name
83
+ TTY::File.copy_file docker_sync_template_path, default_path, context: variables
84
+ default_path
85
+ when :input
86
+ output.puts pastel.red "Implementing: ask for docker-sync.yml path"
87
+ output.puts pastel.green(
88
+ "Wanna contribute? I'm glad to hear that.",
89
+ "\nPlease visit ",
90
+ pastel.bold.on_bright_black("https://github.com/yeuem1vannam/devbin/issues/16")
91
+ )
92
+ when :stop
93
+ output.puts pastel.red "Abort"
94
+ exit 1
95
+ else
96
+ fail "Un-handled select option"
97
+ end
98
+ end
99
+
100
+ def ask_for_docker_compose_file(output: $stdout)
101
+ default_path = "#{Dir.pwd}/docker-compose.yml"
102
+
103
+ if File.exist? default_path
104
+ output.puts pastel.green(
105
+ "Detected the docker-sync configuration file at ",
106
+ pastel.bold(default_path),
107
+ ". Good to go"
108
+ )
109
+ return default_path
110
+ end
111
+
112
+ msg = pastel.yellow "./docker-compose.yml not found"
113
+ choices = [
114
+ { key: "1", name: "Create new file ./docker-compose.yml", value: :new },
115
+ { key: "2", name: "I will give you a path", value: :input },
116
+ { key: "3", name: "Abort", value: :stop },
117
+ ]
118
+ select_value = prompt.select msg, choices
119
+ case select_value
120
+ when :new
121
+ variables = OpenStruct.new
122
+ variables[:app_name] = @app_name
123
+ TTY::File.copy_file docker_compose_template_path, default_path, context: variables
124
+ default_path
125
+ when :input
126
+ output.puts pastel.red "Implementing: ask for docker-compose.yml path"
127
+ output.puts pastel.green(
128
+ "Wanna contribute? I'm glad to hear that.",
129
+ "\nPlease visit ",
130
+ pastel.bold.on_bright_black("https://github.com/yeuem1vannam/devbin/issues/16")
131
+ )
132
+ when :stop
133
+ output.puts pastel.red "Abort"
134
+ exit 1
135
+ else
136
+ fail "Un-handled select option"
137
+ end
138
+ end
139
+
140
+ # @example
141
+ # add_new_config(
142
+ # root_dir: "/Users/yeuem1vannam/awesome-project",
143
+ # docker_sync_file: "./docker-sync.yml",
144
+ # docker_compose_file: "./docker-compose.yml"
145
+ # )
146
+ # # =>
147
+ # # ~/.config/devbin/config.yml
148
+ # # workspaces:
149
+ # # awesome-project:
150
+ # # root: /Users/yeuem1vannam/awesome-project
151
+ # # docker-sync: ./docker-sync.yml
152
+ # # docker-compose: ./docker-compose.yml
153
+ # # services:
154
+ # # app-one: ./app-one
155
+ def add_new_config(root_dir:, docker_sync_file:, docker_compose_file:)
156
+ workspace_name = Dir.pwd.split("/").last
157
+ app_name = @app_name
158
+ yaml_string = ERB.new(File.read(config_template_path)).result binding
159
+ new_config = YAML.load(yaml_string)
160
+
161
+ service_config_path = ["workspaces", workspace_name, "services"]
162
+
163
+ config = YAML.load_file config_file_path
164
+ services_config = config.dig(*service_config_path) || {}
165
+ services_config.merge! new_config.dig(*service_config_path)
166
+ new_config["workspaces"][workspace_name]["services"] = services_config
167
+ config["workspaces"] ||= {}
168
+ config["workspaces"][workspace_name] = new_config["workspaces"][workspace_name]
169
+
170
+ File.open(config_file_path, "w") do |f|
171
+ f.write config.to_yaml
172
+ end
173
+ end
174
+
175
+ # Add new section to docker-sync.yml file
176
+ def add_new_docker_sync(root_dir:, docker_sync_file:)
177
+ file_path = File.join(docker_sync_file)
178
+ config = YAML.load_file file_path
179
+ src_dir = "#{root_dir}/#{@app_name}".gsub Dir.pwd, "."
180
+ config["syncs"]["#{@app_name}-sync"] = {
181
+ "src" => src_dir,
182
+ "sync_excludes" => [".git", "node_modules"]
183
+ }
184
+ File.open(file_path, "w") do |f|
185
+ f.write config.to_yaml
186
+ end
187
+ end
188
+
189
+ # Add new section to docker-compose.yml file
190
+ def add_new_docker_compose(docker_compose_file:)
191
+ file_path = File.join(docker_compose_file)
192
+
193
+ app_name = @app_name
194
+ yaml_string = ERB.new(File.read(docker_compose_template_path)).result binding
195
+ app_config = YAML.load(yaml_string)
196
+
197
+ config = YAML.load_file file_path
198
+ config["services"].merge! app_config["services"]
199
+ config["volumes"].merge! app_config["volumes"]
200
+
201
+ File.open(file_path, "w") do |f|
202
+ f.write config.to_yaml
203
+ end
204
+ end
205
+
206
+ def config_origin_path
207
+ File.expand_path("../../templates/configure/add/config.yml", __dir__)
208
+ end
209
+
210
+ def config_template_path
211
+ File.expand_path("../../templates/configure/add/config.yml.erb", __dir__)
212
+ end
213
+
214
+ def docker_sync_template_path
215
+ File.expand_path("../../templates/configure/add/docker-sync.yml.erb", __dir__)
216
+ end
217
+
218
+ def docker_compose_template_path
219
+ File.expand_path("../../templates/configure/add/docker-compose.yml.erb", __dir__)
220
+ end
221
+ end
222
+ end
223
+ end
224
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../command"
4
+
5
+ module Devbin
6
+ module Commands
7
+ class Navigate < Devbin::Command
8
+ def initialize(app_name, options)
9
+ @app_name = app_name
10
+ @options = options
11
+ end
12
+
13
+ def execute(input: $stdin, output: $stdout)
14
+ output.puts pastel.yellow(
15
+ "Trying to navigate to application #{@app_name}",
16
+ "\n",
17
+ "Will be implemeted after `configure'"
18
+ )
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../command"
4
+
5
+ module Devbin
6
+ module Commands
7
+ class Off < Devbin::Command
8
+ def initialize(app_name, options)
9
+ @app_name = app_name
10
+ @options = options
11
+ end
12
+
13
+ def execute(input: $stdin, output: $stdout)
14
+ if will_stop?
15
+ stop()
16
+ output.puts pastel.green.on_bright_black.bold("Remember to `git push' before go home")
17
+ else
18
+ output.puts pastel.red.on_bright_black.bold("Keep working...")
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def will_stop?
25
+ return true if @options[:yes]
26
+ !prompt.no?(pastel.yellow.bold "Turn off the workspace?")
27
+ end
28
+
29
+ def stop
30
+ require_relative "stop"
31
+ stop_options = { all: true, sync: true }
32
+ Devbin::Commands::Stop.new(:all, stop_options).execute
33
+ end
34
+ end
35
+ end
36
+ end
@@ -17,6 +17,8 @@ module Devbin
17
17
  desc: "Display usage information"
18
18
  method_option :detach, aliases: "-d", type: :boolean, required: false, default: false,
19
19
  desc: "Start the server with detached mode"
20
+ method_option :sync, aliases: "-s", type: :boolean, default: true,
21
+ desc: "Start the docker-sync also"
20
22
  def server(app_name)
21
23
  if options[:help]
22
24
  invoke :help, ["server"]
@@ -53,8 +55,10 @@ module Devbin
53
55
  desc "stop APP_NAME", "Stop the rails application"
54
56
  method_option :help, aliases: "-h", type: :boolean,
55
57
  desc: "Display usage information"
56
- method_option :all, aliases: "-a", type: :boolean, required: false, default: false,
58
+ method_option :all, aliases: "-a", type: :boolean, default: false,
57
59
  desc: "Stop all applications"
60
+ method_option :sync, aliases: "-s", type: :boolean, default: true,
61
+ desc: "Stop the docker-sync also"
58
62
  def stop(app_name = "")
59
63
  if options[:help]
60
64
  invoke :help, ["stop"]
@@ -64,11 +68,13 @@ module Devbin
64
68
  end
65
69
  end
66
70
 
67
- desc "restart APP_NAME", "Restart docker-sync stack and the application"
71
+ desc "restart APP_NAME", "Restart the application"
68
72
  method_option :help, aliases: "-h", type: :boolean,
69
73
  desc: "Display usage information"
70
- method_option :detach, aliases: "-d", type: :boolean, required: false, default: false,
74
+ method_option :detach, aliases: "-d", type: :boolean, default: false,
71
75
  desc: "Restart the server with detached mode"
76
+ method_option :sync, aliases: "-s", type: :boolean, default: false,
77
+ desc: "Restart the docker-sync also"
72
78
  def restart(app_name)
73
79
  if options[:help]
74
80
  invoke :help, ["restart"]
@@ -13,7 +13,7 @@ module Devbin
13
13
 
14
14
  def execute(input: $stdin, output: $stdout)
15
15
  container_id, _err = run "docker-compose ps -q #{@app_name}", chdir: docker_pwd
16
- puts pastel.green(
16
+ output.puts pastel.green(
17
17
  "Remember to use ",
18
18
  pastel.yellow.on_bright_black.bold("Ctrl + C"),
19
19
  " to detach from container ( Overrided Ctrl + P Ctrl + Q to work with VSCode )"
@@ -22,8 +22,7 @@ module Devbin
22
22
  exec "docker attach #{container_id.strip} --detach-keys='ctrl-c'"
23
23
  }
24
24
  Process.wait pid
25
- output.puts "OK"
26
- exit 0
25
+ output.puts pastel.yellow.bold("OK")
27
26
  end
28
27
  end
29
28
  end
@@ -17,7 +17,7 @@ module Devbin
17
17
  exec "docker-compose exec #{@app_name} bundle exec rails c"
18
18
  }
19
19
  Process.wait pid
20
- output.puts "OK"
20
+ output.puts pastel.yellow.bold("OK")
21
21
  exit 0
22
22
  end
23
23
  end
@@ -12,8 +12,8 @@ module Devbin
12
12
 
13
13
  def execute(input: $stdin, output: $stdout)
14
14
  require_relative "stop"
15
- Devbin::Commands::Rails::Stop.new(@app_name, {all: true}).execute
16
- output.puts "OK"
15
+ Devbin::Commands::Rails::Stop.new(@app_name, {all: true, sync: true}).execute
16
+ output.puts pastel.green.on_bright_black.bold("Remember to `git push' before go home")
17
17
  end
18
18
  end
19
19
  end
@@ -8,16 +8,22 @@ module Devbin
8
8
  class Restart < Devbin::Command
9
9
  def initialize(app_name, options)
10
10
  @app_name = app_name
11
- @options = options
11
+ @options = options || {}
12
12
  end
13
13
 
14
14
  def execute(input: $stdin, output: $stdout)
15
15
  require_relative "stop"
16
- Devbin::Commands::Rails::Stop.new(@app_name, {all: false}).execute
17
- run "docker-sync start", chdir: docker_sync_pwd
16
+ Devbin::Commands::Rails::Stop.new(
17
+ @app_name,
18
+ {all: false, sync: @options[:sync]}
19
+ ).execute
20
+
18
21
  require_relative "server"
19
- Devbin::Commands::Rails::Server.new(@app_name, {detach: @optons && @options[:detach]}).execute
20
- output.puts "OK"
22
+ Devbin::Commands::Rails::Server.new(
23
+ @app_name,
24
+ @options.slice(:detach, :sync)
25
+ ).execute
26
+ output.puts pastel.yellow.bold("OK")
21
27
  end
22
28
  end
23
29
  end
@@ -12,12 +12,14 @@ module Devbin
12
12
  end
13
13
 
14
14
  def execute(input: $stdin, output: $stdout)
15
- # Command logic goes here ...
16
- begin
17
- run "docker-sync start", chdir: docker_sync_pwd
18
- rescue TTY::Command::ExitError => e
19
- unless e.message =~ /warning\s+docker-sync\salready\sstarted\sfor\sthis\sconfiguration/
20
- raise e
15
+ require "tty-command"
16
+ if @options[:sync]
17
+ begin
18
+ run "docker-sync start", chdir: docker_sync_pwd
19
+ rescue TTY::Command::ExitError => e
20
+ unless e.message =~ /warning\s+docker-sync\salready\sstarted\sfor\sthis\sconfiguration/
21
+ raise e
22
+ end
21
23
  end
22
24
  end
23
25
  run "docker-compose up -d #{@app_name}", chdir: docker_pwd
@@ -25,7 +27,7 @@ module Devbin
25
27
  require_relative "attach"
26
28
  Devbin::Commands::Rails::Attach.new(@app_name, {}).execute
27
29
  end
28
- output.puts "OK"
30
+ output.puts pastel.yellow.bold("OK")
29
31
  end
30
32
  end
31
33
  end
@@ -12,13 +12,15 @@ module Devbin
12
12
  end
13
13
 
14
14
  def execute(input: $stdin, output: $stdout)
15
- run "docker-sync stop", chdir: docker_sync_pwd
15
+ if @options[:sync]
16
+ run "docker-sync stop", chdir: docker_sync_pwd
17
+ end
16
18
  if @options[:all]
17
19
  run "docker-compose stop", chdir: docker_pwd
18
20
  else
19
21
  run "docker-compose stop #{@app_name}", chdir: docker_pwd
20
22
  end
21
- output.puts "OK"
23
+ output.puts pastel.yellow.bold("OK")
22
24
  end
23
25
  end
24
26
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../command"
4
+
5
+ module Devbin
6
+ module Commands
7
+ class Restart < Devbin::Command
8
+ def initialize(app_name, options)
9
+ @app_name = app_name
10
+ @options = options
11
+ end
12
+
13
+ def execute(input: $stdin, output: $stdout)
14
+ stop()
15
+ start()
16
+
17
+ output.puts pastel.yellow.bold("OK")
18
+ end
19
+
20
+ private
21
+
22
+ def stop
23
+ require_relative "stop"
24
+ stop_options = { sync: @options[:sync] }
25
+ Devbin::Commands::Stop.new(@app_name, stop_options).execute
26
+ end
27
+
28
+ def start
29
+ require_relative "start"
30
+ start_options = { sync: @options[:sync] }
31
+ Devbin::Commands::Start.new(@app_name, start_options).execute
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../command"
4
+
5
+ module Devbin
6
+ module Commands
7
+ class Start < Devbin::Command
8
+ def initialize(app_name, options)
9
+ @app_name = app_name
10
+ @options = options
11
+ end
12
+
13
+ def execute(input: $stdin, output: $stdout)
14
+ require "tty-command"
15
+ if @options[:sync]
16
+ begin
17
+ run "docker-sync start -c #{docker_sync_file}", chdir: root
18
+ rescue TTY::Command::ExitError => e
19
+ unless e.message =~ /warning\s+docker-sync\salready\sstarted\sfor\sthis\sconfiguration/
20
+ raise e
21
+ end
22
+ end
23
+ end
24
+ run "docker-compose -f #{docker_compose_file} up -d #{@app_name}", chdir: root
25
+ output.puts pastel.yellow.bold("OK")
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../command"
4
+
5
+ module Devbin
6
+ module Commands
7
+ class Stop < Devbin::Command
8
+ def initialize(app_name, options)
9
+ @app_name = app_name
10
+ @options = options
11
+ end
12
+
13
+ def execute(input: $stdin, output: $stdout)
14
+ if @options[:sync]
15
+ run "docker-sync stop -c #{docker_sync_file}", chdir: root
16
+ end
17
+ if @options[:all]
18
+ run "docker-compose -f #{docker_compose_file} stop", chdir: root
19
+ else
20
+ run "docker-compose -f #{docker_compose_file} stop #{@app_name}", chdir: root
21
+ end
22
+ output.puts pastel.yellow.bold("OK")
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../command"
4
+
5
+ module Devbin
6
+ module Commands
7
+ class Up < Devbin::Command
8
+ def initialize(app_name, options)
9
+ @app_name = app_name
10
+ @options = options
11
+ end
12
+
13
+ def execute(input: $stdin, output: $stdout)
14
+ require_relative "start"
15
+ start_options = { sync: @options[:sync] }
16
+ Devbin::Commands::Start.new(@app_name, start_options).execute
17
+ unless @options[:detach]
18
+ require_relative "attach"
19
+ attach_options = {}
20
+ Devbin::Commands::Attach.new(@app_name, attach_options).execute
21
+ end
22
+ output.puts pastel.yellow.bold("OK")
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,4 @@
1
+ ---
2
+ global:
3
+ verbose: true
4
+ workspaces:
@@ -0,0 +1,10 @@
1
+ ---
2
+ global:
3
+ verbose: true
4
+ workspaces:
5
+ <%= workspace_name %>:
6
+ root: <%= root_dir %>
7
+ docker-sync: <%= docker_sync_file %>
8
+ docker-compose: <%= docker_compose_file %>
9
+ services:
10
+ <%= app_name %>: "./<%= app_name %>"
@@ -0,0 +1,25 @@
1
+ ---
2
+ version: "3.5"
3
+
4
+ services:
5
+ <%= app_name %>:
6
+ image: ruby:2.6
7
+ working_dir: /workspace
8
+ volumes:
9
+ - <%= app_name %>-sync:/workspace
10
+ - <%= app_name %>-bundle-box:/usr/local/bundle
11
+ ports:
12
+ - 4567:4567
13
+ command:
14
+ - /bin/sh
15
+ - -c
16
+ - |
17
+ set -ex
18
+ bundle check || bundle install
19
+ ruby app.rb
20
+
21
+ volumes:
22
+ <%= app_name %>-sync:
23
+ external: true
24
+ <%= app_name %>-bundle-box:
25
+ driver: local
@@ -0,0 +1,7 @@
1
+ version: "2"
2
+ options:
3
+ verbose: true
4
+ syncs:
5
+ <%= app_name %>-sync:
6
+ src: "./<%= app_name %>"
7
+ sync_excludes: [".git", "node_modules"]
@@ -1,3 +1,3 @@
1
1
  module Devbin
2
- VERSION = "0.0.0"
2
+ VERSION = "0.1.0-alpha.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devbin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.1.0.pre.alpha.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Phuong 'J' Le H.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-01-16 00:00:00.000000000 Z
11
+ date: 2019-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: tty-box
@@ -387,7 +387,12 @@ files:
387
387
  - lib/devbin/cli.rb
388
388
  - lib/devbin/command.rb
389
389
  - lib/devbin/commands/.gitkeep
390
- - lib/devbin/commands/base.rb
390
+ - lib/devbin/commands/attach.rb
391
+ - lib/devbin/commands/bash.rb
392
+ - lib/devbin/commands/configure.rb
393
+ - lib/devbin/commands/configure/add.rb
394
+ - lib/devbin/commands/navigate.rb
395
+ - lib/devbin/commands/off.rb
391
396
  - lib/devbin/commands/rails.rb
392
397
  - lib/devbin/commands/rails/attach.rb
393
398
  - lib/devbin/commands/rails/console.rb
@@ -395,7 +400,16 @@ files:
395
400
  - lib/devbin/commands/rails/restart.rb
396
401
  - lib/devbin/commands/rails/server.rb
397
402
  - lib/devbin/commands/rails/stop.rb
403
+ - lib/devbin/commands/restart.rb
404
+ - lib/devbin/commands/start.rb
405
+ - lib/devbin/commands/stop.rb
406
+ - lib/devbin/commands/up.rb
398
407
  - lib/devbin/templates/.gitkeep
408
+ - lib/devbin/templates/configure/add/.gitkeep
409
+ - lib/devbin/templates/configure/add/config.yml
410
+ - lib/devbin/templates/configure/add/config.yml.erb
411
+ - lib/devbin/templates/configure/add/docker-compose.yml.erb
412
+ - lib/devbin/templates/configure/add/docker-sync.yml.erb
399
413
  - lib/devbin/templates/rails/attach/.gitkeep
400
414
  - lib/devbin/templates/rails/console/.gitkeep
401
415
  - lib/devbin/templates/rails/off/.gitkeep
@@ -421,9 +435,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
421
435
  version: '0'
422
436
  required_rubygems_version: !ruby/object:Gem::Requirement
423
437
  requirements:
424
- - - ">="
438
+ - - ">"
425
439
  - !ruby/object:Gem::Version
426
- version: '0'
440
+ version: 1.3.1
427
441
  requirements: []
428
442
  rubygems_version: 3.0.1
429
443
  signing_key:
File without changes