fly.io-rails 0.1.8 → 0.1.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a9adb2bd6c53c8d27b9ade8898e4a5fb4621f5711781e35b8a273535e66996ec
4
- data.tar.gz: 749a208099b67b3bad53c1b729ef873bb911ae7e69368f7b04863aa65519fee8
3
+ metadata.gz: cea74280dbe517e71da0dfe935f7f28b25f75e858eec0c087f8649c4dadf17fa
4
+ data.tar.gz: 6ae317d9fd653109f6eedf71fe0aa7d6de32e7c9532a154ee8b06b7a7e75a918
5
5
  SHA512:
6
- metadata.gz: 60db97b7cf7f75b5c5485ca6395c2d6398b54148a8e5fb1547483c272366c052f2d6810a3882fe65eda906627e936555269dc71b1208404ab1d772d29082c640
7
- data.tar.gz: 0fd8e2988a4ece554272b0a61e63994243bfa23ad421f2ffdd9f0fd7f5beb446ef09cad99acfbdd7c787ed21b398a597ada26f74d203310dd444667aad7a82a2
6
+ metadata.gz: 8daf49d385324229c388f202cd41b0320a835e273e76340e408e3b7667fe92afdf3108366aae23a881153170fb917457aa3eb700ba11356c9513b03411f0b7ce
7
+ data.tar.gz: 175df3eb6a67c028a7c87f6cdd083a896649aecc035c46c2185ab3f270bbeccb15853c599c3e7d20f3e131c0d6a4ef42226003cd848a7235cca0cf51eb4daa0d
@@ -24,6 +24,7 @@ module Fly
24
24
  # extract options
25
25
  self.app = app
26
26
  regions = options[:region]&.flatten || []
27
+ @avahi = options[:avahi]
27
28
  @litefs = options[:litefs]
28
29
  @nomad = options[:nomad]
29
30
  @passenger = options[:passenger]
@@ -58,11 +59,43 @@ module Fly
58
59
 
59
60
  # set additional variables based on application source
60
61
  scan_rails_app
62
+ @redis = :internal if options[:redis]
63
+ if File.exist? 'Procfile.fly'
64
+ @redis = :internal if IO.read('Procfile.fly') =~ /^redis/
65
+ end
66
+
67
+ if options[:anycable] and not @anycable
68
+ # read and remove original config
69
+ original_config = YAML.load_file 'config/cable.yml'
70
+ File.unlink 'config/cable.yml'
71
+
72
+ # add and configure anycable-rails
73
+ say_status :run, 'bundle add anycable-rails'
74
+ Bundler.with_original_env do
75
+ system 'bundle add anycable-rails'
76
+ system 'bin/rails generate anycable:setup --skip-heroku --skip-procfile-dev --skip-jwt --devenv=skip'
77
+ end
78
+
79
+ # insert action_cable_meta_tag
80
+ insert_into_file 'app/views/layouts/application.html.erb',
81
+ " <%= action_cable_meta_tag %>\n",
82
+ after: "<%= csp_meta_tag %>\n"
83
+
84
+ # copy production environment to original config
85
+ anycable_config = YAML.load_file 'config/cable.yml'
86
+ original_config['production'] = anycable_config['production']
87
+ File.write 'config/cable.yml', YAML.dump(original_config)
88
+
89
+ @anycable = true
90
+ end
61
91
 
62
92
  # determine processes
63
93
  @procs = {web: 'bin/rails server'}
64
94
  @procs[:web] = "nginx -g 'daemon off;'" if @passenger
65
95
  @procs[:worker] = 'bundle exec sidekiq' if @sidekiq
96
+ @procs[:redis] = 'redis-server /etc/redis/redis.conf' if @redis
97
+ @procs.merge! 'anycable-rpc': 'bundle exec anycable',
98
+ 'anycable-go': '/usr/local/bin/anycable-go --port=8082' if @anycable
66
99
  end
67
100
 
68
101
  def app
@@ -143,7 +176,9 @@ module Fly
143
176
  end
144
177
 
145
178
  def generate_patches
146
- if @redis_cable and not File.exist? 'config/initializers/action_cable.rb'
179
+ if @redis_cable and not @anycable and @redis != :internal and
180
+ not File.exist? 'config/initializers/action_cable.rb'
181
+
147
182
  app
