jade_systems_toolbox 0.1.3 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 77d28ae152583dfee09836b6c268f052e18a3e065db172036839fe63ae1da1f0
4
- data.tar.gz: '08307e9fb8f296a5e71e2d990e7a2edd387e1f9a0cea8d53d1d015da2feefd92'
3
+ metadata.gz: 34c1084f87c203c6d008d7c871bfeeeeba556d5208575df9a00c5c7e6c0f95a2
4
+ data.tar.gz: fa4ced1128644400b4bc691cbf9537570edf6246400dbea55a1944b2a3ec85a5
5
5
  SHA512:
6
- metadata.gz: 4ab241764b4b1514a4d770a605b2db8053b03986be8e5164a1813832e1241bf97698582046122565642b6d0b9cdb6023c2ca0912923d95224ffff54680733beb
7
- data.tar.gz: cf374537e612eb3011dd2f7dae3d57b318a7d3be9439609f61dff5bc7d87e937d8cbedf2b91a454118dbfd8428f0d6c66ec84f68633bfc3688e5f96f61ef0d45
6
+ metadata.gz: 9ad77d436e5dcdd4f8552bd19c60e53d253dd83daa1cba573c4e6a6f9c9a188ab15b5695e85a13612752e5a04acb624dd0c4e3a63a6342c3891c7efc3ee79c08
7
+ data.tar.gz: 303847847a630d6fdb089932957f7415ea163256c14ca728d163df3bfc64319037a7479acb81b127808119a95cccfedb796d36c97297ad0a5f36166869cbd95d
data/.rubocop.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  AllCops:
2
- TargetRubyVersion: 3.2
2
+ TargetRubyVersion: 3.3
3
3
 
4
4
  # Omakase Ruby styling for Rails
5
5
  inherit_gem:
@@ -66,5 +66,6 @@
66
66
  "files.trimTrailingWhitespace": true,
67
67
  "[sql]": {
68
68
  "editor.defaultFormatter": "adpyke.vscode-sql-formatter"
69
- }
69
+ },
70
+ "window.title": "jade_systems_toolbox"
70
71
  }
data/README.md CHANGED
@@ -27,20 +27,23 @@ gem install --user-install jade_systems_toolbox
27
27
 
28
28
  ### Summary
29
29
 
30
- ```
30
+ ```terminal
31
31
  Commands:
32
- tool down # docker compose down
32
+ tool down -- COMPOSE_ARGS # docker compose down. Deletes the container. You probably want stop.
33
33
  tool edit # devcontainer open
34
+ tool exec COMMAND [ARGS] # Run a command in the container and exit
34
35
  tool help [COMMAND] # Describe available commands or one specific command
35
36
  tool init # Initialize compose files and devcontainer.json
36
37
  tool initialize_docker # Initialize compose files
37
38
  tool initialize_vscode # Initialize devcontainer.json for vscode
38
- tool open # Open a page on the services's first port
39
+ tool open # Open a page on the services's first port or specified port
39
40
  tool port [CONTAINER_PORT] # Get the host port for the CONTAINER_PORT's container port CONTAINER_PORT
40
41
  tool ports # Get the host ports for the container ports defined in `compose.yml`
41
42
  tool server [COMMAND] # Run the server in the container
43
+ tool start [COMPOSE_ARGS] # docker compose up -d (aliased as `up`)
44
+ tool stop # Stop the service(s) but preserve the container(s)
42
45
  tool terminal # Run a shell in the container
43
- tool up # docker compose up -d
46
+ tool tree # Print a tree of all available commands
44
47
  tool version # Show the version number of the tool.
45
48
 
46
49
  Options:
@@ -60,7 +63,8 @@ The broad steps to start a brand new project are:
60
63
  1. Run the editor and otherwise do what you need to do to create your project.
