smartmachine 1.2.1 → 1.2.3
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/README.md +5 -0
- data/lib/smart_machine/apps/container.rb +2 -1
- data/lib/smart_machine/buildpackers/buildpacker.rb +1 -43
- data/lib/smart_machine/buildpackers/rails.rb +60 -0
- data/lib/smart_machine/machine.rb +95 -40
- data/lib/smart_machine/syncer.rb +3 -1
- data/lib/smart_machine/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 399cf5ca8bd944f129d3731d93be76cf46ba86e3f25b97b5110ee42dc8650430
|
4
|
+
data.tar.gz: 2b0166c466312def05a5ee8930bf3943c0f31e3a224d582caeee878c68e43a8d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e1f029f440a058a7185f315137f2e2544fb3898ef21d3bffb7792f50350d1b7d476c3c116d7ebec2790a2fb8f0c11cc1151558b6fc42db37edfdf55688bb8f4d
|
7
|
+
data.tar.gz: d667cfb03e650d7f9497a6be4b816b3c2eb0c70e85760987746fdd083d9f2bc3496b48ff1d65df667934e6065b8dfa5355e27c48820bc72cfb3e578506c4267e
|
data/README.md
CHANGED
@@ -65,6 +65,11 @@ Install the engine and buildpacker:
|
|
65
65
|
|
66
66
|
## Usage
|
67
67
|
|
68
|
+
### Setup your Network
|
69
|
+
|
70
|
+
$ smartmachine machine network up
|
71
|
+
$ smartmachine machine network down
|
72
|
+
|
68
73
|
### Choose Your Grids
|
69
74
|
|
70
75
|
Choose only the grids you need. You can start or stop a grid at anytime using <b>up</b> or <b>down</b> commands respectively.
|
@@ -33,10 +33,11 @@ module SmartMachine
|
|
33
33
|
"--volume='#{@home_dir}/smartmachine/apps/containers/#{@appname}/app/public/packs:/app/public/packs'",
|
34
34
|
"--volume='#{@home_dir}/smartmachine/apps/containers/#{@appname}/app/node_modules:/app/node_modules'",
|
35
35
|
"--volume='#{@home_dir}/smartmachine/apps/containers/#{@appname}/app/storage:/app/storage'",
|
36
|
+
(using_buildpacker ? "--cpus=1 --memory=512m --memory-swap=1024m" : nil),
|
36
37
|
"--restart='always'",
|
37
38
|
"--init",
|
38
39
|
# "--network='nginx-network'",
|
39
|
-
|
40
|
+
(using_buildpacker ? "smartmachine/buildpackers/rails:#{SmartMachine.version}" : @appimage)
|
40
41
|
]
|
41
42
|
command.push(using_command) if using_command.present?
|
42
43
|
|
@@ -80,13 +80,9 @@ module SmartMachine
|
|
80
80
|
libdb-dev \
|
81
81
|
uuid-dev && \
|
82
82
|
# ruby on rails
|
83
|
-
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
|
84
|
-
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
|
85
83
|
apt-get update && \
|
86
84
|
apt-get install -y --no-install-recommends \
|
87
85
|
tzdata \
|
88
|
-
nodejs \
|
89
|
-
yarn \
|
90
86
|
libmariadb-dev \
|
91
87
|
libvips42 \
|
92
88
|
ffmpeg \
|
@@ -95,7 +91,7 @@ module SmartMachine
|
|
95
91
|
poppler-utils && \
|
96
92
|
rm -rf /var/lib/apt/lists/* && \
|
97
93
|
# ImageMagick 7. Remove this after its dependency is gone from ruby on rails.
|
98
|
-
cd /opt && wget https://download.imagemagick.org/archive/ImageMagick-7.1.1-29.tar.gz && \
|
94
|
+
cd /opt && wget https://download.imagemagick.org/archive/releases/ImageMagick-7.1.1-29.tar.gz && \
|
99
95
|
tar xvzf ImageMagick-7.1.1-29.tar.gz && \
|
100
96
|
cd ImageMagick-7.1.1-29 && \
|
101
97
|
./configure && \
|
@@ -109,44 +105,6 @@ module SmartMachine
|
|
109
105
|
|
110
106
|
format(file)
|
111
107
|
end
|
112
|
-
|
113
|
-
# These swapfile methods can be used (after required modification), when you need to make swapfile for more memory.
|
114
|
-
# def self.create_swapfile
|
115
|
-
# # Creating swapfile for bundler to work properly
|
116
|
-
# unless system("sudo swapon -s | grep -ci '/swapfile'", out: File::NULL)
|
117
|
-
# print "-----> Creating swap swapfile ... "
|
118
|
-
# system("sudo install -o root -g root -m 0600 /dev/null /swapfile", out: File::NULL)
|
119
|
-
# system("sudo dd if=/dev/zero of=/swapfile bs=1k count=2048k", [:out, :err] => File::NULL)
|
120
|
-
# system("sudo mkswap /swapfile", out: File::NULL)
|
121
|
-
# system("sudo sh -c 'echo \"/swapfile none swap sw 0 0\" >> /etc/fstab'", out: File::NULL)
|
122
|
-
# system("echo 10 | sudo tee /proc/sys/vm/swappiness", out: File::NULL)
|
123
|
-
# system("sudo sed -i '/^vm.swappiness = /d' /etc/sysctl.conf", out: File::NULL)
|
124
|
-
# system("echo vm.swappiness = 10 | sudo tee -a /etc/sysctl.conf", out: File::NULL)
|
125
|
-
# puts "done"
|
126
|
-
#
|
127
|
-
# print "-----> Starting swap swapfile ... "
|
128
|
-
# if system("sudo swapon /swapfile", out: File::NULL)
|
129
|
-
# puts "done"
|
130
|
-
# end
|
131
|
-
# end
|
132
|
-
# end
|
133
|
-
#
|
134
|
-
# def self.destroy_swapfile
|
135
|
-
# if system("sudo swapon -s | grep -ci '/swapfile'", out: File::NULL)
|
136
|
-
# print "-----> Stopping swap swapfile ... "
|
137
|
-
# if system("sudo swapoff /swapfile", out: File::NULL)
|
138
|
-
# system("sudo sed -i '/^vm.swappiness = /d' /etc/sysctl.conf", out: File::NULL)
|
139
|
-
# system("echo 60 | sudo tee /proc/sys/vm/swappiness", out: File::NULL)
|
140
|
-
# puts "done"
|
141
|
-
#
|
142
|
-
# print "-----> Removing swap swapfile ... "
|
143
|
-
# system("sudo sed -i '/^\\/swapfile/d' /etc/fstab", out: File::NULL)
|
144
|
-
# if system("sudo rm /swapfile", out: File::NULL)
|
145
|
-
# puts "done"
|
146
|
-
# end
|
147
|
-
# end
|
148
|
-
# end
|
149
|
-
# end
|
150
108
|
end
|
151
109
|
end
|
152
110
|
end
|
@@ -173,6 +173,66 @@ module SmartMachine
|
|
173
173
|
system("alias bundler='bundler _#{bundler_version}_'")
|
174
174
|
logger.info "Using bundler v" + bundler_version + "\n"
|
175
175
|
|
176
|
+
# Install nodejs
|
177
|
+
nodejs_version = `sed -n '/node/{p;n}' package.json`.strip.split(":").last&.strip&.delete_prefix('"')&.delete_suffix(',')&.delete_suffix('"')
|
178
|
+
if nodejs_version.nil? || nodejs_version.empty?
|
179
|
+
logger.error "Could not find nodejs version. Have you specified it explicitly in package.json with engines field and run yarn install?\n"
|
180
|
+
return false
|
181
|
+
end
|
182
|
+
|
183
|
+
unless system(user_bash("node -v"), [:out, :err] => File::NULL) && `#{user_bash('node -v')}`.strip&.delete_prefix('v') == nodejs_version
|
184
|
+
logger.info "Installing nodejs v#{nodejs_version}\n"
|
185
|
+
|
186
|
+
Open3.popen2e(user_bash("asdf plugin add nodejs https://github.com/asdf-vm/asdf-nodejs.git")) do |stdin, stdout_and_stderr, wait_thr|
|
187
|
+
stdout_and_stderr.each { |line| logger.info "#{line}" }
|
188
|
+
end
|
189
|
+
Open3.popen2e(user_bash("asdf plugin update nodejs")) do |stdin, stdout_and_stderr, wait_thr|
|
190
|
+
stdout_and_stderr.each { |line| logger.info "#{line}" }
|
191
|
+
end
|
192
|
+
Open3.popen2e(user_bash("asdf install nodejs #{nodejs_version}")) do |stdin, stdout_and_stderr, wait_thr|
|
193
|
+
stdout_and_stderr.each { |line| logger.info "#{line}" }
|
194
|
+
end
|
195
|
+
Open3.popen2e(user_bash("asdf local nodejs #{nodejs_version}")) do |stdin, stdout_and_stderr, wait_thr|
|
196
|
+
stdout_and_stderr.each { |line| logger.info "#{line}" }
|
197
|
+
end
|
198
|
+
|
199
|
+
unless `#{user_bash('node -v')}`.strip&.delete_prefix('v') == nodejs_version
|
200
|
+
logger.error "Could not install nodejs with version #{nodejs_version}. Please try another valid version that asdf supports.\n"
|
201
|
+
return false
|
202
|
+
end
|
203
|
+
end
|
204
|
+
logger.info "Using nodejs v" + `#{user_bash('node -v')}`.strip&.delete_prefix('v') + "\n"
|
205
|
+
|
206
|
+
# Install yarn
|
207
|
+
yarn_version = `sed -n '/yarn/{p;n}' package.json`.strip.split(":").last&.strip&.delete_prefix('"')&.delete_suffix(',')&.delete_suffix('"')
|
208
|
+
if yarn_version.nil? || yarn_version.empty?
|
209
|
+
logger.error "Could not find yarn version. Have you specified it explicitly in package.json with engines field and run yarn install?\n"
|
210
|
+
return false
|
211
|
+
end
|
212
|
+
|
213
|
+
unless system(user_bash("yarn -v"), [:out, :err] => File::NULL) && `#{user_bash('yarn -v')}`.strip == yarn_version
|
214
|
+
logger.info "Installing yarn v#{yarn_version}\n"
|
215
|
+
|
216
|
+
Open3.popen2e(user_bash("asdf plugin add yarn https://github.com/twuni/asdf-yarn.git")) do |stdin, stdout_and_stderr, wait_thr|
|
217
|
+
stdout_and_stderr.each { |line| logger.info "#{line}" }
|
218
|
+
end
|
219
|
+
Open3.popen2e(user_bash("asdf plugin update yarn")) do |stdin, stdout_and_stderr, wait_thr|
|
220
|
+
stdout_and_stderr.each { |line| logger.info "#{line}" }
|
221
|
+
end
|
222
|
+
Open3.popen2e(user_bash("asdf install yarn #{yarn_version}")) do |stdin, stdout_and_stderr, wait_thr|
|
223
|
+
stdout_and_stderr.each { |line| logger.info "#{line}" }
|
224
|
+
end
|
225
|
+
Open3.popen2e(user_bash("asdf local yarn #{yarn_version}")) do |stdin, stdout_and_stderr, wait_thr|
|
226
|
+
stdout_and_stderr.each { |line| logger.info "#{line}" }
|
227
|
+
end
|
228
|
+
|
229
|
+
unless `#{user_bash('yarn -v')}`.strip == yarn_version
|
230
|
+
logger.error "Could not install yarn with version #{yarn_version}. Please try another valid version that asdf supports.\n"
|
231
|
+
return false
|
232
|
+
end
|
233
|
+
end
|
234
|
+
logger.info "Using yarn v" + `#{user_bash('yarn -v')}`.strip + "\n"
|
235
|
+
|
176
236
|
set_logger_formatter_arrow
|
177
237
|
|
178
238
|
return true
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# coding: utf-8
|
1
2
|
require "net/ssh"
|
2
3
|
|
3
4
|
module SmartMachine
|
@@ -60,36 +61,23 @@ module SmartMachine
|
|
60
61
|
def setup
|
61
62
|
getting_started
|
62
63
|
securing_your_server
|
64
|
+
setup_services
|
63
65
|
end
|
64
66
|
|
65
67
|
private
|
66
68
|
|
67
69
|
def getting_started
|
68
|
-
|
70
|
+
end
|
69
71
|
|
70
|
-
|
71
|
-
#
|
72
|
-
#
|
73
|
-
# sysctl_lines.push('# When getting a VM from a service provider, you will usually get a VM guest and not a VM host and hence these lines should not be added.')
|
74
|
-
# sysctl_lines.push('# Prevent bridged traffic from being processed by iptables rules.')
|
75
|
-
# sysctl_lines.push('net.bridge.bridge-nf-call-ip6tables=0')
|
76
|
-
# sysctl_lines.push('net.bridge.bridge-nf-call-iptables=0')
|
77
|
-
# sysctl_lines.push('net.bridge.bridge-nf-call-arptables=0')
|
78
|
-
sysctl_lines.push('# Redis uses this.')
|
79
|
-
sysctl_lines.push('vm.overcommit_memory=1')
|
80
|
-
sysctl_lines.push('# Elasticsearch uses this.')
|
81
|
-
sysctl_lines.push('vm.max_map_count=262144')
|
82
|
-
commands = [
|
83
|
-
"sudo touch /etc/sysctl.d/99-smartmachine.conf",
|
84
|
-
"echo -e '#{sysctl_lines.join('\n')}' | sudo tee /etc/sysctl.d/99-smartmachine.conf",
|
85
|
-
"sudo sysctl -p /etc/sysctl.d/99-smartmachine.conf"
|
86
|
-
]
|
87
|
-
run_on_machine(commands: commands)
|
72
|
+
def securing_your_server
|
73
|
+
# apt update && apt upgrade
|
74
|
+
# puts 'When updating some packages, you may be prompted to use updated configuration files. If prompted, it is typically safer to keep the locally installed version.'
|
88
75
|
|
89
76
|
# apt install locales-all
|
90
|
-
|
91
77
|
# puts 'You may be prompted to make a menu selection when the Grub package is updated on Ubuntu. If prompted, select keep the local version currently installed.'
|
92
|
-
|
78
|
+
|
79
|
+
# dpkg-reconfigure tzdata
|
80
|
+
# date
|
93
81
|
|
94
82
|
# hostnamectl set-hostname SmartMachine.credentials.machine[:name]
|
95
83
|
|
@@ -99,24 +87,6 @@ module SmartMachine
|
|
99
87
|
# 203.0.113.10 SmartMachine.credentials.machine[:name].example.com SmartMachine.credentials.machine[:name]
|
100
88
|
# 2600:3c01::a123:b456:c789:d012 SmartMachine.credentials.machine[:name].example.com SmartMachine.credentials.machine[:name]
|
101
89
|
|
102
|
-
# dpkg-reconfigure tzdata
|
103
|
-
# date
|
104
|
-
end
|
105
|
-
|
106
|
-
def securing_your_server
|
107
|
-
# apt install unattended-upgrades
|
108
|
-
# dpkg-reconfigure --priority=low unattended-upgrades
|
109
|
-
|
110
|
-
# nano /etc/apt/apt.conf.d/20auto-upgrades
|
111
|
-
# APT::Periodic::Update-Package-Lists "1";
|
112
|
-
# APT::Periodic::Download-Upgradeable-Packages "1";
|
113
|
-
# APT::Periodic::AutocleanInterval "7";
|
114
|
-
# APT::Periodic::Unattended-Upgrade "1";
|
115
|
-
|
116
|
-
# apt install apticron
|
117
|
-
# /usr/lib/apticron/apticron.conf
|
118
|
-
# EMAIL="root@example.com"
|
119
|
-
|
120
90
|
# adduser example_user
|
121
91
|
# adduser example_user sudo
|
122
92
|
|
@@ -143,10 +113,95 @@ module SmartMachine
|
|
143
113
|
# sudo apt install sendmail
|
144
114
|
# sudo cp /etc/fail2ban/fail2ban.conf /etc/fail2ban/fail2ban.local
|
145
115
|
# sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
|
146
|
-
# Change destmail
|
116
|
+
# Change destmail
|
147
117
|
# Change action = %(action_mwl)s
|
148
118
|
# sudo fail2ban-client reload
|
149
119
|
# sudo fail2ban-client status
|
120
|
+
|
121
|
+
# Send email to show that there is a need for pending updates to be completed
|
122
|
+
# apt install apticron
|
123
|
+
# /usr/lib/apticron/apticron.conf
|
124
|
+
# EMAIL="root@example.com"
|
125
|
+
|
126
|
+
# Automatic Updates
|
127
|
+
# apt install unattended-upgrades
|
128
|
+
# sudo systemctl enable unattended-upgrades
|
129
|
+
# sudo systemctl start unattended-upgrades
|
130
|
+
# nano /etc/apt/apt.conf.d/50unattended-upgrades
|
131
|
+
# Unattended-Upgrade::Mail "destemail@domain.com";
|
132
|
+
# Unattended-Upgrade::SyslogEnable "true";
|
133
|
+
# Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
|
134
|
+
# Unattended-Upgrade::Remove-New-Unused-Dependencies "true";
|
135
|
+
# Unattended-Upgrade::Remove-Unused-Dependencies "true";
|
136
|
+
# nano /etc/apt/apt.conf.d/20auto-upgrades
|
137
|
+
# APT::Periodic::Update-Package-Lists "1";
|
138
|
+
# APT::Periodic::Unattended-Upgrade "1";
|
139
|
+
# APT::Periodic::AutocleanInterval "7";
|
140
|
+
end
|
141
|
+
|
142
|
+
def setup_services
|
143
|
+
run_on_machine(commands: "sudo apt update && sudo apt upgrade")
|
144
|
+
|
145
|
+
sysctl_lines = []
|
146
|
+
# sysctl_lines.push('# KVM uses this.')
|
147
|
+
# sysctl_lines.push('# These lines should only be activated for VM hosts and not for VM guests.')
|
148
|
+
# sysctl_lines.push('# When getting a VM from a service provider, you will get a VM guest and not a VM host and hence these lines should not be added.')
|
149
|
+
# sysctl_lines.push('# Prevent bridged traffic from being processed by iptables rules.')
|
150
|
+
# sysctl_lines.push('net.bridge.bridge-nf-call-ip6tables=0')
|
151
|
+
# sysctl_lines.push('net.bridge.bridge-nf-call-iptables=0')
|
152
|
+
# sysctl_lines.push('net.bridge.bridge-nf-call-arptables=0')
|
153
|
+
sysctl_lines.push('# Redis uses this.')
|
154
|
+
sysctl_lines.push('vm.overcommit_memory=1')
|
155
|
+
sysctl_lines.push('# Elasticsearch uses this.')
|
156
|
+
sysctl_lines.push('vm.max_map_count=262144')
|
157
|
+
commands = [
|
158
|
+
"sudo touch /etc/sysctl.d/99-smartmachine.conf",
|
159
|
+
"echo -e '#{sysctl_lines.join('\n')}' | sudo tee /etc/sysctl.d/99-smartmachine.conf",
|
160
|
+
"sudo sysctl -p /etc/sysctl.d/99-smartmachine.conf"
|
161
|
+
]
|
162
|
+
run_on_machine(commands: commands)
|
150
163
|
end
|
164
|
+
|
165
|
+
# These swapfile methods can be used (after required modification), when you need to make swapfile for more memory.
|
166
|
+
# def self.create_swapfile
|
167
|
+
# # Creating swapfile for bundler to work properly
|
168
|
+
# unless system("sudo swapon -s | grep -ci '/swapfile'", out: File::NULL)
|
169
|
+
# print "-----> Creating swap swapfile ... "
|
170
|
+
# system("sudo install -o root -g root -m 0600 /dev/null /swapfile", out: File::NULL)
|
171
|
+
# system("sudo dd if=/dev/zero of=/swapfile bs=1k count=2048k", [:out, :err] => File::NULL)
|
172
|
+
# system("sudo mkswap /swapfile", out: File::NULL)
|
173
|
+
# system("sudo sh -c 'echo \"/swapfile none swap sw 0 0\" >> /etc/fstab'", out: File::NULL)
|
174
|
+
# system("echo 10 | sudo tee /proc/sys/vm/swappiness", out: File::NULL)
|
175
|
+
# system("sudo sed -i '/^vm.swappiness = /d' /etc/sysctl.conf", out: File::NULL)
|
176
|
+
# system("echo vm.swappiness = 10 | sudo tee -a /etc/sysctl.conf", out: File::NULL)
|
177
|
+
# system("echo 50 | sudo tee /proc/sys/vm/vfs_cache_pressure", out: File::NULL)
|
178
|
+
# system("sudo sed -i '/^vm.vfs_cache_pressure = /d' /etc/sysctl.conf", out: File::NULL)
|
179
|
+
# system("echo vm.vfs_cache_pressure = 50 | sudo tee -a /etc/sysctl.conf", out: File::NULL)
|
180
|
+
# puts "done"
|
181
|
+
#
|
182
|
+
# print "-----> Starting swap swapfile ... "
|
183
|
+
# if system("sudo swapon /swapfile", out: File::NULL)
|
184
|
+
# puts "done"
|
185
|
+
# end
|
186
|
+
# end
|
187
|
+
# end
|
188
|
+
#
|
189
|
+
# def self.destroy_swapfile
|
190
|
+
# if system("sudo swapon -s | grep -ci '/swapfile'", out: File::NULL)
|
191
|
+
# print "-----> Stopping swap swapfile ... "
|
192
|
+
# if system("sudo swapoff /swapfile", out: File::NULL)
|
193
|
+
# system("sudo sed -i '/^vm.swappiness = /d' /etc/sysctl.conf", out: File::NULL)
|
194
|
+
# system("echo 100 | sudo tee /proc/sys/vm/vfs_cache_pressure", out: File::NULL)
|
195
|
+
# system("echo 60 | sudo tee /proc/sys/vm/swappiness", out: File::NULL)
|
196
|
+
# puts "done"
|
197
|
+
#
|
198
|
+
# print "-----> Removing swap swapfile ... "
|
199
|
+
# system("sudo sed -i '/^\\/swapfile/d' /etc/fstab", out: File::NULL)
|
200
|
+
# if system("sudo rm /swapfile", out: File::NULL)
|
201
|
+
# puts "done"
|
202
|
+
# end
|
203
|
+
# end
|
204
|
+
# end
|
205
|
+
# end
|
151
206
|
end
|
152
207
|
end
|
data/lib/smart_machine/syncer.rb
CHANGED
@@ -8,7 +8,9 @@ module SmartMachine
|
|
8
8
|
|
9
9
|
push if initial
|
10
10
|
|
11
|
-
pull
|
11
|
+
# Uncomment this if you want to implement pull in sync.
|
12
|
+
# Ideally please remove this functionality in favour of entire server folder backup feature.
|
13
|
+
#pull
|
12
14
|
push
|
13
15
|
|
14
16
|
puts "-----> Syncing SmartMachine Complete"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: smartmachine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- plainsource
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-06-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: net-ssh
|
@@ -417,8 +417,8 @@ licenses:
|
|
417
417
|
metadata:
|
418
418
|
homepage_uri: https://github.com/plainsource/smartmachine
|
419
419
|
bug_tracker_uri: https://github.com/plainsource/smartmachine/issues
|
420
|
-
changelog_uri: https://github.com/plainsource/smartmachine/releases/tag/v1.2.
|
421
|
-
source_code_uri: https://github.com/plainsource/smartmachine/tree/v1.2.
|
420
|
+
changelog_uri: https://github.com/plainsource/smartmachine/releases/tag/v1.2.3
|
421
|
+
source_code_uri: https://github.com/plainsource/smartmachine/tree/v1.2.3
|
422
422
|
post_install_message:
|
423
423
|
rdoc_options: []
|
424
424
|
require_paths:
|