mimas 0.2.2 → 0.3.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/lib/mimas/archiver.rb +6 -10
- data/lib/mimas/cli.rb +1 -0
- data/lib/mimas/commands/archive.rb +19 -0
- data/lib/mimas/commands/console.rb +1 -1
- data/lib/mimas/config.rb +13 -0
- data/lib/mimas/deployment/paths.rb +1 -1
- data/lib/mimas/deployment/ruby_app.rb +74 -46
- data/lib/mimas/deployment/static_site.rb +1 -1
- data/lib/mimas/deployment.rb +1 -1
- data/lib/mimas/scripts/create_deploy_user.sh +3 -1
- data/lib/mimas/scripts/harden.sh +3 -1
- data/lib/mimas/server.rb +10 -0
- data/lib/mimas/site/archive.rb +13 -0
- data/lib/mimas/site.rb +35 -0
- data/lib/mimas/version.rb +1 -1
- data/lib/mimas.rb +2 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ea7a87706ea7f9976b782cb891e446b813c7c866e2a4907f451565e670d194a5
|
|
4
|
+
data.tar.gz: adde800fcc3df657cc512cfd14b9fe1ef314e3d4f19f903c68259c3d7394ef28
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 984c764fc02feeb671c63f33528258abb8ad271811400d27affe7e220fd4eb6d66652b57a3b829fa1bf972aa23a6a2d5fbb42fe6bc7ec290cf1c1155fc352654
|
|
7
|
+
data.tar.gz: 939fa01df07457e75ecb9b2929757edfa0045cb109ec7f7b33366566397af491aca94df1f4a00125f99bd119ab05fc8cc4b318f3cb6c21e0bdabbc03a1853619
|
data/lib/mimas/archiver.rb
CHANGED
|
@@ -2,18 +2,12 @@ require 'zlib'
|
|
|
2
2
|
require 'rubygems/package'
|
|
3
3
|
|
|
4
4
|
module Mimas
|
|
5
|
-
module Archive
|
|
6
|
-
def archive(root: Dir.pwd, output:, archive_root: "", glob: nil, files: [])
|
|
7
|
-
Archiver
|
|
8
|
-
.new(root: root, output: output, archive_root: archive_root, glob: glob, files: files)
|
|
9
|
-
.package
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
|
|
13
5
|
class Archiver
|
|
14
|
-
|
|
6
|
+
DEFAULT_OUTPUT_PATH = Pathname.new(Dir.pwd).join("tmp")
|
|
7
|
+
|
|
8
|
+
def initialize(root:, output_path: DEFAULT_OUTPUT_PATH, output_file:, archive_root: nil, glob: nil, files: [])
|
|
15
9
|
@root = root || Dir.pwd
|
|
16
|
-
@output =
|
|
10
|
+
@output = Pathname.new(output_path).join(output_file)
|
|
17
11
|
@archive_root = archive_root || ""
|
|
18
12
|
@glob = glob
|
|
19
13
|
@source_files = files
|
|
@@ -27,6 +21,8 @@ module Mimas
|
|
|
27
21
|
|
|
28
22
|
tar.close
|
|
29
23
|
gz.close
|
|
24
|
+
|
|
25
|
+
return @output.to_s
|
|
30
26
|
end
|
|
31
27
|
|
|
32
28
|
private
|
data/lib/mimas/cli.rb
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Mimas
|
|
2
|
+
module CLI
|
|
3
|
+
module Commands
|
|
4
|
+
class Archive < BaseCommand
|
|
5
|
+
desc "Create your site's archive which will be uploaded to the server"
|
|
6
|
+
|
|
7
|
+
argument :site, desc: "The name of the site to archive"
|
|
8
|
+
|
|
9
|
+
def call(site: :default)
|
|
10
|
+
site = Config.current.sites[site.to_sym]
|
|
11
|
+
|
|
12
|
+
site.archive
|
|
13
|
+
|
|
14
|
+
say "Your site's archive has been created in #{Archiver::DEFAULT_OUTPUT_PATH}"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -7,7 +7,7 @@ module Mimas
|
|
|
7
7
|
argument :server_name, required: true, desc: "The name of the server to run the console on"
|
|
8
8
|
argument :site, desc: "The site to run the console for. Uses the default site if unspecified"
|
|
9
9
|
|
|
10
|
-
def call(server_name
|
|
10
|
+
def call(server_name:, site: :default)
|
|
11
11
|
server = Config.current.servers[server_name.to_sym]
|
|
12
12
|
site = Config.current.sites[site.to_sym]
|
|
13
13
|
|
data/lib/mimas/config.rb
CHANGED
|
@@ -37,6 +37,17 @@ module Mimas
|
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
+
class InvalidConfiguration < StandardError
|
|
41
|
+
attr_reader :message
|
|
42
|
+
def initialize(message)
|
|
43
|
+
@message = message
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def to_s
|
|
47
|
+
@message.to_s
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
40
51
|
private
|
|
41
52
|
|
|
42
53
|
class DSL
|
|
@@ -56,12 +67,14 @@ module Mimas
|
|
|
56
67
|
name = name.to_sym
|
|
57
68
|
args = Site.evaluate(&block)
|
|
58
69
|
@config.sites[name] = Mimas::Site.new(name, args)
|
|
70
|
+
@config.sites[name].validate!
|
|
59
71
|
end
|
|
60
72
|
|
|
61
73
|
def server(name, &block)
|
|
62
74
|
name = name.to_sym
|
|
63
75
|
args = Options.evaluate(&block)
|
|
64
76
|
@config.servers[name] = Mimas::Server.new(name, args)
|
|
77
|
+
@config.servers[name].validate!
|
|
65
78
|
end
|
|
66
79
|
|
|
67
80
|
def hooks(&block)
|
|
@@ -4,27 +4,14 @@ module Mimas
|
|
|
4
4
|
def deploy_ruby_app
|
|
5
5
|
say "Starting deployment for #{site.domain}"
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
@archive_path = site.archive(filename: archive_name)
|
|
8
8
|
|
|
9
9
|
ssh(server) do |session|
|
|
10
|
-
|
|
11
|
-
session.run "test -d ~/.rubies/ruby-#{ruby_version}"
|
|
12
|
-
say "Ruby #{ruby_version} found on the server..."
|
|
13
|
-
rescue SSH::Session::NonZeroExitCode
|
|
14
|
-
raise "Ruby version not installed on server"
|
|
15
|
-
end
|
|
10
|
+
validate_server_ruby_version(session)
|
|
16
11
|
|
|
17
|
-
|
|
18
|
-
session.run "mkdir -p #{releases_path}"
|
|
12
|
+
create_directory_skeleton(session)
|
|
19
13
|
|
|
20
|
-
|
|
21
|
-
releases = session.run "ls #{releases_path}", capture: true
|
|
22
|
-
expired_releases = releases.split("\n").sort.reverse.drop(5)
|
|
23
|
-
|
|
24
|
-
if expired_releases.any?
|
|
25
|
-
say "Deleting versions: #{expired_releases.join(", ")}"
|
|
26
|
-
session.run "cd #{releases_path} && rm -rf #{expired_releases.join(" ")}"
|
|
27
|
-
end
|
|
14
|
+
expire_old_releases(session)
|
|
28
15
|
|
|
29
16
|
# Check `current` symlink to get currently live version
|
|
30
17
|
remote_current_path = session.run("readlink #{current_path}", capture: true, silent: true).chomp
|
|
@@ -32,12 +19,9 @@ module Mimas
|
|
|
32
19
|
|
|
33
20
|
say "Current live version is #{remote_current_version}" if remote_current_version.size > 0
|
|
34
21
|
|
|
35
|
-
# Make systemd path and the site's mimas folder
|
|
36
|
-
session.run "mkdir -p #{server.user_systemd_path}"
|
|
37
|
-
session.run "mkdir -p #{mimas_path}"
|
|
38
|
-
|
|
39
22
|
refreshing_caddy(session) do
|
|
40
23
|
# Upload the mimas.env and touch an `.env` file in the site's root
|
|
24
|
+
session.run "cp #{mimas_path.join("mimas.env")} #{mimas_path.join("mimas.env.backup")}"
|
|
41
25
|
session.upload StringIO.new(mimas_env), mimas_path.join("mimas.env")
|
|
42
26
|
session.run "touch #{site_root.join(".env")}"
|
|
43
27
|
|
|
@@ -78,30 +62,40 @@ module Mimas
|
|
|
78
62
|
rescue Exception => e
|
|
79
63
|
say "Error raised during deploy: #{e}".red.bold
|
|
80
64
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
session.run "ln -sfn #{remote_current_path} #{current_path}"
|
|
85
|
-
else
|
|
86
|
-
say "Deleting symlink ..."
|
|
87
|
-
session.run "rm -f #{current_path}"
|
|
88
|
-
end
|
|
65
|
+
revert_files_after_failed_deployment(session, remote_current_path: remote_current_path)
|
|
66
|
+
exit 1
|
|
67
|
+
end
|
|
89
68
|
|
|
90
|
-
say "Deleting released files ..."
|
|
91
69
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
end
|
|
70
|
+
cleanup_successful_deployment(session, remote_current_version: remote_current_version)
|
|
71
|
+
say "\n"
|
|
72
|
+
say "Deployment complete! #{version} is now live.".bold.white
|
|
73
|
+
end
|
|
74
|
+
end
|
|
98
75
|
|
|
99
|
-
|
|
100
|
-
session.run "rm -f #{site_root.join("Caddyfile.new")}"
|
|
101
|
-
session.run "rm -rf #{remote_destination}"
|
|
76
|
+
private
|
|
102
77
|
|
|
103
|
-
|
|
104
|
-
|
|
78
|
+
def validate_server_ruby_version(session)
|
|
79
|
+
session.run "test -d ~/.rubies/ruby-#{ruby_version}"
|
|
80
|
+
say "Ruby #{ruby_version} found on the server..."
|
|
81
|
+
rescue SSH::Session::NonZeroExitCode
|
|
82
|
+
raise "Ruby version not installed on server"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def create_directory_skeleton(session)
|
|
86
|
+
# Create the release folder
|
|
87
|
+
session.run "mkdir -p #{releases_path}"
|
|
88
|
+
|
|
89
|
+
# Make systemd path and the site's mimas folder
|
|
90
|
+
session.run "mkdir -p #{server.user_systemd_path}"
|
|
91
|
+
session.run "mkdir -p #{mimas_path}"
|
|
92
|
+
|
|
93
|
+
# Create empty .env file
|
|
94
|
+
session.run "touch #{mimas_path.join("mimas.env")}"
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def cleanup_successful_deployment(session, remote_current_version:)
|
|
98
|
+
session.run "rm -f #{mimas_path.join("mimas.env.backup")}"
|
|
105
99
|
|
|
106
100
|
# Delete the old service if one exists, and the new service started up
|
|
107
101
|
if remote_current_version.size > 0
|
|
@@ -109,18 +103,52 @@ module Mimas
|
|
|
109
103
|
systemd_service_name = systemd_service_name(service, version: remote_current_version)
|
|
110
104
|
|
|
111
105
|
say "Stopping old service: #{systemd_service_name}"
|
|
112
|
-
session.run "systemctl --user stop #{systemd_service_name}"
|
|
113
|
-
session.run "systemctl --user disable #{systemd_service_name}"
|
|
106
|
+
session.run "systemctl --user stop #{systemd_service_name}", capture: true, silent: true
|
|
107
|
+
session.run "systemctl --user disable #{systemd_service_name}", capture: true, silent: true
|
|
114
108
|
session.run "rm #{server.user_systemd_path.join("#{systemd_service_name}.service")}"
|
|
115
109
|
say "#{systemd_service_name} stopped and deleted."
|
|
116
110
|
session.run "rm -f #{unix_socket(version: remote_current_version)}"
|
|
117
111
|
end
|
|
118
112
|
end
|
|
113
|
+
end
|
|
119
114
|
|
|
120
|
-
|
|
121
|
-
|
|
115
|
+
def revert_files_after_failed_deployment(session, remote_current_path:)
|
|
116
|
+
# Revert symlink if there's an existing live release, otherwise delete it
|
|
117
|
+
if remote_current_path.size > 0
|
|
118
|
+
say "Reverting symlink ..."
|
|
119
|
+
session.run "ln -sfn #{remote_current_path} #{current_path}"
|
|
120
|
+
else
|
|
121
|
+
say "Deleting symlink ..."
|
|
122
|
+
session.run "rm -f #{current_path}"
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Restore the previous mimas environment
|
|
126
|
+
session.run "mv #{mimas_path.join("mimas.env.backup")} #{mimas_path.join("mimas.env")}"
|
|
127
|
+
|
|
128
|
+
say "Deleting released files ..."
|
|
129
|
+
|
|
130
|
+
site.services.each do |_, service|
|
|
131
|
+
systemd_service_name = systemd_service_name(service)
|
|
132
|
+
session.run "systemctl --user stop #{systemd_service_name}", capture: true, silent: true
|
|
133
|
+
session.run "systemctl --user disable #{systemd_service_name}", capture: true, silent: true
|
|
134
|
+
session.run "rm #{server.user_systemd_path.join("#{systemd_service_name}.service")}", silent: true
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
session.run "rm -f #{unix_socket(version: version)}"
|
|
138
|
+
session.run "rm -f #{site_root.join("Caddyfile.new")}"
|
|
139
|
+
session.run "rm -rf #{remote_destination}"
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def expire_old_releases(session)
|
|
143
|
+
# Get expired releases. Mimas will only retain the last 5 releases.
|
|
144
|
+
releases = session.run "ls #{releases_path}", capture: true
|
|
145
|
+
expired_releases = releases.split("\n").sort.reverse.drop(5)
|
|
146
|
+
|
|
147
|
+
if expired_releases.any?
|
|
148
|
+
say "Deleting versions: #{expired_releases.join(", ")}"
|
|
149
|
+
session.run "cd #{releases_path} && rm -rf #{expired_releases.join(" ")}"
|
|
150
|
+
end
|
|
122
151
|
end
|
|
123
|
-
end
|
|
124
152
|
end
|
|
125
153
|
end
|
|
126
154
|
end
|
|
@@ -4,7 +4,7 @@ module Mimas
|
|
|
4
4
|
def deploy_static_site
|
|
5
5
|
say "Starting deployment for #{site.domain}"
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
@archive_path = site.archive(filename: archive_name)
|
|
8
8
|
|
|
9
9
|
ssh(server) do |session|
|
|
10
10
|
refreshing_caddy(session) do
|
data/lib/mimas/deployment.rb
CHANGED
|
@@ -7,7 +7,9 @@ DEPLOY_USER="${DEPLOY_USER:-deploy}"
|
|
|
7
7
|
|
|
8
8
|
if ! id $DEPLOY_USER >/dev/null 2>&1; then
|
|
9
9
|
printf "Creating the $DEPLOY_USER user\n\n"
|
|
10
|
-
|
|
10
|
+
getent group $DEPLOY_USER >/dev/null || groupadd $DEPLOY_USER
|
|
11
|
+
useradd $DEPLOY_USER -g $DEPLOY_USER -s /bin/bash -m
|
|
12
|
+
|
|
11
13
|
printf "$DEPLOY_USER user created\n\n"
|
|
12
14
|
else
|
|
13
15
|
printf "$DEPLOY_USER user exists. Configuring the user..."
|
data/lib/mimas/scripts/harden.sh
CHANGED
|
@@ -18,8 +18,10 @@ printf "UFW enabled\n\n"
|
|
|
18
18
|
printf "Creating the admin user\n\n"
|
|
19
19
|
|
|
20
20
|
if ! id admin >/dev/null 2>&1; then
|
|
21
|
+
# Create an admin group
|
|
22
|
+
getent group admin >/dev/null || groupadd admin
|
|
21
23
|
# Add a new user, set the default shell, and create a home directory
|
|
22
|
-
useradd admin -s /bin/bash -m
|
|
24
|
+
useradd admin -g admin -s /bin/bash -m
|
|
23
25
|
fi
|
|
24
26
|
|
|
25
27
|
# Disable password login
|
data/lib/mimas/server.rb
CHANGED
|
@@ -33,5 +33,15 @@ module Mimas
|
|
|
33
33
|
def current_path(site)
|
|
34
34
|
site_root(site).join("current")
|
|
35
35
|
end
|
|
36
|
+
|
|
37
|
+
def validate!
|
|
38
|
+
raise Config::InvalidConfiguration.new("`server` requires a `host`") \
|
|
39
|
+
unless self.host && self.host.size > 0
|
|
40
|
+
|
|
41
|
+
raise Config::InvalidConfiguration.new("`server` requires a `user`") \
|
|
42
|
+
unless self.user && self.user.size > 0
|
|
43
|
+
|
|
44
|
+
true
|
|
45
|
+
end
|
|
36
46
|
end
|
|
37
47
|
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Mimas
|
|
2
|
+
class Site
|
|
3
|
+
module Archive
|
|
4
|
+
def archive(filename: "#{name}.tar.gz")
|
|
5
|
+
if self.ruby_app?
|
|
6
|
+
Archiver.new(output_file: filename, files: files).package
|
|
7
|
+
else
|
|
8
|
+
Archiver.new(root: root_dir, output_file: filename, archive_root: "root", glob: glob, files: files).package
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
data/lib/mimas/site.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
module Mimas
|
|
2
2
|
class Site
|
|
3
|
+
include Archive
|
|
4
|
+
|
|
3
5
|
attr_reader :name
|
|
4
6
|
def initialize(name, args)
|
|
5
7
|
@name = name
|
|
@@ -20,5 +22,38 @@ module Mimas
|
|
|
20
22
|
def ruby_app?
|
|
21
23
|
services.any?
|
|
22
24
|
end
|
|
25
|
+
|
|
26
|
+
# Placeholder, will be overwritten by the config file if defined
|
|
27
|
+
def glob
|
|
28
|
+
nil
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Placeholder, will be overwritten by the config file if defined
|
|
32
|
+
def files
|
|
33
|
+
nil
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def validate!
|
|
37
|
+
raise Config::InvalidConfiguration.new("`site` requires a `domain`") \
|
|
38
|
+
unless self.respond_to?(:domain)
|
|
39
|
+
|
|
40
|
+
if ruby_app?
|
|
41
|
+
raise Config::InvalidConfiguration.new("`site` requires a `files` directive") \
|
|
42
|
+
unless self.files != nil
|
|
43
|
+
|
|
44
|
+
services.values.each do |service|
|
|
45
|
+
raise Config::InvalidConfiguration.new("#{service[:name]} service requires a `command` directive") \
|
|
46
|
+
unless service[:command]
|
|
47
|
+
end
|
|
48
|
+
else
|
|
49
|
+
raise Config::InvalidConfiguration.new("`site` requires a `root_dir` directive") \
|
|
50
|
+
unless self.respond_to?(:root_dir)
|
|
51
|
+
|
|
52
|
+
raise Config::InvalidConfiguration.new("`site` requires a `files` or `glob` directive") \
|
|
53
|
+
unless self.glob != nil || self.files != nil
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
true
|
|
57
|
+
end
|
|
23
58
|
end
|
|
24
59
|
end
|
data/lib/mimas/version.rb
CHANGED
data/lib/mimas.rb
CHANGED
|
@@ -16,6 +16,7 @@ require_relative "mimas/hooks"
|
|
|
16
16
|
|
|
17
17
|
require_relative "mimas/config"
|
|
18
18
|
|
|
19
|
+
require_relative "mimas/site/archive"
|
|
19
20
|
require_relative "mimas/site"
|
|
20
21
|
|
|
21
22
|
require_relative "mimas/server/prerequisites"
|
|
@@ -35,6 +36,7 @@ require_relative "mimas/deployment"
|
|
|
35
36
|
require_relative "mimas/plugins"
|
|
36
37
|
|
|
37
38
|
require_relative "mimas/base_command"
|
|
39
|
+
require_relative "mimas/commands/archive"
|
|
38
40
|
require_relative "mimas/commands/console"
|
|
39
41
|
require_relative "mimas/commands/init"
|
|
40
42
|
require_relative "mimas/commands/install"
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mimas
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ayush Newatia
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-07-
|
|
10
|
+
date: 2026-07-30 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: dry-cli
|
|
@@ -104,6 +104,7 @@ files:
|
|
|
104
104
|
- lib/mimas/archiver.rb
|
|
105
105
|
- lib/mimas/base_command.rb
|
|
106
106
|
- lib/mimas/cli.rb
|
|
107
|
+
- lib/mimas/commands/archive.rb
|
|
107
108
|
- lib/mimas/commands/console.rb
|
|
108
109
|
- lib/mimas/commands/init.rb
|
|
109
110
|
- lib/mimas/commands/install.rb
|
|
@@ -135,6 +136,7 @@ files:
|
|
|
135
136
|
- lib/mimas/server/prerequisites.rb
|
|
136
137
|
- lib/mimas/server/ruby.rb
|
|
137
138
|
- lib/mimas/site.rb
|
|
139
|
+
- lib/mimas/site/archive.rb
|
|
138
140
|
- lib/mimas/ssh.rb
|
|
139
141
|
- lib/mimas/template.rb
|
|
140
142
|
- lib/mimas/templates/Caddyfile.ruby.erb
|