fly.io-rails 0.1.2-x86-linux → 0.1.4-x86-linux

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8aa1c4040ccebf009b5ffe230412dd59d49d69de4bdbc8a4aa9db6c4ece01225
4
- data.tar.gz: 12b87e4079e6543fec6dc515df5ea2d73b75295c2ed57f903aa99673952a0b6b
3
+ metadata.gz: 7cf58baf8524f13403d24ffd0526b6f9b68d928a4f6b6f87a2582b8c81782e14
4
+ data.tar.gz: 3420efc23f821ede30faab9b3ddd7181d4268b1c8a363b9124832f5501260a44
5
5
  SHA512:
6
- metadata.gz: a210b5b5caea3bda202bb309cdc7402abf62690bfdaf96e6b25a3f17a5f654dcd2e23ba3ff7506dc5c0555d654650fd1be9f395be7dfd403dfe984e9fe983671
7
- data.tar.gz: 6038ce927e28afbc8433c5b46cb5d6dd1fa158e4a90f69a44c151eb913fa93e37ec719b06ecaac004f5af55b589f10ee456b97582f3757dc55e48e5472c51435
6
+ metadata.gz: 9bdf68f7215f9d409a7e3f3c3f464a8ceae5f17679ce841e550ed14d08522786b6011254267e85a091123d6beba693b2c78089228332da190eb8b0696f12d394
7
+ data.tar.gz: 884c4a641ab1cbd0de2e5349ea783eaae88a73339072cdfe4c9e4e0133159ccdc8be7e5f6577685d3b559a1cda393ba0624994c7d5ceeedc89a4074fefe0960a
@@ -1,5 +1,6 @@
1
1
  require 'open3'
2
2
  require 'thor'
3
+ require 'toml'
3
4
  require 'active_support'
4
5
  require 'active_support/core_ext/string/inflections'
5
6
  require 'fly.io-rails/machines'
@@ -15,8 +16,11 @@ module Fly
15
16
  include Fly::Scanner
16
17
  attr_accessor :options
17
18
 
18
- def initialize(app = nil, regions = nil)
19
- self.app = app if app
19
+ def initialize(app, options={})
20
+ self.app = app
21
+ regions = options[:region].flatten || []
22
+ @litefs = options[:litefs]
23
+ @set_stage = options[:nomad] ? 'set' : 'set --stage'
20
24
 
21
25
  @ruby_version = RUBY_VERSION
22
26
  @bundler_version = Bundler::VERSION
@@ -36,6 +40,7 @@ module Fly
36
40
  end
37
41
 
38
42
  @region = @regions.first || 'iad'
43
+ @regions = [@region] if @regions.empty?
39
44
 
40
45
  @config = Fly::DSL::Config.new
41
46
  if File.exist? 'config/fly.rb'
@@ -50,6 +55,11 @@ module Fly
50
55
  self.app = TOML.load_file('fly.toml')['app']
51
56
  end
52
57
 
58
+ def app_template template_file, destination
59
+ app
60
+ template template_file, destination
61
+ end
62
+
53
63
  def app=(app)
54
64
  @app = app
55
65
  @appName = @app.gsub('-', '_').camelcase(:lower)
@@ -58,33 +68,31 @@ module Fly
58
68
  source_paths.push File::expand_path('../generators/templates', __dir__)
59
69
 
60
70
  def generate_toml
61
- app
62
- template 'fly.toml.erb', 'fly.toml'
71
+ app_template 'fly.toml.erb', 'fly.toml'
63
72
  end
64
73
 
65
74
  def generate_fly_config
66
- app
67
- template 'fly.rb.erb', 'config/fly.rb'
75
+ app_template 'fly.rb.erb', 'config/fly.rb'
68
76
  end
69
77
 
70
78
  def generate_dockerfile
71
- app
72
- template 'Dockerfile.erb', 'Dockerfile'
79
+ app_template 'Dockerfile.erb', 'Dockerfile'
73
80
  end
74
81
 
75
82
  def generate_dockerignore
