From cc5011ff8d4c8334816ffd9a463eb809f167f60c Mon Sep 17 00:00:00 2001 From: Ufuk Kayserilioglu Date: Fri, 12 Jul 2024 17:59:36 +0300 Subject: [PATCH] Allow Tapioca commands to accept environment variables This change allows Tapioca commands to accept environment variables via the command line or the configuration file. This is useful for setting up the environment for the Tapioca commands, such as setting the custom environment variables that affect how an application is loaded. --- README.md | 18 ++++++++++++++++++ lib/tapioca/cli.rb | 4 ++++ lib/tapioca/helpers/config_helper.rb | 1 + lib/tapioca/helpers/env_helper.rb | 12 +++++++++++- spec/tapioca/cli/dsl_spec.rb | 11 +++++++++++ tasks/readme.rake | 5 +++-- 6 files changed, 48 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d76969e81..423dd7608 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ Commands: Options: -c, [--config=] # Path to the Tapioca configuration file # Default: sorbet/tapioca/config.yml + [--env=key:value] # Environment variables to set before running Tapioca -V, [--verbose], [--no-verbose], [--skip-verbose] # Verbose output for debugging purposes # Default: false @@ -122,6 +123,7 @@ Usage: Options: -c, [--config=] # Path to the Tapioca configuration file # Default: sorbet/tapioca/config.yml + [--env=key:value] # Environment variables to set before running Tapioca -V, [--verbose], [--no-verbose], [--skip-verbose] # Verbose output for debugging purposes # Default: false @@ -202,6 +204,7 @@ Options: # Default: true -c, [--config=] # Path to the Tapioca configuration file # Default: sorbet/tapioca/config.yml + [--env=key:value] # Environment variables to set before running Tapioca -V, [--verbose], [--no-verbose], [--skip-verbose] # Verbose output for debugging purposes # Default: false @@ -376,6 +379,7 @@ Options: --typed, -t, [--typed-overrides=gem:level [gem:level ...]] # Override for typed sigils for pulled annotations -c, [--config=] # Path to the Tapioca configuration file # Default: sorbet/tapioca/config.yml + [--env=key:value] # Environment variables to set before running Tapioca -V, [--verbose], [--no-verbose], [--skip-verbose] # Verbose output for debugging purposes # Default: false @@ -505,6 +509,7 @@ Options: [--compiler-options=key:value] # Options to pass to the DSL compilers -c, [--config=] # Path to the Tapioca configuration file # Default: sorbet/tapioca/config.yml + [--env=key:value] # Environment variables to set before running Tapioca -V, [--verbose], [--no-verbose], [--skip-verbose] # Verbose output for debugging purposes # Default: false @@ -900,6 +905,7 @@ Options: -w, [--workers=N] # Number of parallel workers (default: auto) -c, [--config=] # Path to the Tapioca configuration file # Default: sorbet/tapioca/config.yml + [--env=key:value] # Environment variables to set before running Tapioca -V, [--verbose], [--no-verbose], [--skip-verbose] # Verbose output for debugging purposes # Default: false @@ -938,11 +944,17 @@ The full configuration file, with each option and its default value, would look ```yaml --- require: + env: {} + verbose: false postrequire: sorbet/tapioca/require.rb todo: + env: {} + verbose: false todo_file: sorbet/rbi/todo.rbi file_header: true dsl: + env: {} + verbose: false outdir: sorbet/rbi/dsl file_header: true only: [] @@ -958,6 +970,8 @@ dsl: skip_constant: [] compiler_options: {} gem: + env: {} + verbose: false outdir: sorbet/rbi/gems file_header: true all: false @@ -978,6 +992,8 @@ gem: environment: development halt_upon_load_error: true check_shims: + env: {} + verbose: false gem_rbi_dir: sorbet/rbi/gems dsl_rbi_dir: sorbet/rbi/dsl shim_rbi_dir: sorbet/rbi/shims @@ -986,6 +1002,8 @@ check_shims: payload: true workers: 1 annotations: + env: {} + verbose: false sources: - https://raw.githubusercontent.com/Shopify/rbi-central/main netrc: true diff --git a/lib/tapioca/cli.rb b/lib/tapioca/cli.rb index cadddf6c7..4df22fff5 100644 --- a/lib/tapioca/cli.rb +++ b/lib/tapioca/cli.rb @@ -17,6 +17,10 @@ class Cli < Thor type: :string, desc: "Path to the Tapioca configuration file", default: TAPIOCA_CONFIG_FILE + class_option :env, + type: :hash, + desc: "Environment variables to set before running Tapioca", + repeatable: true class_option :verbose, aliases: ["-V"], type: :boolean, diff --git a/lib/tapioca/helpers/config_helper.rb b/lib/tapioca/helpers/config_helper.rb index fe64bee36..f85bae9c3 100644 --- a/lib/tapioca/helpers/config_helper.rb +++ b/lib/tapioca/helpers/config_helper.rb @@ -100,6 +100,7 @@ def validate_config!(config_file, config) ).returns(T::Array[ConfigError]) end def validate_config_options(command_options, config_key, config_options) + command_options = T.unsafe(self.class).class_options.merge(command_options) config_options.filter_map do |config_option_key, config_option_value| command_option = command_options[config_option_key.to_sym] error_msg = "unknown option `#{config_option_key}` for key `#{config_key}`" diff --git a/lib/tapioca/helpers/env_helper.rb b/lib/tapioca/helpers/env_helper.rb index 1127ed005..7c89690b7 100644 --- a/lib/tapioca/helpers/env_helper.rb +++ b/lib/tapioca/helpers/env_helper.rb @@ -8,10 +8,20 @@ module EnvHelper requires_ancestor { Thor } + private + sig { params(options: T::Hash[Symbol, T.untyped]).void } def set_environment(options) # rubocop:disable Naming/AccessorMethodName - ENV["RAILS_ENV"] = ENV["RACK_ENV"] = options[:environment] + set_all_environment_variables(options[:env]) + ENV["RAILS_ENV"] = ENV["RACK_ENV"] = options[:environment] if options[:environment] ENV["RUBY_DEBUG_LAZY"] = "1" end + + sig { params(options: T.nilable(T::Hash[String, String])).void } + def set_all_environment_variables(options) # rubocop:disable Naming/AccessorMethodName + (options || {}).each do |key, value| + ENV[key] = value + end + end end end diff --git a/spec/tapioca/cli/dsl_spec.rb b/spec/tapioca/cli/dsl_spec.rb index 55921b07e..41670256d 100644 --- a/spec/tapioca/cli/dsl_spec.rb +++ b/spec/tapioca/cli/dsl_spec.rb @@ -2677,6 +2677,17 @@ def title=(title); end RACK ENVIRONMENT: staging OUT end + + it "must accept and set custom environment variables" do + @project.write!("lib/post.rb", <<~RB) + $stderr.puts "ENVIRONMENT: \#{ENV.to_h.inspect}" + RB + + result = @project.tapioca("dsl --env Foo:Bar --env Baz:1") + + assert_stderr_includes(result, '"Foo"=>"Bar"') + assert_stderr_includes(result, '"Baz"=>"1"') + end end describe "list compilers" do diff --git a/tasks/readme.rake b/tasks/readme.rake index 0dbee5934..561577b24 100644 --- a/tasks/readme.rake +++ b/tasks/readme.rake @@ -29,7 +29,8 @@ task :readme do end def skip_option?(option) - option.name == "auth" + ignored_options = ["auth", "config"] + ignored_options.include?(option.name) end def option_value(option) @@ -54,7 +55,7 @@ task :readme do end def command_options(command) - command.options.filter_map do |name, opt| + Tapioca::Cli.class_options.merge(command.options).filter_map do |name, opt| next if skip_option?(opt) [name.to_s, option_value(opt)]