lib/generators/dockerfile_generator.rb in dockerfile-rails-1.3.0 vs lib/generators/dockerfile_generator.rb in dockerfile-rails-1.4.0

- old
+ new

@@ -1,8 +1,9 @@ # frozen_string_literal: true require "erb" +require "json" require_relative "../dockerfile-rails/scanner.rb" class DockerfileGenerator < Rails::Generators::Base include DockerfileRails::Scanner @@ -13,10 +14,11 @@ "compose" => false, "fullstaq" => false, "jemalloc" => false, "label" => {}, "link" => true, + "litefs" => false, "lock" => true, "max-idle" => nil, "mysql" => false, "nginx" => false, "parallel" => false, @@ -109,10 +111,13 @@ desc: "include redis libraries" class_option :sqlite3, aliases: "--sqlite", type: :boolean, default: OPTION_DEFAULTS.sqlite3, desc: "include sqlite3 libraries" + class_option :litefs, type: :boolean, default: OPTION_DEFAULTS.litefs, + desc: "replicate sqlite3 databases using litefs" + class_option :postgresql, aliases: "--postgres", type: :boolean, default: OPTION_DEFAULTS.postgresql, desc: "include postgresql libraries" class_option :mysql, type: :boolean, default: OPTION_DEFAULTS.mysql, desc: "include mysql libraries" @@ -231,10 +236,16 @@ template "docker-entrypoint.erb", "bin/docker-entrypoint" chmod "bin/docker-entrypoint", 0755 & ~File.umask, verbose: false template "docker-compose.yml.erb", "docker-compose.yml" if options.compose + if using_litefs? + template "litefs.yml.erb", "config/litefs.yml" + + fly_attach_consul + end + if @gemfile.include?("vite_ruby") package = JSON.load_file("package.json") unless package.dig("scripts", "build") package["scripts"] ||= {} package["scripts"]["build"] = "vite build --outDir public" @@ -294,10 +305,14 @@ def run_as_root? options.root? end + def using_litefs? + options.litefs? + end + def using_node? return @using_node if @using_node != nil @using_node = File.exist? "package.json" end @@ -493,10 +508,13 @@ packages << "libsqlite3-0" if options.sqlite3? || @sqlite3 packages << "postgresql-client" if options.postgresql? || @postgresql packages << "default-mysql-client" if options.mysql? || @mysql packages << "libjemalloc2" if options.jemalloc? && !options.fullstaq? + # litefs + packages += ["ca-certificates", "fuse3", "sudo"] if options.litefs? + # ActiveStorage preview support packages << "libvips" if @gemfile.include? "ruby-vips" # Rmagick gem if @gemfile.include?("rmagick") || @gemfile.include?("mini_magick") @@ -599,17 +617,25 @@ end def deploy_env env = {} - env["PORT"] = "3001" if options.nginx? && !using_passenger? + env["PORT"] = "3001" if (options.nginx? && !using_passenger?) || using_litefs? if Rails::VERSION::MAJOR < 7 || Rails::VERSION::STRING.start_with?("7.0") env["RAILS_LOG_TO_STDOUT"] = "1" env["RAILS_SERVE_STATIC_FILES"] = "true" unless options.nginx? end + if deploy_database == "sqlite3" + if using_litefs? + env["DATABASE_URL"] = "sqlite3:///litefs/production.sqlite3" + else + env["DATABASE_URL"] = "sqlite3:///data/production.sqlite3" + end + end + if options.yjit? env["RUBY_YJIT_ENABLE"] = "1" end if options.jemalloc? && !options.fullstaq? @@ -637,11 +663,11 @@ env.merge! @@args["deploy"].to_h { |key, value| [key, "$#{key}"] } end env.merge! @@vars["base"] if @@vars["base"] - env.map { |key, value| "#{key}=#{value.inspect}" } + env.map { |key, value| "#{key}=#{value.inspect}" }.sort end def base_args args = {} @@ -714,13 +740,15 @@ binfixups end def deploy_database - if options.postgresql? || @postgresql + # note: as database can be overridden at runtime via DATABASE_URL, + # use presence of "pg" or "mysql2" in the bundle as evidence of intent. + if options.postgresql? || @postgresql || @gemfile.include?("pg") "postgresql" - elsif options.mysql? || @mysql + elsif options.mysql? || @mysql || @gemfile.include?("mysql2") "mysql" else "sqlite3" end end @@ -850,7 +878,35 @@ ActiveSupport::Duration.parse("PT#{t.upcase}") rescue ActiveSupport::Duration.parse("P#{t.upcase}") end.sum.seconds end rescue ArgumentError nil + end + + # if running on fly v2, make a best effort to attach consul + def fly_attach_consul + # certainly not fly unless there is a fly.toml + return unless File.exist? "fly.toml" + + # Check fly.toml to guess if v1 or v2 + toml = File.read("fly.toml") + return if toml.include?("enable_consul") # v1-ism + return unless toml.include?("primary_region") # v2 + + # see if flyctl is in the path + paths = ENV["PATH"].split(File::PATH_SEPARATOR) + cmds = %w(flyctl) + exts = ENV["PATHEXT"] ? ENV["PATHEXT"].split(";") : [""] + flyctl = Enumerator.product(paths, cmds, exts). + map { |path, cmd, ext| File.join(path, "#{cmd}#{ext}") }. + find { |path| File.executable? path } + return unless flyctl + + # see if secret is already set? + secrets = JSON.parse(`#{flyctl} secrets list --json`) + return if secrets.any? { |secret| secret["Name"] == "FLY_CONSUL_URL" } + + # attach consul + say_status "execute", "flyctl consul attach", :green + system "#{flyctl} consul attach" end end