76
- app
77
- template 'dockerignore.erb', '.dockerignore'
83
+ app_template 'dockerignore.erb', '.dockerignore'
78
84
  end
79
85
 
80
86
  def generate_terraform
81
- app
82
- template 'main.tf.erb', 'main.tf'
87
+ app_template 'main.tf.erb', 'main.tf'
83
88
  end
84
89
 
85
90
  def generate_raketask
86
- app
87
- template 'fly.rake.erb', 'lib/tasks/fly.rake'
91
+ app_template 'fly.rake.erb', 'lib/tasks/fly.rake'
92
+ end
93
+
94
+ def generate_litefs
95
+ app_template 'litefs.yml.erb', 'config/litefs.yml'
88
96
  end
89
97
 
90
98
  def generate_key
@@ -96,8 +104,8 @@ module Fly
96
104
  end
97
105
 
98
106
  if credentials
99
- say_status :run, "flyctl secrets set --stage RAILS_MASTER_KEY from #{credentials}"
100
- system "flyctl secrets set --stage RAILS_MASTER_KEY=#{IO.read(credentials).chomp}"
107
+ say_status :run, "flyctl secrets #{@set_stage} RAILS_MASTER_KEY from #{credentials}"
108
+ system "flyctl secrets #{@set_stage} RAILS_MASTER_KEY=#{IO.read(credentials).chomp}"
101
109
  puts
102
110
  end
103
111
 
@@ -126,9 +134,9 @@ module Fly
126
134
  def create_volume(app, region, size)
127
135
  volume = "#{app.gsub('-', '_')}_volume"
128
136
  volumes = JSON.parse(`flyctl volumes list --json`).
129
- map {|volume| volume['Name']}
137
+ map {|volume| [volume['Name'], volume['Region']]}
130
138
 
131
- unless volumes.include? volume
139
+ unless volumes.include? [volume, region]
132
140
  cmd = "flyctl volumes create #{volume} --app #{app} --region #{region} --size #{size}"
133
141
  say_status :run, cmd
134
142
  system cmd
@@ -195,11 +203,53 @@ module Fly
195
203
  exit 1
196
204
  end
197
205
 
198
- def deploy(app, image)
199
-
206
+ def launch(app)
200
207
  secrets = JSON.parse(`flyctl secrets list --json`).
201
208
  map {|secret| secret["Name"]}
202
209
 
210
+ unless secrets.include? 'RAILS_MASTER_KEY'
211
+ generate_key
212
+ end
213
+
214
+ if @sqlite3
215
+ if @litefs
216
+ @regions.each do |region|
217
+ @volume = create_volume(app, region, @config.sqlite3.size)
218
+ end
219
+ else
220
+ @volume = create_volume(app, @region, @config.sqlite3.size)
221
+ end
222
+ elsif @postgresql and not secrets.include? 'DATABASE_URL'
223
+ secret = create_postgres(app, @org, @region,
224
+ @config.postgres.vm_size,
225
+ @config.postgres.volume_size,
226
+ @config.postgres.initial_cluster_size)
227
+
228
+ if secret
229
+ cmd = "flyctl secrets #{@set_stage} DATABASE_URL=#{secret}"
230
+ say_status :run, cmd
231
+ system cmd
232
+ end
233
+ end
234
+
235
+ if @redis and not secrets.include? 'REDIS_URL'
236
+ # Set eviction policy to true if a cache provider, else false.
237
+ eviction = @redis_cache ? '--enable-eviction' : '--disable-eviction'
238
+
239
+ secret = create_redis(app, @org, @region, eviction)
240
+
241
+ if secret
242
+ cmd = "flyctl secrets #{@set_stage} REDIS_URL=#{secret}"
243
+ say_status :run, cmd
244
+ system cmd
245
+ end
246
+ end
247
+ end
248
+
249
+ def deploy(app, image)
250
+ launch(app)
251
+
252
+ # default config
203
253
  config = {
204
254
  region: @region,
205
255
  app: app,
@@ -222,67 +272,54 @@ module Fly
222
272
  ]