148
183
  template 'patches/action_cable.rb', 'config/initializers/action_cable.rb'
149
184
  end
@@ -266,7 +301,7 @@ module Fly
266
301
  end
267
302
  end
268
303
 
269
- if @redis and not secrets.include? 'REDIS_URL'
304
+ if @redis and @redis != :internal and not secrets.include? 'REDIS_URL'
270
305
  # Set eviction policy to true if a cache provider, else false.
271
306
  eviction = @redis_cache ? '--enable-eviction' : '--disable-eviction'
272
307
 
@@ -324,18 +359,20 @@ module Fly
324
359
  STDERR.puts "run 'flyctl logs --instance #{machine}' for more information"
325
360
  exit 1
326
361
  end
362
+ end
327
363
 
328
- # start proxy, if necessary
329
- endpoint = Fly::Machines::fly_api_hostname!
364
+ # start proxy, if necessary
365
+ endpoint = Fly::Machines::fly_api_hostname!
330
366
 
331
- # stop previous instances - list will fail on first run
332
- stdout, stderr, status = Open3.capture3('fly machines list --json')
333
- unless stdout.empty?
334
- JSON.parse(stdout).each do |list|
335
- next if list['id'] == machine
336
- system "fly machines remove --force #{list['id']}"
337
- end
338
- end
367
+ # stop previous instances - list will fail on first run
368
+ stdout, stderr, status = Open3.capture3('fly machines list --json')
369
+ unless stdout.empty?
370
+ JSON.parse(stdout).each do |list|
371
+ next if list['id'] == machine or list['state'] == 'destroyed'
372
+ cmd = "fly machines remove --force #{list['id']}"
373
+ say_status :run, cmd
374
+ system cmd
375
+ end
339
376
  end
340
377
 
341
378
  # configure sqlite3 (can be overridden by fly.toml)
@@ -363,23 +400,38 @@ module Fly
363
400
  end
364
401
 
365
402
  # start app
403
+ machines = {}
366
404
  say_status :fly, "start #{app}"
367
- start = Fly::Machines.create_and_start_machine(app, config: config)
368
- machine = start[:id]
405
+ if not toml['processes']
406
+ start = Fly::Machines.create_and_start_machine(app, config: config)
407
+ machines['app'] = start[:id]
408
+ else
409
+ config[:env] ||= {}
410
+ toml['processes'].each do |name, entrypoint|
411
+ config[:env]['SERVER_COMMAND'] = entrypoint
412
+ start = Fly::Machines.create_and_start_machine(app, config: config)
413
+ machines[name] = start[:id]
414
+ end
415
+ end
369
416
 
370
- if !machine
417
+ if machines.empty?
371
418
  STDERR.puts 'Error starting application'
372
419
  PP.pp start, STDERR
373
420
  exit 1
374
421
  end
375
422
 
376
- 5.times do
377
- status = Fly::Machines.wait_for_machine app, machine,
378
- timeout: 60, status: 'started'
379
- return if status[:ok]
423
+ timeout = Time.now + 300
424
+ while Time.now < timeout and not machines.empty?
425
+ machines.each do |name, machine|
426
+ status = Fly::Machines.wait_for_machine app, machine,
427
+ timeout: 10, status: 'started'
428
+ machines.delete name if status[:ok]
429
+ end
380
430
  end
381
431
 
382
- STDERR.puts 'Timeout waiting for application to start'
432
+ unless machines.empty?
433
+ STDERR.puts 'Timeout waiting for application to start'
434
+ end
383
435
  end
384
436
 
385
437
  def terraform(app, image)
@@ -12,7 +12,9 @@ module Fly
12
12
  @postgresql = true
13
13
  end
14
14
 
15
- @sidekiq = IO.read('Gemfile').include? 'sidekiq' rescue false
15
+ gemfile = IO.read('Gemfile') rescue ''
16
+ @sidekiq = gemfile.include? 'sidekiq'
17
+ @anycable = gemfile.include? 'anycable'
16
18
 
17
19
  @cable = ! Dir['app/channels/*.rb'].empty?
18
20
 
@@ -29,6 +29,8 @@ module FlyIoRails
29
29
  end
30
30
 
