lbhrr 1.1.1 → 2.33.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 +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