223
273
  }
224
274
 
225
- unless secrets.include? 'RAILS_MASTER_KEY'
226
- generate_key
275
+ # only run release step if there is a non-empty release task in fly.rake
276
+ if (IO.read('lib/tasks/fly.rake') rescue '') =~ /^\s*task[ \t]*+:?release"?[ \t]*\S/
277
+ # build config for release machine, overriding server command
278
+ release_config = config.dup
279
+ release_config.delete :services
280
+ release_config.delete :mounts
281
+ release_config[:env] = { 'SERVER_COMMAND' => 'bin/rails fly:release' }
282
+
283
+ # perform release
284
+ say_status :fly, release_config[:env]['SERVER_COMMAND']
285
+ machine = release(app, release_config)
286
+ Fly::Machines.delete_machine app, machine if machine
287
+
288
+ # start proxy, if necessary
289
+ endpoint = Fly::Machines::fly_api_hostname!
290
+
291
+ # stop previous instances - list will fail on first run
292
+ stdout, stderr, status = Open3.capture3('fly machines list --json')
293
+ unless stdout.empty?
294
+ JSON.parse(stdout).each do |list|
295
+ next if list['id'] == machine
296
+ system "fly machines remove --force #{list['id']}"
297
+ end
298
+ end
227
299
  end
228
300
 
301
+ # configure sqlite3 (can be overridden by fly.toml)
229
302
  if @sqlite3
230
- volume = create_volume(app, @region, @config.sqlite3.size)
231
-
232
303
  config[:mounts] = [
233
- { volume: volume, path: '/mnt/volume' }
304
+ { volume: @volume, path: '/mnt/volume' }
234
305
  ]
235
306
 
236
307
  config[:env] = {
237
308
  "DATABASE_URL" => "sqlite3:///mnt/volume/production.sqlite3"
238
309
  }
239
- elsif @postgresql and not secrets.include? 'DATABASE_URL'
240
- secret = create_postgres(app, @org, @region,
241
- @config.postgres.vm_size,
242
- @config.postgres.volume_size,
243
- @config.postgres.initial_cluster_size)
244
310
 
245
- if secret
246
- cmd = "flyctl secrets set --stage DATABASE_URL=#{secret}"
247
- say_status :run, cmd
248
- system cmd
311
+ if @litefs
312
+ config[:env]['DATABASE_URL'] = "sqlite3:///data/production.sqlite3"
249
313
  end
250
314
  end
251
315
 
252
- if @redis and not secrets.include? 'REDIS_URL'
253
- # Set eviction policy to true if a cache provider, else false.
254
- eviction = @redis_cache ? '--enable-eviction' : '--disable-eviction'
255
-
256
- secret = create_redis(app, @org, @region, eviction)
257
-
258
- if secret
259
- cmd = "flyctl secrets set --stage REDIS_URL=#{secret}"
260
- say_status :run, cmd
261
- system cmd
262
- end
263
- end
264
-
265
- # build config for release machine, overriding server command
266
- release_config = config.dup
267
- release_config.delete :services
268
- release_config.delete :mounts
269
- release_config[:env] = { 'SERVER_COMMAND' => 'bin/rails fly:release' }
270
-
271
- # perform release
272
- say_status :fly, release_config[:env]['SERVER_COMMAND']
273
- machine = release(app, release_config)
274
- Fly::Machines.delete_machine app, machine if machine
275
-
276
- # start proxy, if necessary
277
- endpoint = Fly::Machines::fly_api_hostname!
278
-
279
- # stop previous instances - list will fail on first run
280
- stdout, stderr, status = Open3.capture3('fly machines list --json')
281
- unless stdout.empty?
282
- JSON.parse(stdout).each do |list|
283
- next if list['id'] == machine
284
- system "fly machines remove --force #{list['id']}"
285
- end
316
+ # process toml overrides
317
+ toml = (TOML.load_file('fly.toml') rescue {})
318
+ config[:env] = toml['env'] if toml['env']
319
+ config[:services] = toml['services'] if toml['services']
320
+ if toml['mounts']
321
+ mounts = toml['mounts']
322
+ config[:mounts] = [ { volume: mounts['source'], path: mounts['destination'] } ]
286
323
  end