31
31
  def create_app(name: nil, org: 'personal', regions: [], nomad: false, **rest)
32
+ return if File.exist? 'fly.toml'
33
+
32
34
  cmd = if name
33
35
  "flyctl apps create #{name.inspect} --org #{org.inspect} --machines"
34
36
  else
@@ -1,3 +1,3 @@
1
1
  module Fly_io
2
- VERSION = '0.1.8'
2
+ VERSION = '0.1.10'
3
3
  end
@@ -9,7 +9,10 @@ class AppGenerator < Rails::Generators::Base
9
9
  class_option :region, type: :array, repeatable: true, default: []
10
10
  class_option :nomad, type: :boolean, default: false
11
11
 
12
+ class_option :anycable, type: :boolean, default: false
13
+ class_option :avahi, type: :boolean, default: false
12
14
  class_option :litefs, type: :boolean, default: false
15
+ class_option :redis, type: :boolean, default: false
13
16
  class_option :passenger, type: :boolean, default: false
14
17
  class_option :serverless, type: :boolean, default: false
15
18
 
@@ -30,9 +30,12 @@ ARG BUNDLER_VERSION=<%= @bundler_version %>
30
30
 
31
31
  ARG RAILS_ENV=production
32
32
  ENV RAILS_ENV=${RAILS_ENV}
33
-
34
- ENV RAILS_SERVE_STATIC_FILES true
33
+ <% if @anycable or not @passenger -%>
35
34
  ENV RAILS_LOG_TO_STDOUT true
35
+ <% end -%>
36
+ <% unless @passenger -%>
37
+ ENV RAILS_SERVE_STATIC_FILES true
38
+ <% end -%>
36
39
 
37
40
  ARG BUNDLE_WITHOUT=development:test
38
41
  ARG BUNDLE_PATH=vendor/bundle
@@ -81,9 +84,6 @@ RUN gem update --system --no-document && \
81
84
 
82
85
  COPY Gemfile* ./
