lbhrr 1.1.1 → 2.33.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.DS_Store +0 -0
- data/.ruby-version +1 -0
- data/crane.png +0 -0
- data/exe/lbhrr +384 -259
- data/lib/.kafkr/acknowledged_messages.txt +1 -0
- data/lib/.kafkr/message_queue.txt +5 -0
- data/lib/lbhrr/version.rb +1 -1
- data/templates/lib/panamax.rb.erb +4 -0
- data/templates/lib/rubygems_plugin.rb.erb +41 -0
- data/templates/panamax.gemspec.erb +24 -0
- metadata +11 -5
- data/.gitlab-ci.yml +0 -10
- data/config/manifest.yml +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5a5a72e033c32aae92732521d690ca1bb95db44ffbea53d9be161f183e83b2bd
|
4
|
+
data.tar.gz: d063d071b65b6a56d29774185d5a3f975cecd7d491e90344d3adf8e5c8fc2286
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a4b0ec574e5d44c09db1ed6b91ea3267bf22a8d4dc382692f9984e53b63a095f216c2ec8c99be737299cc4e84a9791298d57af1e5d1f2c845b814e703e237ea1
|
7
|
+
data.tar.gz: d174498ec46033204e0685b279b1e801b1812c3db81999d8bb732256caad47399b491abb7f3aa5d3408f30eaa3060b5767686beacd0728971b4d970d90e4eb9d
|
data/.DS_Store
ADDED
Binary file
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.2.2
|
data/crane.png
ADDED
Binary file
|
data/exe/lbhrr
CHANGED
@@ -1,177 +1,243 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "fileutils"
|
4
|
+
require "logger"
|
5
|
+
require "erb"
|
6
|
+
require "open3"
|
7
|
+
require "io/console"
|
2
8
|
require_relative "../lib/lbhrr"
|
3
9
|
|
4
10
|
class LbhrrCLI < Thor
|
11
|
+
include Thor::Actions
|
12
|
+
|
13
|
+
# Error handling
|
14
|
+
def self.exit_on_failure?
|
15
|
+
true
|
16
|
+
end
|
17
|
+
|
5
18
|
no_commands do
|
19
|
+
require 'net/http'
|
20
|
+
require 'uri'
|
6
21
|
|
7
|
-
def
|
8
|
-
|
22
|
+
def fibonacci(n)
|
23
|
+
[21,34,55][n]
|
9
24
|
end
|
10
25
|
|
11
|
-
def
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
26
|
+
def ok(url,grace: 0)
|
27
|
+
retries = 2
|
28
|
+
sleep(grace)
|
29
|
+
(0..retries).each do |i|
|
30
|
+
uri = URI(url)
|
31
|
+
response = Net::HTTP.get_response(uri)
|
32
|
+
|
33
|
+
if response.is_a?(Net::HTTPSuccess)
|
34
|
+
yield if block_given?
|
35
|
+
break
|
36
|
+
else
|
37
|
+
puts "Response was not 200, it was #{response.code}., check logs gor website"
|
38
|
+
end
|
39
|
+
|
40
|
+
delay = fibonacci(i)
|
41
|
+
sleep(delay)
|
42
|
+
|
43
|
+
|
22
44
|
end
|
45
|
+
end
|
23
46
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
47
|
+
# Example usage:
|
48
|
+
def with_error_handling
|
49
|
+
# Ensure the ~/.lbhrr directory exists
|
50
|
+
log_dir = File.expand_path("~/.lbhrr")
|
51
|
+
FileUtils.mkdir_p(log_dir) unless Dir.exist?(log_dir)
|
52
|
+
|
53
|
+
# Setup logger
|
54
|
+
logger = Logger.new("#{log_dir}/error.log")
|
55
|
+
|
56
|
+
begin
|
57
|
+
yield
|
58
|
+
rescue Interrupt
|
59
|
+
#logger.error("Operation interrupted by Ctrl+C")
|
60
|
+
rescue => e
|
61
|
+
logger.error("Error occurred: #{e.class}: #{e.message}")
|
62
|
+
raise
|
29
63
|
end
|
64
|
+
end
|
30
65
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
66
|
+
def increment_version(version, focus = :minor)
|
67
|
+
major, minor, patch = version.split(".").map(&:to_i)
|
68
|
+
|
69
|
+
case focus
|
70
|
+
when :major
|
71
|
+
major += 1
|
72
|
+
# Reset minor and patch to 0 when major version increments
|
73
|
+
minor = 0
|
74
|
+
patch = 0
|
75
|
+
when :minor
|
76
|
+
minor += 1
|
77
|
+
# Reset patch to 0 when minor version increments
|
78
|
+
patch = 0
|
79
|
+
when :patch
|
80
|
+
patch += 1
|
81
|
+
else
|
82
|
+
raise ArgumentError, "Invalid focus: #{focus}. Valid options are :major, :minor, :patch."
|
83
|
+
end
|
36
84
|
|
85
|
+
"#{major}.#{minor}.#{patch}"
|
37
86
|
end
|
38
87
|
|
39
|
-
def
|
40
|
-
#
|
41
|
-
|
88
|
+
def progressing(name = "Task")
|
89
|
+
# Start the long-running task in a separate thread, yielding to the given block
|
90
|
+
task_thread = Thread.new do
|
91
|
+
yield if block_given? # Execute the block representing the long-running task
|
92
|
+
end
|
42
93
|
|
43
|
-
|
44
|
-
|
94
|
+
spinner = Enumerator.new do |e|
|
95
|
+
rectangles = ["[ ]","[=]", "[==]", "[===]", "[===]", "[==","[=]","[ ]"]
|
96
|
+
loop do
|
97
|
+
rectangles.each { |rect| e.yield rect }
|
98
|
+
rectangles.reverse.each { |rect| e.yield rect }
|
99
|
+
end
|
100
|
+
end
|
45
101
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
102
|
+
until task_thread.join(0.1)
|
103
|
+
print "#{name} is in progress.. \r#{spinner.next}"
|
104
|
+
$stdout.flush
|
105
|
+
sleep(0.1)
|
106
|
+
end
|
50
107
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
gitignore_content = '
|
56
|
-
# Ignore bundler config and installed gems.
|
57
|
-
/.bundle
|
58
|
-
# Ignore all logfiles and tempfiles.
|
59
|
-
/log/*
|
60
|
-
/tmp/*
|
61
|
-
!/log/.keep
|
62
|
-
!/tmp/.keep
|
63
|
-
|
64
|
-
# Ignore other unneeded files.
|
65
|
-
*.pid
|
66
|
-
*.swap
|
67
|
-
*.gem
|
68
|
-
*.rbc
|
69
|
-
.DS_Store
|
70
|
-
.idea
|
71
|
-
.byebug_history
|
72
|
-
'
|
73
|
-
|
74
|
-
File.write(gitignore_path, gitignore_content.strip)
|
75
|
-
puts ".gitignore created for Rack project."
|
76
|
-
rescue => e
|
77
|
-
puts "Error creating .gitignore: #{e.message}"
|
108
|
+
# Clear the progress line
|
109
|
+
print "#{name} is in progress.. #{spinner.peek}\r"
|
110
|
+
nil
|
78
111
|
end
|
79
112
|
|
80
|
-
def
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
113
|
+
def find_container_ip(container_name)
|
114
|
+
initial_backoff_intervals = [5, 8, 13, 21]
|
115
|
+
ip_backoff_intervals = [1, 2, 3, 5, 8]
|
116
|
+
ip_address = nil
|
117
|
+
|
118
|
+
# First, check if the container is running
|
119
|
+
container_running = false
|
120
|
+
initial_backoff_intervals.each do |interval|
|
121
|
+
output, status = Open3.capture2("lxc list -f csv | grep #{container_name}")
|
122
|
+
if status.success? && !output.empty? && output.split(",")[1].strip == "RUNNING"
|
123
|
+
container_running = true
|
124
|
+
break
|
125
|
+
end
|
126
|
+
sleep(interval)
|
127
|
+
end
|
128
|
+
|
129
|
+
# If container is running, look for the IP address
|
130
|
+
if container_running
|
131
|
+
ip_backoff_intervals.each do |interval|
|
132
|
+
output, status = Open3.capture2("lxc list -f csv | grep #{container_name}")
|
133
|
+
if status.success? && !output.empty?
|
134
|
+
data = output.split(",")
|
135
|
+
ip_address = data[2].split(" ").first
|
136
|
+
if !ip_address.nil? && !ip_address.empty?
|
137
|
+
yield(ip_address) if block_given?
|
138
|
+
break
|
139
|
+
end
|
140
|
+
end
|
141
|
+
sleep(interval)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
ip_address
|
94
146
|
end
|
95
147
|
|
96
|
-
def
|
97
|
-
|
98
|
-
|
99
|
-
"
|
100
|
-
|
101
|
-
|
148
|
+
def clean_up(name = nil)
|
149
|
+
# Remove the build directory
|
150
|
+
if Dir.exist?("build")
|
151
|
+
FileUtils.rm_r("build")
|
152
|
+
end
|
153
|
+
# Remove gems on the container
|
154
|
+
`lxc exec #{name} -- rm -rf /var/gems/*`
|
102
155
|
end
|
103
156
|
|
104
|
-
def
|
157
|
+
def modify_manifest
|
158
|
+
file_path = "config/manifest.yml" # Update the path if necessary
|
105
159
|
|
106
|
-
|
107
|
-
|
160
|
+
# Read the YAML file
|
161
|
+
if File.exist?(file_path)
|
162
|
+
yaml_content = YAML.load_file(file_path)
|
108
163
|
|
109
|
-
|
164
|
+
# Yield the hash to the block for modification
|
165
|
+
yield(yaml_content) if block_given?
|
110
166
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
167
|
+
# Write the changes back to the YAML file
|
168
|
+
File.write(file_path, yaml_content.to_yaml)
|
169
|
+
else
|
170
|
+
puts "File not found: #{file_path}"
|
171
|
+
end
|
172
|
+
end
|
115
173
|
|
116
|
-
|
174
|
+
def notify_terminal(message, title)
|
175
|
+
`terminal-notifier -message "#{message}" -title "#{title}" -contentImage "crane.png"`
|
176
|
+
end
|
117
177
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
end
|
122
|
-
RUBY
|
178
|
+
def containerized?(name)
|
179
|
+
`lxc list -c n -f csv`.include? name
|
180
|
+
end
|
123
181
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
exe_directory = File.join(Dir.pwd, "exe")
|
182
|
+
def create_container(name, image = "panamax")
|
183
|
+
return if containerized? name
|
184
|
+
config = load_configuration
|
128
185
|
|
129
|
-
|
130
|
-
|
131
|
-
File.chmod(0o755, run_file_path) # Set executable permission
|
132
|
-
puts "Created ./exe/run file."
|
133
|
-
end
|
186
|
+
# Set default image if not specified
|
187
|
+
image = config["image"].nil? ? "panamax" : config["image"]
|
134
188
|
|
135
|
-
|
136
|
-
run_file_path = File.join(Dir.pwd, "exe", "run")
|
137
|
-
service_run_file_content = "#!/bin/sh\n HARBR_ENV=$2 ruby service"
|
138
|
-
exe_directory = File.join(Dir.pwd, "exe")
|
189
|
+
`lxc launch #{image} #{name}` unless containerized? name
|
139
190
|
|
140
|
-
|
141
|
-
|
142
|
-
File.chmod(0o755, run_file_path) # Set executable permission
|
143
|
-
puts "Created ./exe/run file."
|
191
|
+
find_container_ip(name) do |ip_address|
|
192
|
+
`harbr container add #{name} #{ip_address}`
|
144
193
|
|
145
|
-
|
146
|
-
|
147
|
-
|
194
|
+
if config["host"].nil?
|
195
|
+
`harbr host add #{name} 9292 #{name}.harbr.zero2one.ee`
|
196
|
+
`harbr host add #{name} 9393 next.#{name}.harbr.zero2one.ee`
|
197
|
+
else
|
198
|
+
`harbr host add #{name} 9292 #{config["host"]}`
|
199
|
+
`harbr host add #{name} 9393 next.#{config["host"]}`
|
200
|
+
end
|
148
201
|
|
202
|
+
`harbr commit`
|
149
203
|
end
|
204
|
+
end
|
150
205
|
|
206
|
+
# Method to process ERB templates and write to build directory
|
207
|
+
def process_template(template_path, target_path, binding)
|
208
|
+
content = ERB.new(File.read(template_path)).result(binding)
|
209
|
+
File.write(target_path, content)
|
210
|
+
end
|
151
211
|
|
212
|
+
def manifest?
|
213
|
+
File.exist? File.join(Dir.pwd, "config", "manifest.yml")
|
214
|
+
end
|
152
215
|
|
216
|
+
def commit(new_message)
|
217
|
+
# Ensure we are in a git repository
|
218
|
+
system("git rev-parse --git-dir > /dev/null 2>&1") or raise "Not a git repository"
|
219
|
+
# commit changes with the new message
|
220
|
+
`git commit -am '#{new_message}'`
|
153
221
|
rescue => e
|
154
|
-
puts "Error
|
222
|
+
puts "Error during commit amend: #{e.message}"
|
155
223
|
end
|
156
224
|
|
157
|
-
def
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
"host" => "#{File.basename(Dir.pwd)}.harbr.zero2one.ee",
|
164
|
-
"host_aliases" => []
|
165
|
-
}
|
225
|
+
def amend_last_commit(new_message)
|
226
|
+
# Ensure we are in a git repository
|
227
|
+
system("git rev-parse --git-dir > /dev/null 2>&1") or raise "Not a git repository"
|
228
|
+
|
229
|
+
# Amend the last commit with the new message
|
230
|
+
system("git commit --amend -m \"#{new_message}\"") or raise "Failed to amend the last commit"
|
166
231
|
|
167
|
-
|
232
|
+
puts "Successfully amended the last commit."
|
233
|
+
rescue => e
|
234
|
+
puts "Error during commit amend: #{e.message}"
|
168
235
|
end
|
169
236
|
|
170
237
|
def load_configuration
|
171
238
|
global_config_dir = File.expand_path("~/.config/harbr")
|
172
239
|
global_config_path = File.join(global_config_dir, "manifest.yml")
|
173
240
|
local_config_path = File.join(Dir.pwd, "config", "manifest.yml")
|
174
|
-
|
175
241
|
# Ensure global configuration exists
|
176
242
|
unless File.exist?(global_config_path)
|
177
243
|
FileUtils.mkdir_p(global_config_dir) unless Dir.exist?(global_config_dir)
|
@@ -193,189 +259,248 @@ RUBY
|
|
193
259
|
global_config
|
194
260
|
end
|
195
261
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
262
|
+
desc "containerize", "Create a container for an app"
|
263
|
+
def containerize
|
264
|
+
config = load_configuration
|
265
|
+
name = config["name"]
|
266
|
+
image = config["image"]
|
267
|
+
if manifest?
|
268
|
+
create_container(name, image)
|
269
|
+
end
|
203
270
|
end
|
204
|
-
end
|
205
271
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
272
|
+
desc "rollback", "rollback an application using the configuration from config/manifest.yml"
|
273
|
+
def rollback(name = nil)
|
274
|
+
with_error_handling do
|
275
|
+
progressing("Roll back") do
|
276
|
+
config = load_configuration
|
277
|
+
name = name.nil? ? config["name"] : name
|
278
|
+
rolled_back = config["rolledback"]
|
279
|
+
|
280
|
+
if config["rolledback"] == true
|
281
|
+
puts "No rollback available"
|
282
|
+
else
|
283
|
+
`lxc exec #{name} -- bash -c 'if [ -d /var/www/app/container/live ]; then rm /var/www/app/container/live; fi'`
|
284
|
+
|
285
|
+
`lxc exec #{name} -- mv /var/www/app/container/rollback /var/www/app/container/live`
|
286
|
+
`lxc exec #{name} -- bash -c 'if [ -d /var/www/app/container/rollback ]; then rm /var/www/app/container/rollback; fi'`
|
287
|
+
`lxc exec #{name} -- sv restart live`
|
288
|
+
modify_manifest do |config|
|
289
|
+
config["live"] = config["rollback"]
|
290
|
+
config["rolledback"] = true
|
291
|
+
end
|
292
|
+
end
|
293
|
+
commit("Rolled back #{name} to version #{config["rollback"]} on live")
|
294
|
+
ok("https://#{config['host']}/ok",grace: 15) do
|
295
|
+
notify_terminal("#{name} version #{config['rollback']} is up on live!", "Lbhhr")
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
214
299
|
end
|
215
|
-
# Load and merge configurations
|
216
|
-
local_config = YAML.load_file(local_config_path) || {}
|
217
|
-
create_gitignore
|
218
|
-
create_run_file(options[:type])
|
219
300
|
|
220
301
|
|
221
302
|
|
222
|
-
# Include other initialization tasks if necessary
|
223
|
-
end
|
224
303
|
|
225
|
-
desc "containers", "list all containers"
|
226
|
-
def containers
|
227
|
-
config = load_configuration
|
228
|
-
host = config["host"]
|
229
|
-
user = config["user"]
|
230
|
-
puts `ssh #{user}@#{host} 'harbr containers'`
|
231
304
|
end
|
232
305
|
|
233
|
-
desc "drop", "Destroy an app and remove all traces"
|
234
|
-
def drop(name=nil)
|
235
|
-
config = load_configuration
|
236
|
-
host = config["host"]
|
237
|
-
user = config["user"]
|
238
|
-
|
239
|
-
if name.nil?
|
240
306
|
|
241
|
-
|
242
|
-
|
243
|
-
|
307
|
+
desc "drop", "Destroy an app and remove all traces"
|
308
|
+
def drop(name = nil)
|
309
|
+
with_error_handling do
|
310
|
+
return unless yes?("Are you sure you want to drop this app? This action cannot be undone. (y/n)")
|
311
|
+
|
312
|
+
# Load configuration and retrieve the name if not provided
|
313
|
+
config = load_configuration unless name
|
314
|
+
name ||= config["name"]
|
315
|
+
|
316
|
+
progressing("Drop") do
|
317
|
+
if manifest?
|
318
|
+
# Check if the LXC container exists
|
319
|
+
if `lxc list`.include?(name)
|
320
|
+
# Commands to run if the container exists
|
321
|
+
`lxc delete #{name} --force`
|
322
|
+
`harbr container delete #{name}`
|
323
|
+
`harbr commit`
|
324
|
+
end
|
325
|
+
end
|
244
326
|
end
|
327
|
+
end
|
328
|
+
end
|
245
329
|
|
330
|
+
desc "logs", "Show logs for the container"
|
331
|
+
method_option :live, type: :boolean, aliases: "-l", desc: "Process in live mode"
|
332
|
+
def logs(name = nil)
|
333
|
+
with_error_handling do
|
334
|
+
config = load_configuration
|
246
335
|
name = config["name"]
|
336
|
+
if options[:live]
|
337
|
+
exec "lxc exec #{name} -- tail -f /var/log/container/live/current"
|
338
|
+
else
|
339
|
+
exec "lxc exec #{name} -- tail -f /var/log/container/next/current"
|
340
|
+
end
|
247
341
|
end
|
248
|
-
|
249
|
-
puts "Destroying app: #{name}"
|
250
|
-
`ssh #{user}@#{host} 'harbr destroy #{name}'`
|
251
|
-
|
252
|
-
puts "App #{name} has been successfully destroyed."
|
253
342
|
end
|
254
343
|
|
255
|
-
desc "
|
256
|
-
|
257
|
-
|
344
|
+
desc "hoist", "Deploy an application using the configuration from config/manifest.yml to next"
|
345
|
+
method_option :major, type: :boolean, aliases: "-ma", desc: "Increment major version"
|
346
|
+
method_option :msg, type: :boolean, aliases: "-msg", desc: "set the commit message"
|
347
|
+
method_option :minor, type: :boolean, aliases: "-mi", desc: "Increment minor version"
|
348
|
+
method_option :feature, type: :boolean, aliases: "-fea", desc: "Increment minor version"
|
349
|
+
method_option :fix, type: :boolean, aliases: "-f", desc: "Increment minor version"
|
350
|
+
method_option :release, type: :boolean, aliases: "-rel", desc: "Increment minor version"
|
351
|
+
method_option :patch, type: :boolean, aliases: "-pa", desc: "Increment minor version"
|
352
|
+
def hoist(name = nil)
|
353
|
+
with_error_handling do
|
354
|
+
config = load_configuration
|
258
355
|
|
259
|
-
|
356
|
+
msg =nil
|
357
|
+
if options[:msg]
|
358
|
+
msg = ask("commit massage: ")
|
359
|
+
end
|
260
360
|
|
361
|
+
focus = nil
|
261
362
|
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
363
|
+
focus = if options[:major] || options[:release]
|
364
|
+
"major"
|
365
|
+
elsif options[:minor] || options[:feature]
|
366
|
+
"minor"
|
367
|
+
elsif options[:patch] || options[:fix]
|
368
|
+
"patch"
|
369
|
+
else
|
370
|
+
"patch"
|
371
|
+
end
|
266
372
|
|
267
|
-
|
268
|
-
raise "Local manifest file not found at #{local_manifest_path}" unless File.exist?(local_manifest_path)
|
373
|
+
version = increment_version(config["version"], focus.to_sym)
|
269
374
|
|
270
|
-
|
271
|
-
|
272
|
-
|
375
|
+
modify_manifest do |config|
|
376
|
+
config["version"] = version
|
377
|
+
end
|
273
378
|
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
379
|
+
progressing("Hoist") do
|
380
|
+
name = config["name"]
|
381
|
+
gem = "#{name}-#{version}.gem"
|
382
|
+
assemble "next", version
|
383
|
+
`lxc file push -rp build/#{gem} #{name}/var/gems/`
|
384
|
+
`lxc exec #{name} -- /root/.rbenv/shims/gem install /var/gems/#{gem} --no-document`
|
385
|
+
`lxc exec #{name} -- /root/.rbenv/shims/gem install /var/gems/#{gem} --no-document`
|
386
|
+
`lxc exec #{name} -- sv restart next`
|
387
|
+
`lxc exec #{name} -- sv restart next.ws`
|
282
388
|
|
389
|
+
modify_manifest do |config|
|
390
|
+
config["next"] = version
|
391
|
+
end
|
283
392
|
|
284
|
-
|
285
|
-
`ssh #{user}@#{host} 'mkdir -p #{versions_directory}'`
|
286
|
-
`ssh #{user}@#{host} 'mkdir -p #{data_directory}'`
|
393
|
+
clean_up(name)
|
287
394
|
|
288
|
-
|
289
|
-
|
395
|
+
change = "RELEASE #{version}"
|
396
|
+
commit("#{change}\n\n#{msg}\n\n Hoisted #{name} version #{version}")
|
290
397
|
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
else
|
295
|
-
puts "Failed to deploy application version #{version} to #{host}"
|
398
|
+
ok("https://next.#{config['host']}/ok",grace: 25) do
|
399
|
+
notify_terminal(" #{name} version #{version} is up on next!", "Lbhhr")
|
400
|
+
end
|
296
401
|
end
|
297
|
-
|
298
|
-
else
|
299
|
-
puts "no manifest found!"
|
300
402
|
end
|
403
|
+
end
|
404
|
+
|
405
|
+
desc "deploy", "Deploy an application using the configuration from config/manifest.yml to live"
|
406
|
+
def deploy(name = nil)
|
407
|
+
with_error_handling do
|
408
|
+
progressing("Deploy") do
|
409
|
+
config = load_configuration
|
410
|
+
name = name.nil? ? config["name"] : name
|
411
|
+
if config["next"].nil?
|
412
|
+
puts "No deploymnt available"
|
413
|
+
else
|
414
|
+
`lxc exec #{name} -- bash -c 'if [ -d /var/www/app/container/rollback ]; then rm -rf /var/www/app/container/rollback; fi'`
|
415
|
+
`lxc exec #{name} -- mv /var/www/app/container/live /var/www/app/container/rollback`
|
416
|
+
`lxc exec #{name} -- cp -r /var/www/app/container/next /var/www/app/container/live`
|
417
|
+
`lxc exec #{name} -- sv restart live`
|
418
|
+
`lxc exec #{name} -- sv restart ws`
|
419
|
+
modify_manifest do |config|
|
420
|
+
config["rollback"] = config["live"]
|
421
|
+
config["live"] = config["next"]
|
422
|
+
config["rolledback"] = false
|
423
|
+
end
|
424
|
+
end
|
425
|
+
commit("Deployed #{name} version #{config["live"]} to live")
|
426
|
+
|
427
|
+
ok("https://#{config['host']}/ok",grace: 15) do
|
428
|
+
notify_terminal(" #{name} version #{version} is up on live!", "Lbhhr")
|
429
|
+
end
|
301
430
|
|
431
|
+
end
|
432
|
+
end
|
302
433
|
end
|
303
434
|
|
304
|
-
desc "
|
305
|
-
|
306
|
-
method_option :next, type: :boolean, default: true, aliases: "-n", desc: "Process in next mode"
|
307
|
-
def logs(name=nil)
|
435
|
+
desc "assemble", "Build an application using the configuration from config/manifest.yml into a ruby gem"
|
436
|
+
def assemble(env = "next", version = nil)
|
308
437
|
config = load_configuration
|
309
|
-
|
310
|
-
|
438
|
+
name = config["name"]
|
439
|
+
image = config["image"]
|
440
|
+
|
441
|
+
containerize
|
311
442
|
|
312
|
-
if
|
313
|
-
|
314
|
-
|
315
|
-
|
443
|
+
# Check if we're in the root directory
|
444
|
+
if manifest?
|
445
|
+
# Create the build directory if it doesn't exist
|
446
|
+
if Dir.exist?("build")
|
447
|
+
FileUtils.rm_r("build")
|
316
448
|
end
|
317
449
|
|
318
|
-
|
450
|
+
FileUtils.mkdir_p("build/src")
|
319
451
|
|
320
|
-
|
321
|
-
|
322
|
-
|
452
|
+
# Copy all files and folders to the build directory
|
453
|
+
Dir.glob("*").each do |item|
|
454
|
+
next if item == "build" # Skip the build directory itself
|
455
|
+
next if item == ".git" # Skip the .git directory
|
456
|
+
next if item == "tmp" # Skip the config directory
|
323
457
|
|
324
|
-
|
325
|
-
|
326
|
-
else
|
327
|
-
exec "ssh #{user}@#{host} 'harbr peek #{container_name} --next'"
|
328
|
-
end
|
329
|
-
end
|
458
|
+
FileUtils.cp_r(item, "build/src/#{item}")
|
459
|
+
end
|
330
460
|
|
461
|
+
# Parameters for gemspec
|
462
|
+
gem_name = config["name"]
|
463
|
+
gem_version = version.nil? ? config["version"] : version
|
331
464
|
|
332
|
-
|
333
|
-
|
334
|
-
container_name = File.basename(Dir.pwd)
|
335
|
-
config = load_configuration
|
336
|
-
host = config["host"]
|
337
|
-
user = config["user"]
|
338
|
-
exec "ssh #{user}@#{host} 'harbr logs'"
|
339
|
-
end
|
465
|
+
# Ensure the build directory exists
|
466
|
+
FileUtils.mkdir_p("build/lib")
|
340
467
|
|
468
|
+
# Define the template files and their target locations
|
469
|
+
template_dir = File.expand_path(File.join(File.dirname(__FILE__), "../", "templates"))
|
341
470
|
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
471
|
+
templates = {
|
472
|
+
"#{template_dir}/lib/panamax.rb.erb" => "build/lib/#{gem_name}.rb",
|
473
|
+
"#{template_dir}/lib/rubygems_plugin.rb.erb" => "build/lib/rubygems_plugin.rb",
|
474
|
+
"#{template_dir}/panamax.gemspec.erb" => "build/#{gem_name}.gemspec"
|
475
|
+
}
|
347
476
|
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
return
|
477
|
+
# Process each template
|
478
|
+
templates.each do |template, target|
|
479
|
+
process_template(template, target, binding)
|
352
480
|
end
|
353
|
-
name = config["name"]
|
354
|
-
end
|
355
|
-
puts `ssh #{user}@#{host} 'harbr deploy #{name}'`
|
356
|
-
end
|
357
481
|
|
358
|
-
|
359
|
-
|
482
|
+
`cd build && gem build #{gem_name}.gemspec`
|
483
|
+
notify_terminal("Assembled #{name}", "Lbhhr")
|
484
|
+
else
|
485
|
+
puts "config/manifest file not found. Please ensure you are in the root directory of your project."
|
486
|
+
end
|
487
|
+
end
|
360
488
|
|
361
|
-
config = load_configuration
|
362
|
-
host = config["host"]
|
363
|
-
user = config["user"]
|
364
489
|
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
end
|
370
|
-
name = config["name"]
|
490
|
+
desc "version", "Display the version of Lbhrr"
|
491
|
+
def version
|
492
|
+
with_error_handling do
|
493
|
+
puts "lbhrr version #{Lbhrr::VERSION}"
|
371
494
|
end
|
372
|
-
|
373
|
-
end
|
374
|
-
|
495
|
+
end
|
375
496
|
|
376
|
-
|
377
|
-
|
497
|
+
desc "update", "Display the version of Lbhrr"
|
498
|
+
def update
|
499
|
+
with_error_handling do
|
500
|
+
`gem update lbhrr --conservative`
|
501
|
+
end
|
378
502
|
end
|
503
|
+
|
379
504
|
end
|
380
505
|
|
381
506
|
LbhrrCLI.start(ARGV)
|
@@ -0,0 +1 @@
|
|
1
|
+
d2914e65-5f28-492f-9615-4f00fb29e437
|
@@ -0,0 +1,5 @@
|
|
1
|
+
L9l8YThIoCo83pL/5hZ5mrNTzRRCdUBuxXFYZxe5ZUSC0yeKn3tq11znnEaWXrWFiqaV62V8xhpHWBJo1B9gLA==
|
2
|
+
5cmFh3rph/f/5dJr8MK8do6VyW44B5naEQg8iTHMaE1eXbLaS5lrZ9Co+VuybfQPkocGkPeYT4b55Ii7jzvDtw==
|
3
|
+
vk/l4x1F9rcoJXdZoF3XIod68atgQZ9LeS3VRkZOmgQkA77FhqtZqXjPEo9/dVlz7CiS1P50jhg1SkdeFO5e5A==
|
4
|
+
S7phDwdvAtXd4h6sjr/W+9uhGakSwObf3kAdyA30wQeajXY2d1oAygDXtr6bMEv5F5WfgbD0nz4vlPyO+e4Tuw==
|
5
|
+
XanoLNMHjZM9LirLNYxnmFRZNDcWB7FqP1/MvE7Wxwa362mQi3wTwsvFsIE6c3yOv7WcokzgSMlmseD/BBX/Yg==
|
data/lib/lbhrr/version.rb
CHANGED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'prettyprint'
|
2
|
+
|
3
|
+
Gem.pre_install do |installer|
|
4
|
+
if installer.spec.metadata.dig("container") == "panamax"
|
5
|
+
env = installer.spec.metadata.dig("env")
|
6
|
+
destination = File.join(installer.spec.metadata.dig("destination"), env)
|
7
|
+
src = File.expand_path(File.join(File.dirname(__FILE__), '..', 'src'))
|
8
|
+
system("rm -rf #{destination}")
|
9
|
+
puts "deploying #{installer.spec.name} to #{destination}"
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
Gem.post_install do |installer|
|
15
|
+
if installer.spec.metadata.dig("container") == "panamax"
|
16
|
+
env = installer.spec.metadata.dig("env")
|
17
|
+
destination = File.join(installer.spec.metadata.dig("destination"), env)
|
18
|
+
src = File.expand_path(File.join(File.dirname(__FILE__), '..', 'src'))
|
19
|
+
|
20
|
+
|
21
|
+
if env == "live"
|
22
|
+
puts "symlink files to #{destination}"
|
23
|
+
system("ln -sf #{src} #{destination}")
|
24
|
+
else
|
25
|
+
puts "copy files #{destination}"
|
26
|
+
system("cp -rf #{src} #{destination}")
|
27
|
+
puts "copy uploads"
|
28
|
+
live = File.join(installer.spec.metadata.dig("destination"), "live")
|
29
|
+
system("cp -rf #{live}/public/uploads/ #{destination}/public/uploads/")
|
30
|
+
puts "uploads synced"
|
31
|
+
end
|
32
|
+
|
33
|
+
if File.exist?("#{destination}/bin/hoisted")
|
34
|
+
system("chmod +x #{destination}/bin/hoisted")
|
35
|
+
system("cd #{destination} && ./bin/hoisted")
|
36
|
+
end
|
37
|
+
|
38
|
+
puts "deployed #{installer.spec.name} to #{destination}"
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
require_relative 'lib/<%= gem_name%>'
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = '<%= gem_name %>'
|
6
|
+
s.version = '<%= gem_version %>'
|
7
|
+
s.authors = ["Delaney Burke"]
|
8
|
+
s.email = "delaney@zero2one.ee"
|
9
|
+
s.homepage = "http://zero2one.ee/gems/<%= gem_name%>"
|
10
|
+
s.summary = "<%= gem_name %> container desscripton"
|
11
|
+
s.description = "<%= gem_name %> container"
|
12
|
+
s.required_rubygems_version = ">= 1.3.6"
|
13
|
+
s.files = Dir['lib/**/*', 'src/**/*'].reject { |f| File.directory?(f) }
|
14
|
+
# s.add_dependency 'some-gem'
|
15
|
+
# s.extra_rdoc_files = ['README.md', 'LICENSE']
|
16
|
+
s.license = 'MIT'
|
17
|
+
s.metadata = {
|
18
|
+
"container" => "panamax",
|
19
|
+
"env" => <%= gem_name.capitalize %>::ENV,
|
20
|
+
"destination" => <%= gem_name.capitalize %>::DESTINATION
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lbhrr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.33.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Delaney Kuldvee Burke
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-03-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: net-ssh
|
@@ -34,9 +34,10 @@ executables:
|
|
34
34
|
extensions: []
|
35
35
|
extra_rdoc_files: []
|
36
36
|
files:
|
37
|
+
- ".DS_Store"
|
37
38
|
- ".gitignore"
|
38
|
-
- ".gitlab-ci.yml"
|
39
39
|
- ".rspec"
|
40
|
+
- ".ruby-version"
|
40
41
|
- ".standard.yml"
|
41
42
|
- CHANGELOG.md
|
42
43
|
- CODE_OF_CONDUCT.md
|
@@ -47,13 +48,18 @@ files:
|
|
47
48
|
- Rakefile
|
48
49
|
- bin/console
|
49
50
|
- bin/setup
|
50
|
-
-
|
51
|
+
- crane.png
|
51
52
|
- exe/lbhrr
|
52
53
|
- hero.png
|
53
54
|
- lbhrr.gemspec
|
55
|
+
- lib/.kafkr/acknowledged_messages.txt
|
56
|
+
- lib/.kafkr/message_queue.txt
|
54
57
|
- lib/lbhrr.rb
|
55
58
|
- lib/lbhrr/version.rb
|
56
59
|
- sig/lbhrr.rbs
|
60
|
+
- templates/lib/panamax.rb.erb
|
61
|
+
- templates/lib/rubygems_plugin.rb.erb
|
62
|
+
- templates/panamax.gemspec.erb
|
57
63
|
homepage: https://github.com/dekubu/lbhrr
|
58
64
|
licenses:
|
59
65
|
- MIT
|
@@ -76,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
76
82
|
- !ruby/object:Gem::Version
|
77
83
|
version: '0'
|
78
84
|
requirements: []
|
79
|
-
rubygems_version: 3.5.
|
85
|
+
rubygems_version: 3.5.5
|
80
86
|
signing_key:
|
81
87
|
specification_version: 4
|
82
88
|
summary: A CLI tool for deploying and managing Rack applications.
|
data/.gitlab-ci.yml
DELETED