287
324
 
288
325
  # start app
@@ -28,18 +28,19 @@ module FlyIoRails
28
28
  data.join
29
29
  end
30
30
 
31
- def create_app(name=nil, org='personal', regions=[])
31
+ def create_app(name: nil, org: 'personal', regions: [], nomad: false, **rest)
32
32
  cmd = if name
33
33
  "flyctl apps create #{name.inspect} --org #{org.inspect} --machines"
34
34
  else
35
35
  "flyctl apps create --generate-name --org #{org.inspect} --machines"
36
36
  end
37
+
38
+ cmd.sub! ' --machines', '' if nomad
37
39
 
38
40
  output = tee cmd
39
41
  exit 1 unless output =~ /^New app created: /
40
42
 
41
43
  @app = output.split.last
42
- template 'fly.toml.erb', 'fly.toml' if defined? template # rake tasks are on their own
43
44
 
44
45
  unless regions.empty?
45
46
  @regions = regions.flatten
@@ -1,3 +1,3 @@
1
1
  module Fly_io
2
- VERSION = '0.1.2'
2
+ VERSION = '0.1.4'
3
3
  end
@@ -7,23 +7,28 @@ class AppGenerator < Rails::Generators::Base
7
7
  class_option :name, type: :string, required: false
8
8
  class_option :org, type: :string, default: 'personal'
9
9
  class_option :region, type: :array, repeatable: true, default: []
10
+ class_option :nomad, type: :boolean, default: false
11
+
12
+ class_option :litefs, type: :boolean, default: false
10
13
 
11
14
  def generate_app
12
15
  source_paths.push File.expand_path('../templates', __dir__)
13
16
 
14
- create_app(options[:name], options[:org], options)
17
+ create_app(**options.symbolize_keys)
15
18
 
16
- action = Fly::Actions.new(@app, options[:region])
19
+ action = Fly::Actions.new(@app, options)
17
20
 
21
+ action.generate_toml
18
22
  action.generate_fly_config unless File.exist? 'config/fly.rb'
19
23
  action.generate_dockerfile unless File.exist? 'Dockerfile'
20
24
  action.generate_dockerignore unless File.exist? '.dockerignore'
21
25
  action.generate_raketask unless File.exist? 'lib/tasks/fly.rake'
26
+ action.generate_litefs if options[:litefs] and not File.exist? 'config/litefs'
22
27
  action.generate_patches
23
28
  action.generate_ipv4
24
29
  action.generate_ipv6
25
- action.generate_key
26
-
30
+
31
+ action.launch(@app)
27
32
  end
28
33
  end
29
34
  end
@@ -8,13 +8,16 @@ class TerraformGenerator < Rails::Generators::Base
8
8
  class_option :org, type: :string, default: 'personal'
9
9
  class_option :region, type: :array, repeatable: true, default: []
10
10
 
11
+ class_option :litefs, type: :boolean, default: false
12
+
11
13
  def terraform
12
14
  source_paths.push File.expand_path('../templates', __dir__)
13
15
 
14
- create_app(options[:name], options[:org], options[:region])
16
+ create_app(**options.symbolize_keys)
15
17
 
16
- action = Fly::Actions.new(@app, options[:region])
18
+ action = Fly::Actions.new(@app, options)
17
19
 
20
+ action.generate_toml
18
21
  action.generate_dockerfile
19
22
  action.generate_dockerignore
20
23
  action.generate_terraform
@@ -26,4 +29,4 @@ class TerraformGenerator < Rails::Generators::Base
26
29
  tee 'terraform init'
27
30
  end
28
31
  end
29
- end
32
+ end
@@ -21,6 +21,8 @@ ARG RUBY_VERSION=<%= @ruby_version %>
21
21
  ARG VARIANT=jemalloc-slim