83
86
  RUN bundle install && rm -rf vendor/bundle/ruby/*/cache
84
- <% if @procs.length > 1 -%>
85
- RUN gem install foreman
86
- <% end -%>
87
87
 
88
88
  <% if @node -%>
89
89
  #######################################################################
@@ -113,23 +113,27 @@ FROM flyio/litefs:pr-109 AS litefs
113
113
 
114
114
  FROM base
115
115
 
116
+ <% if @passenger -%>
117
+ # add passenger repository
118
+ RUN apt-get install -y dirmngr gnupg apt-transport-https ca-certificates curl && \
119
+ curl https://oss-binaries.phusionpassenger.com/auto-software-signing-gpg-key.txt | \
120
+ gpg --dearmor > /etc/apt/trusted.gpg.d/phusion.gpg && \
121
+ sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger bullseye main > /etc/apt/sources.list.d/passenger.list'
122
+
123
+ <% end -%>
116
124
  <%
117
125
  @deploy_packages = %w(file vim curl gzip)
118
126
  @deploy_packages += %w(nginx passenger libnginx-mod-http-passenger) if @passenger
119
127
  @deploy_packages << 'postgresql-client' if @postgresql
120
128
  @deploy_packages << 'libsqlite3-0' if @sqlite3
121
129
  @deploy_packages << 'fuse' if @litefs
130
+ @deploy_packages << 'ruby-foreman' if @procs.length > 1
131
+ @deploy_packages << 'redis-server' if @redis == :internal
132
+ @deploy_packages += %w(avahi-daemon avahi-utils libnss-mdns) if @avahi
122
133
  -%>
123
134
  ARG DEPLOY_PACKAGES=<%= @deploy_packages.join(' ').inspect %>
124
135
  ENV DEPLOY_PACKAGES=${DEPLOY_PACKAGES}
125
136
 
126
- <% if @passenger -%>
127
- RUN apt-get install -y dirmngr gnupg apt-transport-https ca-certificates curl && \
128
- curl https://oss-binaries.phusionpassenger.com/auto-software-signing-gpg-key.txt | \
129
- gpg --dearmor > /etc/apt/trusted.gpg.d/phusion.gpg && \
130
- sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger bullseye main > /etc/apt/sources.list.d/passenger.list'
131
-
132
- <% end -%>
133
137
  RUN --mount=type=cache,id=prod-apt-cache,sharing=locked,target=/var/cache/apt \
134
138
  --mount=type=cache,id=prod-apt-lib,sharing=locked,target=/var/lib/apt \
135
139
  apt-get update -qq && \
@@ -137,6 +141,19 @@ RUN --mount=type=cache,id=prod-apt-cache,sharing=locked,target=/var/cache/apt \
137
141
  ${DEPLOY_PACKAGES} \
138
142
  && rm -rf /var/lib/apt/lists /var/cache/apt/archives
139
143
 
144
+ <% if @anycable -%>
145
+ # install anycable
146
+ RUN curl -L https://github.com/anycable/anycable-go/releases/download/v1.2.1/anycable-go-linux-amd64 -o /usr/local/bin/anycable-go && chmod 755 /usr/local/bin/anycable-go
147
+
148
+ <% end -%>
149
+ <% if @redis == :internal -%>
150
+ # configure redis
151
+ RUN sed -i 's/^daemonize yes/daemonize no/' /etc/redis/redis.conf &&\
152
+ sed -i 's/^bind/# bind/' /etc/redis/redis.conf &&\
153
+ sed -i 's/^protected-mode yes/protected-mode no/' /etc/redis/redis.conf &&\
154
+ sed -i 's/^logfile/# logfile/' /etc/redis/redis.conf
155
+
156
+ <% end -%>
140
157
  # copy installed gems
141
158
  COPY --from=gems /app /app
142
159
  COPY --from=gems /usr/lib/fullstaq-ruby/versions /usr/lib/fullstaq-ruby/versions
@@ -158,15 +175,32 @@ ADD config/litefs.yml /etc/litefs.yml
158
175
  RUN mkdir /data
159
176
  <% end -%>
160
177
  #######################################################################
178
+ <% if @avahi -%>
179
+
180
+ # configure avahi for ipv6
181
+ RUN sed -i 's/mdns4_minimal/mdns_minimal/' /etc/nsswitch.conf
182
+ <% end -%>
161
183
  <% if @passenger -%>
162
184
 
163
185
  # configure nginx/passenger
164
186
  COPY config/nginx.conf /etc/nginx/sites-available/rails.conf
165
187
  RUN rm /etc/nginx/sites-enabled/default && \
166
- ln -s /etc/nginx/sites-available/rails.conf /etc/nginx/sites-enabled/
188
+ ln -s /etc/nginx/sites-available/rails.conf /etc/nginx/sites-enabled/ && \
189
+ sed -i 's/user .*;/user root;/' /etc/nginx/nginx.conf && \
190
+ sed -i '/^include/i include /etc/nginx/main.d/*.conf;' /etc/nginx/nginx.conf && \
191
+ mkdir /etc/nginx/main.d && \
192
+ echo 'env RAILS_MASTER_KEY;' >> /etc/nginx/main.d/env.conf &&\
193
+ <% if @redis -%>
194
+ echo 'env REDIS_URL;' >> /etc/nginx/main.d/env.conf &&\
195
+ <% end -%>
196
+ <% if @anycable -%>
197
+ echo 'env ANYCABLE_RPC_HOST;' >> /etc/nginx/main.d/env.conf &&\
198
+ echo 'env CABLE_URL;' >> /etc/nginx/main.d/env.conf &&\
199
+ <% end -%>
200
+ echo 'env RAILS_LOG_TO_STDOUT;' >> /etc/nginx/main.d/env.conf
167
201
  <% if @serverless -%>
168
202
  COPY config/hook_detached_process /etc/nginx/
169
- <% end -%>
203
+ <% end -%>
170
204
  <% end -%>
171
205
 
172
206
  # Deploy your application
@@ -17,20 +17,46 @@ namespace :fly do
17
17
  task :release => 'db:migrate'
18
18
  <%- end -%>
19
19
 
20
+ <% end -%>
21
+ <% if @avahi -%>
22
+ task :env do
23
+ <% if @redis -%>
24
+ ENV['REDIS_URL'] = "redis://#{ENV['FLY_REGION']}-redis.local:6379/1"
25
+ <% end -%>
26
+ <% if @anycable -%>
27
+ ENV['ANYCABLE_RPC_HOST'] = "#{ENV['FLY_REGION']}-anycable-rpc.local:50051"
28
+ ENV['CABLE_URL'] = "#{ENV['FLY_REGION']}-anycable-go.local"
29
+ <% end -%>
30
+ end
31
+
20
32
  <% end -%>
21
33
  # SERVER step:
22
34
  # - changes to the filesystem made here are deployed
23
35
  # - full access to secrets, databases
24
36
  # - failures here result in VM being stated, shutdown, and rolled back
25
37
  # to last successful deploy (if any).
26
- <%- if @sqlite3 -%>
27
- task :server => [:swapfile, 'db:migrate'] do
28
- <%- else -%>
29
- task :server => :swapfile do
30
- <%- end -%>
38
+ <%= begin
39
+ deps = [:swapfile]
40
+ deps << 'db:migrate' if @sqlite3
41
+ deps = deps.first if deps.length == 1
42
+
43
+ if @procs.length > 1 ? ':server, [:formation]' : ':server'
44
+ "task :server, [:formation] => #{deps.inspect} do |task, args|"
45
+ else
46
+ "task :server => #{deps.inspect} do"
47
+ end
48
+ end %>
31
49
  <%- if @procs.length > 1 -%>
50
+ formation = args[:formation] || <%= @procs.keys.map {|key| "#{key}=1"}.join(';').inspect %>
51
+ formation.gsub! ';', ','
52
+ <%- if @avahi -%>
53
+ Rake::Task['fly:avahi_publish'].invoke(formation)
54
+ <%- end -%>
32
55
  Bundler.with_original_env do
33
- sh 'foreman start --procfile=Procfile.fly'
56
+ <%- if @avahi -%>
57
+ # Rake::Task['fly:env'].invoke
58
+ <%- end -%>
59
+ sh "foreman start --procfile=Procfile.fly --formation=#{formation}"
34
60
  end
35
61
  <%- else -%>
36
62
  sh <%= @procs.values.first.inspect %>
@@ -53,5 +79,8 @@ namespace :fly do
53
79
  sh 'mkswap /swapfile'
54
80
  sh 'echo 10 > /proc/sys/vm/swappiness'
55
81
  sh 'swapon /swapfile'
82
+ <% if @redis == :internal -%>
83
+ sh 'echo 1 > /proc/sys/vm/overcommit_memory'
84
+ <% end -%>
56
85
  end
57
86
  end
@@ -1,7 +1,9 @@
1
1
  app = "<%= @app %>"
2
2
  kill_signal = "SIGINT"
3
3
  kill_timeout = 5
4
+ <% unless @avahi -%>
4
5
  processes = []
6
+ <% end -%>
5
7
 
6
8
  [build]
7
9
  [build.args]
@@ -23,6 +25,11 @@ processes = []
23
25
  <% else -%>
24
26
  DATABASE_URL = "sqlite3:///mnt/volume/production.sqlite3"
25
27
  <% end -%>
28
+ <% if @avahi -%>
29
+
30
+ [processes]
31
+ app = "bin/rails fly:server[<%= @procs.keys.map {|key| "#{key}=1"}.join(';') %>]"
32
+ <% end -%>
26
33
 
27
34
  [mounts]
28
35
  source = <%= "#{app.gsub('-', '_')}_volume".inspect %>
@@ -3,9 +3,5 @@
3
3
  status = `passenger-status`
4
4
 
5
5
  processes = status[/^Processes\s*:\s*(\d*)/, 1].to_i
6
- <% if @cable -%>
7
- cable = status[/^<%= @app %>-cable.*?\n\n/m]
8
- processes -= 1 if cable and cable =~ /Sessions:\s*[1-9]/
9
- <% end -%>
10
6
 
11
- system 'nginx -s stop' if processes == 0
7
+ system 'nginx -s stop' if processes == 0
@@ -4,26 +4,44 @@ passenger_min_instances 0;
4
4
  passenger_pool_idle_time 300;
5
5
 
6
6
  <% end -%>
7
+ passenger_log_file /dev/stdout;
8
+ passenger_default_user root;
9
+
7
10
  server {
8
- listen 8080;
11
+ listen 8080 default_server;
12
+ listen [::]:8080 default_server;
9
13
  server_name <%= @app %>.fly.dev;
10
14
  root /app/public;
11
15
 
16
+ access_log /dev/stdout;
17
+ error_log /dev/stdout info;
18
+
12
19
  passenger_enabled on;
13
20
  passenger_ruby /usr/lib/fullstaq-ruby/versions/<%= @ruby_version %>-jemalloc/bin/ruby;
14
21
 
15
- <% if @cable -%>
16
- location / {
17
- passenger_app_group_name <%= @app%>;
18
- }
22
+ <% if @anycable -%>
23
+ location /cable {
24
+ proxy_pass http://localhost:8082/cable;
25
+ proxy_http_version 1.1;
26
+ proxy_set_header Upgrade $http_upgrade;
27
+ proxy_set_header Connection "Upgrade";
28
+ proxy_set_header Host $host;
29
+ }
19
30
 
20
- location /cable {
21
- passenger_app_group_name <%= @app%>-cable;
22
- passenger_force_max_concurrent_requests_per_process 0;
23
- }
31
+ <% elsif @cable -%>
32
+ location /cable {
33
+ passenger_app_group_name <%= @app %>-cable;
34
+ passenger_force_max_concurrent_requests_per_process 0;
35
+ }
24
36
 
25
37
  <% end -%>
38
+ location / {
39
+ passenger_app_group_name <%= @app %>;
40
+ passenger_env_var RAILS_SERVE_STATIC_FILES true;
41
+ passenger_env_var RAILS_LOG_TO_STDOUT true;
42
+ }
43
+
26
44
  # Nginx has a default limit of 1 MB for request bodies, which also applies
27
45
  # to file uploads. The following line enables uploads of up to 50 MB:
28
46
  client_max_body_size 50M;
29
- }
47
+ }
data/lib/tasks/fly.rake CHANGED
@@ -50,6 +50,30 @@ namespace :fly do
50
50
  end
51
51
  end
52
52
  end
53
+
54
+ desc 'dbus daemon - used for IPC'
55
+ task :dbus_deamon do
56
+ IO.write '/var/lib/dbus/machine-id', `hostname`
57
+ mkdir_p '/var/run/dbus'
58
+ sh 'dbus-daemon --config-file=/usr/share/dbus-1/system.conf --print-address'
59
+ end
60
+
61
+ desc 'Zeroconf/avahi/bonjour discovery'
62
+ task :avahi_publish, [:formation] => :dbus_deamon do |task, args|
63
+ pids = []
64
+ pids << spawn('avahi-daemon')
65
+ sleep 0.1
66
+
67
+ ip = IPSocket.getaddress(Socket.gethostname)
68
+ args[:formation].scan(/([-\w]+)=(\d+)/).each do |name, count|
69
+ next if count.to_i == 0
70
+ pids << spawn("avahi-publish -a -R #{ENV['FLY_REGION']}-#{name}.local #{ip}")
71
+ end
72
+
73
+ at_exit do
74
+ pids.each {|pid| Process.kill 7, pid}
75
+ end
76
+ end
53
77
  end
54
78
 
55
79
  # Alias, for convenience
@@ -0,0 +1,17 @@
1
+ require 'rack'
2
+ require 'rack/handler/puma'
3
+
4
+ namespace :mock do
5
+ desc 'Mock server - useful for debugging startup issues'
6
+ task :server do
7
+ handler = Rack::Handler::Puma
8
+
9
+ class RackApp
10
+ def call(env)
11
+ [200, {"Content-Type" => "text/plain"}, ["Hello from Fly.io"]]
12
+ end
13
+ end
14
+
15
+ handler.run RackApp.new, Port: ENV['PORT'] || 8080
16
+ end
17
+ end
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.8
4
+ version: 0.1.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Ruby
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-10-08 00:00:00.000000000 Z
11
+ date: 2022-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fly-ruby
@@ -73,6 +73,7 @@ files:
73
73
  - lib/generators/templates/nginx.conf.erb
74
74
  - lib/generators/templates/patches/action_cable.rb
75
75
  - lib/tasks/fly.rake
76
+ - lib/tasks/mock.rake
76
77
  homepage: https://github.com/rubys/fly.io-rails
77
78
  licenses:
78
79
  - Apache-2.0