61
64
  1. When the web server is ready to run (if you're developing a web app), run the server.
62
65
  1. Open a browser window to the web server.
63
- 1. When you're done, bring down the containers.
66
+ 1. When you're done, stop the containers.
67
+ 1. If you need to delete the containers, down tools.
64
68
 
65
69
  To start:
66
70
 
@@ -100,19 +104,37 @@ To choose a different ruby version and Debian version:
100
104
  tool init --ruby-version 3.2 --distro-version bullseye
101
105
  ```
102
106
 
107
+ A fairly common variant is to get a `compose.yml` that also has a Playwright container:
108
+
109
+ ```bash
110
+ tool init --end-to-end-tool playwright
111
+ ```
112
+
113
+ This retrieves the compose file, and puts it in your local `compose.yml`.
114
+
103
115
  You can choose a currently supported Ruby version, and a Debian version that supports that Ruby version, from the containers built by https://github.com/lcreid/docker.
104
116
 
105
- You're free to modify the `compose.yml` (and `compose.override.yml` on Linux). If you run `tool init` again, it will over-write your changes.
117
+ You're free to modify the `compose.yml` (and `compose.override.yml` on Linux). Note that if you run `tool init` again, it will over-write your changes.
106
118
 
107
119
  #### Start the Containers
108
120
 
109
121
  ```bash
110
- tool up
122
+ tool start
111
123
  ```
112
124
 
113
125
  This takes a while to run, the first time you run it when the image isn't already downloaded to your computer.
114
126
 
115
- ### Open a Terminal Session
127
+ You can add additional Docker Compose arguments to the command line. For example:
128
+
129
+ ```bash
130
+ tool start --remove-orphans
131
+ ```
132
+
133
+ If any of the command's arguments are the same as any of `tool`'s arguments,
134
+ separate the `exec` command from the rest of the command line with `--`,
135
+ like this: `tool start -- -v`.
136
+
137
+ #### Open a Terminal Session
116
138
 
117
139
  ```bash
118
140
  tool terminal
@@ -124,6 +146,14 @@ This connects to the `web` service defined in the `compose.yml` file. If you wan
124
146
  tool terminal --service mysql
125
147
  ```
126
148
 
149
+ Set some environment variables in the container (the `docker compose --env` flag):
150
+
151
+ ```bash
152
+ tool terminal -e RAILS_ENV=test
153
+ ```
154
+
155
+ `tool terminal` supports the `--mapping` argument as described under [Run the Server](run-the-server).
156
+
127
157
  #### Start VScode
128
158
 
129
159
  ```bash
@@ -136,10 +166,22 @@ tool edit
136
166
  tool server
137
167
  ```
138
168
 
169
+ By default, the container has environment variables set for port mapping.
170
+ The container environment will have variables named `HOST_PORT_xxxx`,
171
+ and `xxxx` is the container port (e.g. 3000).
172
+ The _value_ of each environment variable
173
+ is the host's port number that the container port is mapped to.
174
+
175
+ If you don't want the mapping, you can turn it off:
176
+
177
+ ```bash
178
+ tool server --no-mapping
179
+ ```
180
+
139
181
  This runs `bin/dev`. To run something else, e.g. a bare Puma so you can debug it:
140
182
 
141
183
  ```bash
142
- tool server "bin/rails s -b 0.0.0.0"
184
+ tool server bin/rails s -b 0.0.0.0
143
185
  ```
144
186
 
145
187
  If you have other services running servers, or the server is in a sub-directory of your project:
@@ -150,6 +192,8 @@ tool server --work-dir test/app --service monitor
150
192
 
151
193
  To terminate the server, type Control-C.
152
194
 
195
+ `tool server` supports the `--env` argument as described under [Open a Terminal Session](open-a-terminal-session).
196
+
153
197
  #### Open a Browser Window
154
198
 
155
199
  To connect to the server running on service `web` on port 3000:
@@ -176,12 +220,63 @@ If you want to connect to a path other than `/`:
176
220
  tool open --path letter_opener
177
221
  ```
178
222
 
223
+ #### Stop the Containers
224
+
225
+ ```bash
226
+ tool stop
227
+ ```
228
+
229
+ You can add additional Docker Compose arguments to the command line. For example:
230
+
231
+ ```bash
232
+ tool stop --remove-orphans
233
+ ```
234
+
235
+ If any of the command's arguments are the same as any of `tool`'s arguments,
236
+ separate the `exec` command from the rest of the command line with `--`,
237
+ like this: `tool stop -- -v`.
238
+
239
+ #### Run a Single Command in a Container
240
+
241
+ ```bash
242
+ tool exec ls -l ..
243
+ ```
244
+
245
+ Some things to watch for:
246
+
247
+ - If any of the command's arguments are the same as any of `tool`'s arguments,
248
+ separate the `exec` command from the rest of the command line with `--`,
249
+ like this: `tool exec -- ls -l -t ..`.
250
+ - The shell on the host processes the command line,
251
+ so you need to quote or escape the command if you want variable expansion
252
+ and other shell features to happen in the container.
253
+ For example: `tool exec ls -l '$HOME'` to show the home directory in the container, not your home directory
254
+ (which probably doesn't exist in the container).
255
+
179
256
  #### Bring Down the Containers
180
257
 
258
+ This destroys the containers, which will likely destroy all your gems.
259
+
181
260
  ```bash
182
261
  tool down
183
262
  ```
184
263
 
264
+ You can add additional Docker Compose arguments to the command line. For example: NOTE THAT THE FOLLOWING COMMAND IS VERY DESTRUCTIVE. It destroys the volume where you might have your development and test databases, or other important data:
265
+
266
+ ```bash
267
+ tool start -- -v
268
+ ```
269
+
270
+ If any of the command's arguments are the same as any of `tool`'s arguments,
271
+ separate the `exec` command from the rest of the command line with `--`,
272
+ like this: `tool down -- -v`.
273
+
274
+ Skip the confirmation mesage with:
275
+
276
+ ```bash
277
+ tool down --force
278
+ ```
279
+
185
280
  ## Development
186
281
 
187
282
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -192,13 +287,13 @@ To test locally without installing, run the executable like this:
192
287
  ruby -I lib exe/tool [COMMAND]
193
288
  ```
194
289
 
195
- To run in another directory, use the path name from the directory you're in, to the directory where you checked out the gem's code, for example:
290
+ To run in another directory, use the path from the directory you're in, to the directory where you checked out the gem's code. For example:
196
291
 
197
292
  ```bash
198
293
  ruby -I ../jade_systems_toolbox/lib ../jade_systems_toolbox/exe/tool [COMMAND]
199
294
  ```
200
295
 
201
- To install this gem onto your local machine, build it: `gem build jade_systems_toolbox.gemspec`, and install it: `gem install -l jade_systems_toolbox-0.1.2.gem`. (Change the version number to match the current version number.)
296
+ To install this gem onto your local machine, build it: `gem build jade_systems_toolbox.gemspec`, and install it: `gem install -l jade_systems_toolbox-0.1.4.gem`. (Change the version number to match the current version number.)
202
297
 
203
298
  ## Release
204
299
 
@@ -2,10 +2,10 @@
2
2
 
3
3
  module JadeSystemsToolbox
4
4
  class Cli < Thor
5
- # This and other improvements from Matt: https://mattbrictson.com/blog/fixing-thor-cli-behavior
6
- check_unknown_options!
5
+ stop_on_unknown_option! :down
7
6
 
8
7
  class << self
8
+ # This and other improvements from Matt: https://mattbrictson.com/blog/fixing-thor-cli-behavior
9
9
  def exit_on_failure? = true
10
10
  end
11
11
 
@@ -14,9 +14,13 @@ module JadeSystemsToolbox
14
14
 
15
15
  class_option :verbose, type: :boolean, default: false, aliases: "-v"
16
16
 
17
- desc "down", "docker compose down"
18
- def down
19
- system("docker compose down")
17
+ desc "down -- COMPOSE_ARGS", "docker compose down. Deletes the container. You probably want stop."
18
+ option :force, default: "n", aliases: "-f"
19
+ def down(*compose_args)
20
+ force = ask("tool down destroys the containers. Are you sure [y/N]?").downcase unless options[:force] == "y"
21
+ exit(1) if force[0] != "y"
22
+
23
+ system(([ "docker compose down" ] + compose_args).join(" "))
20
24
  end
21
25
 
22
26
  desc "edit", "devcontainer open"
@@ -24,57 +28,64 @@ module JadeSystemsToolbox
24
28
  `devcontainer open`
25
29
  end
26
30
 
31
+ desc "exec COMMAND [ARGS]", "Run a command in the container and exit"
32
+ option :env, repeatable: true, default: [], aliases: "-e", banner: "VAR=value"
33
+ option :mapping, type: :boolean, default: true, aliases: "-m"
34
+ option :service, default: "web", aliases: "-s"
35
+ option :work_dir, aliases: "-w"
36
+ def exec(command_for_container, *args)
37
+ service = options[:service]
38
+ workdir = "-w #{options[:work_dir]} " unless options[:work_dir].nil?
39
+ environment_variables = options[:env].map { "-e #{_1}" }.join(" ")
40
+ port_map_environment_variables = port_map_for_environment(service) if options[:mapping]
41
+ shell_command = [ command_for_container, *args ].join(" ")
42
+ command = [
43
+ "docker compose exec",
44
+ environment_variables,
45
+ port_map_environment_variables,
46
+ workdir,
47
+ "-it",
48
+ service,
49
+ "sh -c",
50
+ "'#{shell_command}'",
51
+ ].compact.join(" ")
52
+
53
+ system(command)
54
+ end
55
+
27
56
  desc "init", "Initialize compose files and devcontainer.json"
28
- option :compose_file, default: "compose.yml"
29
57
  option :database, default: "sqlite", aliases: "-d"
30
- option :ruby_version, default: "3.4", aliases: "-r"
31
- option :distro_version, default: "bookworm", aliases: "-t" # For Toy Story.
58
+ option :ruby_version, default: "4.0", aliases: "-r"
59
+ option :distro_version, default: "trixie", aliases: "-t" # For Toy Story.
32
60
  def init
33
61
  invoke :initialize_docker
34
62
  invoke :initialize_vscode, [], {}
35
63
  end
36
64
 
37
65
  desc "initialize_docker", "Initialize compose files"
38
- option :compose_file, default: "compose.yml"
39
66
  option :database, default: "sqlite", aliases: "-d"
40
- option :ruby_version, default: "3.4", aliases: "-r"
41
- option :distro_version, default: "bookworm", aliases: "-t" # For Toy Story.
67
+ option :ruby_version, default: "4.0", aliases: "-r"
68
+ option :distro_version, default: "trixie", aliases: "-t" # For Toy Story.
69
+ method_option :end_to_end_tool,
70
+ type: :string,
71
+ enum: [ "playwright", "selenium" ],
72
+ desc: "Use an end-to-end (browser) testing tool",
73
+ aliases: "-e"
42
74
  def initialize_docker
43
- get_and_save_file(
44
- "https://github.com/lcreid/docker/raw/refs/heads/main/rails-app-sqlite/compose.yml",
45
- ) do |file_contents|
46
- file_contents.gsub!(
47
- /jade:rails-app-[0-9]+\.[0-9]+-\w+-\w+$/,
48
- "jade:rails-app-#{options[:ruby_version] || "3.4"}" \
49
- "-#{options[:database] || "sqlite"}" \
50
- "-#{options[:distro_version] || bookworm}",
51
- )
52
- end
53
-
54
- case Gem::Platform.local.os
55
- when "linux"
56
- get_and_save_file("https://github.com/lcreid/docker/raw/refs/heads/main/Linux/compose.override.yml")
57
- else
58
- raise Error.new("Not implemented for #{Gem::Platform.local.os}", options[:verbose])
59
- end
75
+ DockerInitializer.new(**options.transform_keys(&:to_sym).except(:verbose)).get_and_save_compose_files
60
76
  end
61
77
 
62
- desc "initilize_vscode", "Initialize devcontainer.json for vscode"
78
+ desc "initialize_vscode", "Initialize devcontainer.json for vscode"
63
79
  def initialize_vscode
64
- get_and_save_file("https://github.com/lcreid/docker/raw/refs/heads/main/.devcontainer.json") do |file_contents|
65
- file_contents.gsub!(/, "compose.override.yml"/, "") unless Gem::Platform.local.os == "linux"
66
- end
67
-
68
- Dir.mkdir(".vscode") unless Dir.exist?(".vscode")
69
- [
70
- "https://github.com/lcreid/jade_systems_toolbox/raw/refs/heads/main/templates/extensions.json",
71
- "https://github.com/lcreid/jade_systems_toolbox/raw/refs/heads/main/templates/settings.json",
72
- ].each { get_and_save_file(_1, target_directory: File.join(".", ".vscode")) }
80
+ initializer = Vscode.new
81
+ initializer.write_devcontainer_json
82
+ initializer.write_extensions_json
83
+ initializer.write_settings_json
73
84
  end
74
85
 
75
- desc "open", "Open a page on the services's first port"
76
- option :service, default: "web"
77
- option :path, default: "/"
86
+ desc "open", "Open a page on the services's first port or specified port"
87
+ option :service, default: "web", aliases: "-s"
88
+ option :path, default: "/", alias: "-p"
78
89
  option :container_port, default: 3000, type: :numeric
79
90
  option :protocol, default: "http"
80
91
  def open
@@ -83,14 +94,14 @@ module JadeSystemsToolbox
83
94
  container_port = options[:container_port]
84
95
  protocol = options[:protocol]
85
96
 
86
- container_ports = compose_yaml.dig("services", "service", "ports")
97
+ container_ports = compose_yaml.dig("services", service, "ports")
87
98
  container_port = container_ports&.[](0) || container_port
88
99
  path = "/#{path}" if path[0] != "/"
89
100
  `open "#{protocol}://localhost:#{host_port_from_container_port(service:, container_port:)}#{path}"`
90
101
  end
91
102
 
92
103
  desc "port [CONTAINER_PORT]", "Get the host port for the CONTAINER_PORT's container port CONTAINER_PORT"
93
- option :service, default: "web"
104
+ option :service, default: "web", aliases: "-s"
94
105
  def port(container_port = 3000)
95
106
  service = options[:service]
96
107
  puts host_port_from_container_port(service:, container_port:)
@@ -109,25 +120,58 @@ module JadeSystemsToolbox
109
120
  end
110
121
  end
111
122
 
112
- desc "server [COMMAND]", "Run the server in the container"
113
- option :service, default: "web"
123
+ desc "server [COMMAND] [ARGS]", "Run the server in the container"
124
+ option :env, repeatable: true, default: [], aliases: "-e", banner: "VAR=value"
125
+ option :mapping, type: :boolean, default: true, aliases: "-m"
126
+ option :service, default: "web", aliases: "-s"
114
127
  option :work_dir, aliases: "-w"
115
- def server(command = "bin/dev")
128
+ def server(command = "bin/dev", *args)
116
129
  service = options[:service]
117
130
  workdir = "-w #{options[:work_dir]} " unless options[:work_dir].nil?
118
- system("docker compose exec #{workdir}#{service} #{command}")
131
+ environment_variables = options[:env].map { "-e #{_1}" }.join(" ")
132
+ port_map_environment_variables = port_map_for_environment(service) if options[:mapping]
133
+ shell_command = [ command, *args ].join(" ")
134
+ compose_command = [
135
+ "docker compose exec",
136
+ environment_variables,
137
+ port_map_environment_variables,
138
+ workdir,
139
+ service,
140
+ "sh -c",
141
+ "'#{shell_command}'",
142
+ ].compact.join(" ")
143
+
144
+ system(compose_command)
145
+ end
146
+
147
+ desc "start [COMPOSE_ARGS]", "docker compose up -d (aliased as `up`)"
148
+ def start(*compose_args)
149
+ system(([ "docker compose up -d" ] + compose_args).join(" "))
150
+ end
151
+ map "up" => :start
152
+
153
+ desc "stop", "Stop the service(s) but preserve the container(s)"
154
+ def stop
155
+ system("docker compose stop")
119
156
  end
120
157
 
121
158
  desc "terminal", "Run a shell in the container"
122
- option :service, default: "web"
159
+ option :env, repeatable: true, default: [], aliases: "-e", banner: "VAR=value"
160
+ option :mapping, type: :boolean, default: true, aliases: "-m"
161
+ option :service, default: "web", aliases: "-s"
123
162
  def terminal
124
163
  service = options[:service]
125
- system("docker compose exec -it #{service} '/bin/bash'")
126
- end
127
-
128
- desc "up", "docker compose up -d"
129
- def up
130
- system("docker compose up -d")
164
+ environment_variables = options[:env].map { "-e #{_1}" }.join(" ")
165
+ port_map_environment_variables = port_map_for_environment(service) if options[:mapping]
166
+ command = [
167
+ "docker compose exec",
168
+ environment_variables,
169
+ port_map_environment_variables,
170
+ "-it",
171
+ service,
172
+ "'/bin/bash'",
173
+ ].join(" ")
174
+ system(command)
131
175
  end
132
176
 
133
177
  desc "version", "Show the version number of the tool."
@@ -139,32 +183,14 @@ module JadeSystemsToolbox
139
183
 
140
184
  def compose_yaml = @compose_yaml ||= YAML.load_file(options[:compose_file] || "compose.yml")
141
185
 
142
- def get_and_save_file(url, target_directory: nil)
143
- file_contents = get_file_from_internet(url:)
186
+ def get_and_save_file(url, target_directory: nil, target_file_name: nil)
187
+ file_contents = Http.get_file(url:)
144
188
  yield file_contents if block_given?
145
- file_name = Pathname.new(url).basename.to_s
189
+ file_name = target_file_name || Pathname.new(url).basename.to_s
146
190
  file_name = Pathname.new(target_directory) + file_name unless target_directory.nil?
147
191
  File.write(file_name, file_contents)
148
192
  end
149
193
 
150
- def get_file_from_internet(url:, redirects: 10)
151
- raise Errorl.new("Too many redirects", options[:verbose]) if redirects.zero?
152
-
153
- uri = URI.parse(url)
154
- request = Net::HTTP.new(uri.host, uri.port)
155
- request.use_ssl = true
156
- response = request.get(uri.path)
157
-
158
- case response
159
- when Net::HTTPSuccess
160
- response.body
161
- when Net::HTTPRedirection
162
- get_file_from_internet(redirects: redirects - 1, url: response["location"])
163
- else
164
- response.error!
165
- end
166
- end
167
-
168
194
  def host_port_from_container_port(container_port:, service: "web")
169
195
  ports = container_port.to_s.match(/([0-9]+:){0,1}([0-9]+$)/)
170
196
  if !ports[1].nil?
@@ -174,5 +200,31 @@ module JadeSystemsToolbox
174
200
  output.match(/[0-9]+$/)
175
201
  end
176
202
  end
203
+
204
+ def port_map(service)
205
+ service_ports = compose_yaml.dig("services", service, "ports")
206
+ service_ports&.reduce({}) do |acc, port|
207
+ acc[port] = host_port_from_container_port(container_port: port, service:).to_s
208
+ acc
209
+ end
210
+ end
211
+
212
+ def port_map_for_environment(service)
213
+ port_map(service).map do |container_port, host_port|
214
+ "-e HOST_PORT_#{container_port}=#{host_port}"
215
+ end.join(" ")
216
+ end
217
+
218
+ def handle_argument_error(command, error, args, arity)
219
+ # Check if the error is due to an unknown option or incorrect invocation
220
+ if (error.is_a?(Thor::UnknownArgumentError) || error.message.include?("was called with arguments")) &&
221
+ [ "down" ].include?(command)
222
+ # Return to let Thor proceed instead of raising the error
223
+ nil
224
+ else
225
+ # Fallback to standard Thor behavior for actual code bugs
226
+ super
227
+ end
228
+ end
177
229
  end
178
230
  end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JadeSystemsToolbox
4
+ class DockerInitializer
5
+ def initialize(compose_file: nil, database: nil, ruby_version: nil, distro_version: nil, end_to_end_tool: nil)
6
+ @end_to_end_tool = end_to_end_tool&.downcase&.strip
7
+ database = database.to_s.downcase.strip
8
+ @database = database unless %w[false none nil ""].include?(database)
9
+ @ruby_version = ruby_version&.downcase&.strip
10
+ @distro_version = distro_version&.downcase&.strip
11
+ end
12
+
13
+ def compose_file_path
14
+ base_dir = [ "rails-app", database ].compact.join("-")
15
+ Pathname("compose-files").join(*([ base_dir, end_to_end_tool, "compose.yml" ].compact))
16
+ end
17
+
18
+ def get_and_save_compose_files
19
+ compose_file = Http.get_file(url: Http.url(path: compose_file_path))
20
+ customize_compose_file!(compose_file)
21
+ File.write("compose.yml", compose_file)
22
+
23
+ case Gem::Platform.local.os
24
+ when "linux"
25
+ compose_override_file = Http.get_file(url: Http.url(path: "compose-files/Linux/compose.override.yml"))
26
+ File.write("compose.override.yml", compose_override_file)
27
+ end
28
+ end
29
+
30
+ def customize_compose_file!(base_file)
31
+ base_file.gsub!("${RUBY_VERSION:-4.0}", ruby_version) unless ruby_version.nil?
32
+ base_file.gsub!("${DISTRO_VERSION:-trixie}", distro_version) unless distro_version.nil?
33
+ base_file
34
+ end
35
+
36
+ private
37
+
38
+ attr_reader :end_to_end_tool
39
+ attr_reader :database
40
+ attr_reader :ruby_version
41
+ attr_reader :distro_version
42
+ end
43
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JadeSystemsToolbox
4
+ class Http
5
+ class << self
6
+ def url(path:)
7
+ base_url + path.to_s
8
+ end
9
+
10
+ def get_file(url:, redirects: 10)
11
+ raise Error.new("Too many redirects", options[:verbose]) if redirects.zero?
12
+
13
+ uri = URI.parse(url)
14
+ request = Net::HTTP.new(uri.host, uri.port)
15
+ request.use_ssl = true
16
+ response = request.get(uri.path)
17
+
18
+ case response
19
+ when Net::HTTPSuccess
20
+ response.body
21
+ when Net::HTTPRedirection
22
+ get_file(redirects: redirects - 1, url: response["location"])
23
+ else
24
+ response.value
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def base_url = "https://github.com/lcreid/jade_systems_toolbox/raw/refs/heads/main/"
31
+ end
32
+ end
33
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JadeSystemsToolbox
4
- VERSION = "0.1.3"
4
+ VERSION = "0.2.0"
5
5
  end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module JadeSystemsToolbox
6
+ class Vscode
7
+ def write_settings_json
8
+ target_file = target_directory.join("settings.json")
9
+ settings = if !target_file.exist? || target_file.empty?
10
+ {}
11
+ else
12
+ JSON.load_file(target_file)
13
+ end
14
+
15
+ settings["window.title"] = Pathname.pwd.basename
16
+ File.write(target_file, JSON.pretty_generate(settings))
17
+ end
18
+
19
+ def write_devcontainer_json
20
+ devcontainer_text = Http.get_file(url: Http.url(path: "templates/.devcontainer.json"))
21
+ devcontainer_json = JSON.parse(devcontainer_text, allow_comments: true)
22
+ unless Gem::Platform.local.os == "linux"
23
+ devcontainer_json["dockerComposeFile"] = [ "compose.yml" ]
24
+ end
25
+ Pathname(".devcontainer.json").write(JSON.pretty_generate(devcontainer_json))
26
+ end
27
+
28
+ def write_extensions_json
29
+ extensions_text = Http.get_file(url: Http.url(path: "templates/extensions.json"))
30
+ target_directory.join("extensions.json").write(extensions_text)
31
+ end
32
+
33
+ def get_and_write_settings_json
34
+ settings_text = Http.get_file(url: Http.url(path: "templates/settings.json"))
35
+ settings = JSON.parse(settings_text, allow_comments: true)
36
+ settings["window.title"] = Pathname.pwd.basename
37
+
38
+ target_file = target_directory.join("settings.json")
39
+ File.write(target_file, JSON.pretty_generate(settings))
40
+ end
41
+
42
+ private
43
+
44
+ def target_directory
45
+ @target_directory unless @target_directory.nil?
46
+
47
+ @target_directory = Pathname("./.vscode")
48
+ FileUtils.mkdir(@target_directory) unless @target_directory.exist?
49
+ @target_directory
50
+ end
51
+ end
52
+ end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "debug"
4
3
  require "net/http"
5
4
  require "pathname"
6
5
  require "thor"
@@ -8,7 +7,10 @@ require "yaml"
8
7
 
9
8
  require_relative "jade_systems_toolbox/version"
10
9
  require_relative "jade_systems_toolbox/cli"
10
+ require_relative "jade_systems_toolbox/docker_initializer"
11
11
  require_relative "jade_systems_toolbox/error_reporter"
12
+ require_relative "jade_systems_toolbox/http"
13
+ require_relative "jade_systems_toolbox/vscode"
12
14
 
13
15
  module JadeSystemsToolbox
14
16
  class Error < StandardError
@@ -0,0 +1,36 @@
1
+ // For format details, see https://aka.ms/devcontainer.json. For config options, see the
2
+ // README at: https://github.com/devcontainers/templates/tree/main/src/docker-existing-docker-compose
3
+ {
4
+ // Update the 'dockerComposeFile' list if you have more compose files or use different names.
5
+ "dockerComposeFile": ["compose.yml", "compose.override.yml"],
6
+
7
+ // The 'service' property is the name of the service for the container that VS Code should
8
+ // use. Update this value and .devcontainer/docker-compose.yml to the real service name.
9
+ "service": "web",
10
+
11
+ // The optional 'workspaceFolder' property is the path VS Code should open by default when
12
+ // connected. This is typically a file mount in .devcontainer/docker-compose.yml
13
+ "workspaceFolder": "/home/dev/app",
14
+ // "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}"
15
+
16
+ // Features to add to the dev container. More info: https://containers.dev/features.
17
+ // "features": {},
18
+
19
+ // Use 'forwardPorts' to make a list of ports inside the container available locally.
20
+ // "forwardPorts": [],
21
+
22
+ // Uncomment the next line if you want start specific services in your Docker Compose config.
23
+ // "runServices": [],
24
+
25
+ // Uncomment the next line if you want to keep your containers running after VS Code shuts down.
26
+ "shutdownAction": "none"
27
+
28
+ // Uncomment the next line to run commands after the container is created.
29
+ // "postCreateCommand": "cat /etc/os-release",
30
+
31
+ // Configure tool-specific properties.
32
+ // "customizations": {},
33
+
34
+ // Uncomment to connect as an existing user other than the container default. More info: https://aka.ms/dev-containers-non-root.
35
+ // "remoteUser": "devcontainer"
36
+ }
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jade_systems_toolbox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Larry Reid
8
+ autorequire:
8
9
  bindir: exe
9
10
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
11
+ date: 2026-11-09 00:00:00.000000000 Z
11
12
  dependencies:
12
13
  - !ruby/object:Gem::Dependency
13
14
  name: thor
@@ -23,6 +24,7 @@ dependencies:
23
24
  - - "~>"
24
25
  - !ruby/object:Gem::Version
25
26
  version: '1.3'
27
+ description:
26
28
  email:
27
29
  - lcreid@jadesystems.ca
28
30
  executables:
@@ -41,9 +43,13 @@ files:
41
43
  - exe/tool
42
44
  - lib/jade_systems_toolbox.rb
43
45
  - lib/jade_systems_toolbox/cli.rb
46
+ - lib/jade_systems_toolbox/docker_initializer.rb
44
47
  - lib/jade_systems_toolbox/error_reporter.rb
48
+ - lib/jade_systems_toolbox/http.rb
45
49
  - lib/jade_systems_toolbox/version.rb
50
+ - lib/jade_systems_toolbox/vscode.rb
46
51
  - sig/jade_systems_toolbox.rbs
52
+ - templates/.devcontainer.json
47
53
  - templates/extensions.json
48
54
  - templates/settings.json
49
55
  homepage: https://github.com/lcreid/jade_systems_toolbox
@@ -53,6 +59,7 @@ metadata:
53
59
  homepage_uri: https://github.com/lcreid/jade_systems_toolbox
54
60
  source_code_uri: https://github.com/lcreid/jade_systems_toolbox
55
61
  changelog_uri: https://github.com/lcreid/jade_systems_toolbox/CHANGELOG.nd
62
+ post_install_message:
56
63
  rdoc_options: []
57
64
  require_paths:
58
65
  - lib
@@ -60,14 +67,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
60
67
  requirements:
61
68
  - - ">="
62
69
  - !ruby/object:Gem::Version
63
- version: '3.2'
70
+ version: '3.3'
64
71
  required_rubygems_version: !ruby/object:Gem::Requirement
65
72
  requirements:
66
73
  - - ">="
67
74
  - !ruby/object:Gem::Version
68
75
  version: '0'
69
76
  requirements: []
70
- rubygems_version: 3.6.7
77
+ rubygems_version: 3.5.22
78
+ signing_key:
71
79
  specification_version: 4
72
80
  summary: A collection of command line commands to support development.
73
81
  test_files: []