22
22
  FROM quay.io/evl.ms/fullstaq-ruby:${RUBY_VERSION}-${VARIANT} as base
23
23
 
24
+ LABEL fly_launch_runtime="rails"
25
+
24
26
  <% if @node -%>
25
27
  ARG NODE_VERSION=<%= @node_version %>
26
28
  <% end -%>
@@ -54,7 +56,12 @@ RUN volta install node@${NODE_VERSION} yarn
54
56
 
55
57
  FROM base as build_deps
56
58
 
57
- ARG BUILD_PACKAGES="git build-essential libpq-dev wget vim curl gzip xz-utils libsqlite3-dev"
59
+ <%
60
+ @build_packages = %w(git build-essential wget vim curl gzip xz-utils)
61
+ @build_packages << 'libpq-dev' if @postgresql
62
+ @build_packages << 'libsqlite3-dev' if @sqlite3
63
+ -%>
64
+ ARG BUILD_PACKAGES=<%= @build_packages.join(' ').inspect %>
58
65
  ENV BUILD_PACKAGES ${BUILD_PACKAGES}
59
66
 
60
67
  RUN --mount=type=cache,id=dev-apt-cache,sharing=locked,target=/var/cache/apt \
@@ -92,12 +99,24 @@ RUN npm install
92
99
 
93
100
  <% end -%>
94
101
  #######################################################################
102
+ <% if @litefs -%>
103
+
104
+ # Fetch the LiteFS binary
105
+ FROM flyio/litefs:pr-109 AS litefs
95
106
 
107
+ #######################################################################
108
+ <% end %>
96
109
  # install deployment packages
97
110
 
98
111
  FROM base
99
112
 
100
- ARG DEPLOY_PACKAGES="postgresql-client file vim curl gzip libsqlite3-0"
113
+ <%
114
+ @deploy_packages = %w(file vim curl gzip)
115
+ @deploy_packages << 'postgresql-client' if @postgresql
116
+ @deploy_packages << 'libsqlite3-0' if @sqlite3
117
+ @deploy_packages << 'fuse' if @litefs
118
+ -%>
119
+ ARG DEPLOY_PACKAGES=<%= @deploy_packages.join(' ').inspect %>
101
120
  ENV DEPLOY_PACKAGES=${DEPLOY_PACKAGES}
102
121
 
103
122
  RUN --mount=type=cache,id=prod-apt-cache,sharing=locked,target=/var/cache/apt \
@@ -116,6 +135,16 @@ COPY --from=gems /usr/local/bundle /usr/local/bundle
116
135
  # copy installed node modules
117
136
  COPY --from=node_modules /app/node_modules /app/node_modules
118
137
 
138
+ <% end -%>
139
+ <% if @litefs -%>
140
+ # copy litefs binary
141
+ COPY --from=litefs /usr/local/bin/litefs /usr/local/bin/litefs
142
+
143
+ # Copy our LiteFS configuration.
144
+ ADD config/litefs.yml /etc/litefs.yml
145
+
146
+ # Create mount point
147
+ RUN mkdir /data
119
148
  <% end -%>
120
149
  #######################################################################
121
150
 
@@ -140,6 +169,10 @@ RUN ${BUILD_COMMAND}
140
169
 
141
170
  # Default server start instructions. Generally Overridden by fly.toml.
142
171
  ENV PORT 8080
172
+ <% if @litefs -%>
173
+ ARG SERVER_COMMAND="litefs"
174
+ <% else -%>
143
175
  ARG SERVER_COMMAND="bin/rails fly:server"
176
+ <% end -%>
144
177
  ENV SERVER_COMMAND ${SERVER_COMMAND}
145
178
  CMD ${SERVER_COMMAND}
@@ -6,6 +6,7 @@ namespace :fly do
6
6
  # - Failures here prevent deployment
7
7
  task :build => 'assets:precompile'
8
8
 
9
+ <% unless @litefs -%>
9
10
  # RELEASE step:
10
11
  # - changes to the filesystem made here are DISCARDED
11
12
  # - full access to secrets, databases
@@ -16,6 +17,7 @@ namespace :fly do
16
17
  task :release => 'db:migrate'
17
18
  <%- end -%>
18
19
 
20
+ <% end -%>
19
21
  # SERVER step:
20
22
  # - changes to the filesystem made here are deployed
21
23
  # - full access to secrets, databases
@@ -1,4 +1,67 @@
1
1
  app = "<%= @app %>"
2
+ kill_signal = "SIGINT"
3
+ kill_timeout = 5
4
+ processes = []
5
+
6
+ [build]
7
+ [build.args]
8
+ BUILD_COMMAND = "bin/rails fly:build"
9
+ <% if @litefs -%>
10
+ SERVER_COMMAND = "litefs"
11
+ <% else -%>
12
+ SERVER_COMMAND = "bin/rails fly:server"
2
13
 
3
14
  [deploy]
4
- release_command = "bundle exec rails fly:release"
15
+ release_command = "bin/rails fly:release"
16
+ <% end -%>
17
+
18
+ [env]
19
+ PORT = "8080"
20
+ <% if @sqlite3 -%>
21
+ <% if @litefs -%>
22
+ DATABASE_URL = "sqlite3:///data/production.sqlite3"
23
+ <% else -%>
24
+ DATABASE_URL = "sqlite3:///mnt/volume/production.sqlite3"
25
+ <% end -%>
26
+
27
+ [mounts]
28
+ source = <%= "#{app.gsub('-', '_')}_volume".inspect %>
29
+ destination = "/mnt/volume"
30
+ <% end -%>
31
+
32
+ [experimental]
33
+ allowed_public_ports = []
34
+ auto_rollback = true
35
+ <% if @litefs -%>
36
+ enable_consul = true
37
+ <% end -%>
38
+
39
+ [[services]]
40
+ http_checks = []
41
+ internal_port = 8080
42
+ processes = ["app"]
43
+ protocol = "tcp"
44
+ script_checks = []
45
+ [services.concurrency]
46
+ hard_limit = 25
47
+ soft_limit = 20
48
+ type = "connections"
49
+
50
+ [[services.ports]]
51
+ force_https = true
52
+ handlers = ["http"]
53
+ port = 80
54
+
55
+ [[services.ports]]
56
+ handlers = ["tls", "http"]
57
+ port = 443
58
+
59
+ [[services.tcp_checks]]
60
+ grace_period = "1s"
61
+ interval = "15s"
62
+ restart_limit = 0
63
+ timeout = "2s"
64
+
65
+ [[statics]]
66
+ guest_path = "/app/public"
67
+ url_prefix = "/"
@@ -0,0 +1,14 @@
1
+ # The path to where the SQLite database will be accessed.
2
+ mount-dir: "/data"
3
+
4
+ # The path to where the underlying volume mount is.
5
+ data-dir: "/mnt/volume"
6
+
7
+ # Execute this subprocess once LiteFS connects to the cluster.
8
+ exec: "bin/rails fly:server"
9
+
10
+ # These environment variables will be available in your Fly.io application.
11
+ # You must specify "experiement.enable_consul" for FLY_CONSUL_URL to be available.
12
+ consul:
13
+ url: "${FLY_CONSUL_URL}"
14
+ advertise-url: "http://${HOSTNAME}.vm.${FLY_APP_NAME}.internal:20202"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fly.io-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.4
5
5
  platform: x86-linux
6
6
  authors:
7
7
  - Sam Ruby
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-09-25 00:00:00.000000000 Z
11
+ date: 2022-09-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fly-ruby
@@ -67,6 +67,7 @@ files:
67
67
  - lib/generators/templates/fly.rake.erb
68
68
  - lib/generators/templates/fly.rb.erb
69
69
  - lib/generators/templates/fly.toml.erb
70
+ - lib/generators/templates/litefs.yml.erb
70
71
  - lib/generators/templates/main.tf.erb
71
72
  - lib/generators/templates/patches/action_cable.rb
72
73
  - lib/tasks/fly.rake