dry-web-roda 0.6.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +7 -1
  3. data/.rspec +1 -2
  4. data/.travis.yml +14 -8
  5. data/CHANGELOG.md +22 -0
  6. data/Gemfile +26 -15
  7. data/README.md +22 -4
  8. data/dry-web-roda.gemspec +3 -1
  9. data/lib/dry/web/roda/application.rb +3 -3
  10. data/lib/dry/web/roda/cli.rb +9 -2
  11. data/lib/dry/web/roda/cli/generate.rb +4 -4
  12. data/lib/dry/web/roda/generators/flat_project.rb +31 -0
  13. data/lib/dry/web/roda/generators/{app.rb → sub_app.rb} +2 -2
  14. data/lib/dry/web/roda/generators/{umbrella.rb → umbrella_project.rb} +6 -6
  15. data/lib/dry/web/roda/skeletons/{umbrella → flat_project}/Gemfile +3 -3
  16. data/lib/dry/web/roda/skeletons/{umbrella → flat_project}/README.md.tt +0 -0
  17. data/lib/dry/web/roda/skeletons/{umbrella → flat_project}/Rakefile.tt +0 -0
  18. data/lib/dry/web/roda/skeletons/{umbrella → flat_project}/bin/console.tt +0 -0
  19. data/lib/dry/web/roda/skeletons/{umbrella → flat_project}/bin/setup +0 -0
  20. data/lib/dry/web/roda/skeletons/{umbrella → flat_project}/config.ru.tt +0 -0
  21. data/lib/dry/web/roda/skeletons/{umbrella → flat_project}/config/settings.yml.tt +0 -0
  22. data/lib/dry/web/roda/skeletons/{umbrella → flat_project}/db/sample_data.rb +0 -0
  23. data/lib/dry/web/roda/skeletons/{umbrella → flat_project}/db/seed.rb +0 -0
  24. data/lib/dry/web/roda/skeletons/{app → flat_project}/lib/__underscored_app_name__/.keep +0 -0
  25. data/lib/dry/web/roda/skeletons/{app → flat_project}/lib/__underscored_app_name__/views/welcome.rb.tt +0 -0
  26. data/lib/dry/web/roda/skeletons/{umbrella → flat_project}/lib/persistence/commands/.keep +0 -0
  27. data/lib/dry/web/roda/skeletons/{umbrella → flat_project}/lib/persistence/relations/.keep +0 -0
  28. data/lib/dry/web/roda/skeletons/flat_project/lib/rom/instrumentation.rb.tt +22 -0
  29. data/lib/dry/web/roda/skeletons/{umbrella → flat_project}/lib/types.rb +0 -0
  30. data/lib/dry/web/roda/skeletons/{umbrella → flat_project}/log/.keep +0 -0
  31. data/lib/dry/web/roda/skeletons/{umbrella → flat_project}/spec/app_helper.rb +0 -0
  32. data/lib/dry/web/roda/skeletons/{umbrella → flat_project}/spec/db_helper.rb.tt +0 -0
  33. data/lib/dry/web/roda/skeletons/{umbrella → flat_project}/spec/spec_helper.rb.tt +0 -0
  34. data/lib/dry/web/roda/skeletons/{umbrella → flat_project}/spec/support/db/test_factories.rb +0 -0
  35. data/lib/dry/web/roda/skeletons/{umbrella → flat_project}/spec/support/test_helpers.rb.tt +0 -0
  36. data/lib/dry/web/roda/skeletons/flat_project/system/__underscored_app_name__/application.rb.tt +29 -0
  37. data/lib/dry/web/roda/skeletons/flat_project/system/__underscored_app_name__/container.rb.tt +23 -0
  38. data/lib/dry/web/roda/skeletons/{app → flat_project}/system/__underscored_app_name__/import.rb.tt +0 -0
  39. data/lib/dry/web/roda/skeletons/{umbrella/lib → flat_project/system}/__underscored_app_name__/repository.rb.tt +0 -0
  40. data/lib/dry/web/roda/skeletons/{umbrella → flat_project}/system/__underscored_app_name__/settings.rb.tt +0 -0
  41. data/lib/dry/web/roda/skeletons/flat_project/system/__underscored_app_name__/transactions.rb.tt +34 -0
  42. data/lib/dry/web/roda/skeletons/{umbrella/lib → flat_project/system}/__underscored_app_name__/view_context.rb.tt +0 -0
  43. data/lib/dry/web/roda/skeletons/{app → flat_project}/system/__underscored_app_name__/view_controller.rb.tt +0 -0
  44. data/lib/dry/web/roda/skeletons/flat_project/system/boot.rb.tt +11 -0
  45. data/lib/dry/web/roda/skeletons/flat_project/system/boot/monitor.rb.tt +10 -0
  46. data/lib/dry/web/roda/skeletons/{umbrella → flat_project}/system/boot/rom.rb.tt +0 -0
  47. data/lib/dry/web/roda/skeletons/{app → flat_project}/system/boot/view.rb.tt +0 -0
  48. data/lib/dry/web/roda/skeletons/flat_project/transactions/example.rb.tt +10 -0
  49. data/lib/dry/web/roda/skeletons/{app → flat_project}/web/routes/example.rb.tt +0 -0
  50. data/lib/dry/web/roda/skeletons/{app → flat_project}/web/templates/layouts/application.html.slim +0 -0
  51. data/lib/dry/web/roda/skeletons/{app → flat_project}/web/templates/welcome.html.slim +0 -0
  52. data/lib/dry/web/roda/skeletons/sub_app/lib/__underscored_app_name__/.keep +0 -0
  53. data/lib/dry/web/roda/skeletons/sub_app/lib/__underscored_app_name__/views/welcome.rb.tt +11 -0
  54. data/lib/dry/web/roda/skeletons/{app → sub_app}/system/__underscored_app_name__/application.rb.tt +1 -1
  55. data/lib/dry/web/roda/skeletons/{app → sub_app}/system/__underscored_app_name__/container.rb.tt +2 -0
  56. data/lib/dry/web/roda/skeletons/{umbrella → sub_app}/system/__underscored_app_name__/import.rb.tt +0 -0
  57. data/lib/dry/web/roda/skeletons/{app → sub_app}/system/__underscored_app_name__/transactions.rb.tt +0 -0
  58. data/lib/dry/web/roda/skeletons/{app → sub_app}/system/__underscored_app_name__/view_context.rb.tt +0 -0
  59. data/lib/dry/web/roda/skeletons/sub_app/system/__underscored_app_name__/view_controller.rb.tt +13 -0
  60. data/lib/dry/web/roda/skeletons/{app → sub_app}/system/boot.rb.tt +1 -2
  61. data/lib/dry/web/roda/skeletons/sub_app/system/boot/view.rb.tt +3 -0
  62. data/lib/dry/web/roda/skeletons/{app → sub_app}/transactions/example.rb.tt +0 -0
  63. data/lib/dry/web/roda/skeletons/sub_app/web/routes/example.rb.tt +7 -0
  64. data/lib/dry/web/roda/skeletons/sub_app/web/templates/layouts/application.html.slim +3 -0
  65. data/lib/dry/web/roda/skeletons/sub_app/web/templates/welcome.html.slim +1 -0
  66. data/lib/dry/web/roda/skeletons/{umbrella → umbrella_project}/.gitignore +0 -0
  67. data/lib/dry/web/roda/skeletons/umbrella_project/Gemfile +39 -0
  68. data/lib/dry/web/roda/skeletons/umbrella_project/README.md.tt +12 -0
  69. data/lib/dry/web/roda/skeletons/umbrella_project/Rakefile.tt +81 -0
  70. data/lib/dry/web/roda/skeletons/umbrella_project/bin/console.tt +7 -0
  71. data/lib/dry/web/roda/skeletons/umbrella_project/bin/setup +7 -0
  72. data/lib/dry/web/roda/skeletons/umbrella_project/config.ru.tt +2 -0
  73. data/lib/dry/web/roda/skeletons/umbrella_project/config/settings.yml.tt +8 -0
  74. data/lib/dry/web/roda/skeletons/umbrella_project/db/sample_data.rb +1 -0
  75. data/lib/dry/web/roda/skeletons/umbrella_project/db/seed.rb +1 -0
  76. data/lib/dry/web/roda/skeletons/umbrella_project/lib/__underscored_app_name__/repository.rb.tt +11 -0
  77. data/lib/dry/web/roda/skeletons/{umbrella → umbrella_project}/lib/__underscored_app_name__/transactions.rb.tt +0 -0
  78. data/lib/dry/web/roda/skeletons/umbrella_project/lib/__underscored_app_name__/view_context.rb.tt +39 -0
  79. data/lib/dry/web/roda/skeletons/umbrella_project/lib/persistence/commands/.keep +0 -0
  80. data/lib/dry/web/roda/skeletons/umbrella_project/lib/persistence/relations/.keep +0 -0
  81. data/lib/dry/web/roda/skeletons/umbrella_project/lib/rom/instrumentation.rb.tt +22 -0
  82. data/lib/dry/web/roda/skeletons/umbrella_project/lib/types.rb +6 -0
  83. data/lib/dry/web/roda/skeletons/umbrella_project/log/.keep +0 -0
  84. data/lib/dry/web/roda/skeletons/umbrella_project/spec/app_helper.rb +35 -0
  85. data/lib/dry/web/roda/skeletons/umbrella_project/spec/db_helper.rb.tt +24 -0
  86. data/lib/dry/web/roda/skeletons/umbrella_project/spec/spec_helper.rb.tt +61 -0
  87. data/lib/dry/web/roda/skeletons/umbrella_project/spec/support/db/test_factories.rb +3 -0
  88. data/lib/dry/web/roda/skeletons/umbrella_project/spec/support/test_helpers.rb.tt +15 -0
  89. data/lib/dry/web/roda/skeletons/umbrella_project/system/__underscored_app_name__/application.rb.tt +14 -0
  90. data/lib/dry/web/roda/skeletons/{umbrella → umbrella_project}/system/__underscored_app_name__/container.rb.tt +1 -0
  91. data/lib/dry/web/roda/skeletons/umbrella_project/system/__underscored_app_name__/import.rb.tt +5 -0
  92. data/lib/dry/web/roda/skeletons/umbrella_project/system/__underscored_app_name__/settings.rb.tt +17 -0
  93. data/lib/dry/web/roda/skeletons/{umbrella → umbrella_project}/system/boot.rb.tt +0 -0
  94. data/lib/dry/web/roda/skeletons/umbrella_project/system/boot/monitor.rb.tt +10 -0
  95. data/lib/dry/web/roda/skeletons/umbrella_project/system/boot/rom.rb.tt +26 -0
  96. data/lib/dry/web/roda/version.rb +1 -1
  97. data/script/ci +67 -0
  98. data/script/setup +47 -0
  99. data/script/teardown +42 -0
  100. data/spec/integration/new_app_spec.rb +21 -0
  101. data/spec/spec_helper.rb +14 -16
  102. data/spec/support/app.rb +64 -0
  103. data/spec/support/bundler.rb +113 -0
  104. data/spec/support/cli.rb +47 -0
  105. data/spec/support/directories.rb +37 -0
  106. data/spec/support/env.rb +84 -0
  107. data/spec/support/files.rb +59 -0
  108. data/spec/support/project.rb +60 -0
  109. data/spec/support/requests.rb +5 -0
  110. data/spec/support/silently.rb +28 -0
  111. metadata +139 -49
  112. data/lib/dry/web/roda/skeletons/umbrella/system/__underscored_app_name__/application.rb.tt +0 -7
  113. data/lib/dry/web/roda/skeletons/umbrella/system/boot/logger.rb.tt +0 -5
@@ -0,0 +1,64 @@
1
+ require "net/http"
2
+ require "uri"
3
+ require "waitutil"
4
+ require_relative "silently"
5
+
6
+ module RSpec
7
+ module Support
8
+ module App
9
+ private
10
+
11
+ class RunningApp
12
+ attr_reader :port
13
+
14
+ def initialize(port)
15
+ @port = port
16
+ end
17
+
18
+ def get(path)
19
+ Net::HTTP.get(uri(path))
20
+ end
21
+
22
+ private
23
+
24
+ def uri(path)
25
+ URI("http://0.0.0.0:#{port}#{path}")
26
+ end
27
+ end
28
+
29
+ def run_app(host: "0.0.0.0", port: "30333", timeout: 5)
30
+ cmd = "bundle exec rackup -o 0.0.0.0 -p #{port} config.ru"
31
+ out = Tempfile.new("dry-web-roda-out")
32
+
33
+ pid = fork {
34
+ Bundler.with_clean_env do
35
+ exec cmd, out: out.path, err: out.path
36
+ end
37
+ }
38
+
39
+ WaitUtil.wait_for_condition "app available on #{host}:#{port}", timeout_sec: timeout do
40
+ begin
41
+ result = WaitUtil.send(:is_tcp_port_open, host, port, WaitUtil::DEFAULT_DELAY_SEC)
42
+
43
+ result || begin
44
+ out.rewind
45
+ [false, "#{cmd} failed:\n#{out.read}"]
46
+ end
47
+ rescue SocketError
48
+ out.rewind
49
+ [false, "#{cmd} failed:\n#{out.read}"]
50
+ end
51
+ end
52
+
53
+ yield RunningApp.new(port)
54
+ ensure
55
+ Process.kill "TERM", pid
56
+ Process.wait pid
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ RSpec.configure do |config|
63
+ config.include RSpec::Support::App, type: :cli
64
+ end
@@ -0,0 +1,113 @@
1
+ require 'open3'
2
+ require 'pathname'
3
+ require_relative 'env'
4
+ require_relative 'silently'
5
+ require_relative 'files'
6
+
7
+ module RSpec
8
+ module Support
9
+ module Bundler
10
+ def self.root
11
+ Pathname.new(__dir__).join("..", "..")
12
+ end
13
+
14
+ def self.cache
15
+ root.join("vendor", "cache")
16
+ end
17
+
18
+ def self.setup
19
+ return if cache.exist?
20
+
21
+ with_clean_env do
22
+ RSpec::Support.silently "./script/setup"
23
+ end
24
+ end
25
+
26
+ def self.with_clean_env(&blk)
27
+ ::Bundler.with_clean_env(&blk)
28
+ end
29
+
30
+ private
31
+
32
+ attr_reader :out, :err, :exitstatus
33
+
34
+ def setup_gemfile(gems: [], exclude_gems: [], path: "Gemfile")
35
+ filtered_content = ::File.readlines(path).
36
+ drop(1).
37
+ reject { |l| exclude_gems.any? { |g| l.include?(g) } }
38
+
39
+ content = ["source 'file://#{cache}'\n"] + filtered_content + gems.map { |g| "gem #{g}\n" }
40
+
41
+ rewrite(path, content)
42
+ end
43
+
44
+ def bundle_install
45
+ bundle "install --local --no-cache --retry 0 --no-color"
46
+ end
47
+
48
+ def bundle_exec(cmd, env: nil, &blk)
49
+ bundle("exec #{cmd}", env: env, &blk)
50
+ end
51
+
52
+ def bundle(cmd, env: nil, &blk)
53
+ ruby_bin = which("ruby")
54
+ bundle_bin = which("bundle")
55
+ rack_env = "RACK_ENV=#{env} " unless env.nil?
56
+
57
+ system_exec("#{rack_env}#{ruby_bin} -I#{load_paths} #{bundle_bin} #{cmd}", &blk)
58
+ end
59
+
60
+ # Adapted from Bundler source code
61
+ #
62
+ # Bundler is released under MIT license
63
+ # https://github.com/bundler/bundler/blob/master/LICENSE.md
64
+ #
65
+ # A special "thank you" goes to Bundler maintainers and contributors.
66
+ #
67
+ # rubocop:disable Metrics/AbcSize
68
+ # rubocop:disable Metrics/MethodLength
69
+ def system_exec(cmd)
70
+ Open3.popen3(RSpec::Support::Env.env, cmd) do |stdin, stdout, stderr, wait_thr|
71
+ yield stdin, stdout, wait_thr if block_given?
72
+ stdin.close
73
+
74
+ @exitstatus = wait_thr && wait_thr.value.exitstatus
75
+ @out = Thread.new { stdout.read }.value.strip
76
+ @err = Thread.new { stderr.read }.value.strip
77
+ end
78
+
79
+ (@all_output ||= "") << [
80
+ "$ #{cmd.to_s.strip}",
81
+ out,
82
+ err,
83
+ @exitstatus ? "# $? => #{@exitstatus}" : "",
84
+ "\n"
85
+ ].reject(&:empty?).join("\n")
86
+
87
+ @out
88
+ end
89
+ # rubocop:enable Metrics/MethodLength
90
+ # rubocop:enable Metrics/AbcSize
91
+
92
+ def load_paths
93
+ [root.join('lib'), root.join('spec')].join(':')
94
+ end
95
+
96
+ def root
97
+ RSpec::Support::Bundler.root
98
+ end
99
+
100
+ def cache
101
+ RSpec::Support::Bundler.cache
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ RSpec.configure do |config|
108
+ config.include RSpec::Support::Bundler, type: :cli
109
+
110
+ config.before(:all, type: :cli) do
111
+ RSpec::Support::Bundler.setup
112
+ end
113
+ end
@@ -0,0 +1,47 @@
1
+ require "aruba"
2
+ require "aruba/api"
3
+ require "pathname"
4
+
5
+ module RSpec
6
+ module Support
7
+ module Cli
8
+ def self.included(spec)
9
+ spec.before do
10
+ aruba = Pathname.new(Dir.pwd).join('tmp', 'aruba')
11
+ aruba.rmtree if aruba.exist?
12
+
13
+ setup_aruba
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def run_command(cmd, output = nil, exit_status: 0)
20
+ run_simple "bundle exec #{cmd}", fail_on_error: false
21
+
22
+ match_output(output)
23
+ expect(last_command_started).to have_exit_status(exit_status)
24
+ end
25
+
26
+ def match_output(output)
27
+ case output
28
+ when String
29
+ expect(all_output).to include(output)
30
+ when Regexp
31
+ expect(all_output).to match(output)
32
+ when Array
33
+ output.each { |o| match_output(o) }
34
+ end
35
+ end
36
+
37
+ def all_output
38
+ all_commands.map(&:output).join("\n")
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ RSpec.configure do |config|
45
+ config.include Aruba::Api, type: :cli
46
+ config.include RSpec::Support::Cli, type: :cli
47
+ end
@@ -0,0 +1,37 @@
1
+ require "fileutils"
2
+
3
+ module RSpec
4
+ module Support
5
+ module Directory
6
+ private
7
+
8
+ def with_directory(directory)
9
+ current = Dir.pwd
10
+ target = Pathname.new(Dir.pwd).join(directory)
11
+
12
+ Dir.chdir(target)
13
+ yield
14
+ ensure
15
+ Dir.chdir(current)
16
+ end
17
+
18
+ def with_tmp_directory
19
+ dir = Pathname.new("tmp").join("aruba")
20
+
21
+ with_directory(dir) do
22
+ yield
23
+ end
24
+ ensure
25
+ FileUtils.rm_rf(dir)
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ RSpec.configure do |config|
32
+ config.include RSpec::Support::Directory, type: :cli
33
+
34
+ config.before :suite do
35
+ Pathname.new(Dir.pwd).join("tmp").mkpath
36
+ end
37
+ end
@@ -0,0 +1,84 @@
1
+ require 'singleton'
2
+ require 'thread'
3
+
4
+ module RSpec
5
+ module Support
6
+ class Env
7
+ include Singleton
8
+
9
+ def self.setup
10
+ instance.__send__(:setup)
11
+ end
12
+
13
+ def self.reset
14
+ instance.__send__(:setup)
15
+ end
16
+
17
+ def self.env
18
+ instance.to_h
19
+ end
20
+
21
+ def self.[](key)
22
+ instance[key]
23
+ end
24
+
25
+ def self.[]=(key, value)
26
+ instance[key] = value
27
+ end
28
+
29
+ def self.fetch_from_original(key)
30
+ instance.__send__(:original).fetch(key)
31
+ end
32
+
33
+ def initialize
34
+ @original = ENV.to_hash
35
+ @mutex = Mutex.new
36
+ setup
37
+ end
38
+
39
+ def [](key)
40
+ synchronize do
41
+ env[key]
42
+ end
43
+ end
44
+
45
+ def []=(key, value)
46
+ synchronize do
47
+ env[key] = value
48
+ end
49
+ end
50
+
51
+ def to_h
52
+ env.dup
53
+ end
54
+
55
+ private
56
+
57
+ attr_reader :original, :env
58
+
59
+ def setup
60
+ synchronize do
61
+ @env = {}
62
+ end
63
+
64
+ self["GEM_ROOT"] = original["GEM_ROOT"]
65
+ self["GEM_HOME"] = original["GEM_HOME"]
66
+ self["GEM_PATH"] = original["GEM_PATH"]
67
+ end
68
+
69
+ def synchronize(&blk)
70
+ @mutex.synchronize(&blk)
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ RSpec.configure do |config|
77
+ config.before(:suite) do
78
+ RSpec::Support::Env.setup
79
+ end
80
+
81
+ config.after do
82
+ RSpec::Support::Env.reset
83
+ end
84
+ end
@@ -0,0 +1,59 @@
1
+ module RSpec
2
+ module Support
3
+ module Files
4
+ private
5
+
6
+ def write(path, *content)
7
+ Pathname.new(path).dirname.mkpath
8
+ open(path, ::File::CREAT | ::File::WRONLY, *content)
9
+ end
10
+
11
+ def rewrite(path, *content)
12
+ open(path, ::File::TRUNC | ::File::WRONLY, *content)
13
+ end
14
+
15
+ def replace(path, target, replacement)
16
+ content = ::File.readlines(path)
17
+ content[index(content, path, target)] = "#{replacement}\n"
18
+
19
+ rewrite(path, content)
20
+ end
21
+
22
+ def replace_last(path, target, replacement)
23
+ content = ::File.readlines(path)
24
+ content[-index(content.reverse, path, target) - 1] = "#{replacement}\n"
25
+
26
+ rewrite(path, content)
27
+ end
28
+
29
+ def unshift(path, line)
30
+ content = ::File.readlines(path)
31
+ content.unshift("#{line}\n")
32
+
33
+ rewrite(path, content)
34
+ end
35
+
36
+ def append(path, contents)
37
+ content = ::File.readlines(path)
38
+ content << "#{contents}\n"
39
+
40
+ rewrite(path, content)
41
+ end
42
+
43
+ def open(path, mode, *content)
44
+ ::File.open(path, mode) do |file|
45
+ file.write(Array(content).flatten.join)
46
+ end
47
+ end
48
+
49
+ def index(content, path, target)
50
+ content.index { |l| l.include?(target) } or
51
+ raise ArgumentError.new("Cannot find `#{target}' inside `#{path}'.")
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ RSpec.configure do |config|
58
+ config.include RSpec::Support::Files, type: :cli
59
+ end
@@ -0,0 +1,60 @@
1
+ require "waitutil"
2
+ require_relative 'env'
3
+ require_relative 'silently'
4
+ require_relative 'bundler'
5
+ require_relative 'directories'
6
+
7
+ module RSpec
8
+ module Support
9
+ module Project
10
+ private
11
+
12
+ KNOWN_ARGUMENTS = [:arch].freeze
13
+
14
+ def with_project(name = "sandbox", **args)
15
+ with_tmp_directory do
16
+ create_project name, args
17
+
18
+ within_project_directory(name) do
19
+ setup_gemfile
20
+ bundle_install
21
+ yield
22
+ end
23
+ end
24
+ end
25
+
26
+ def within_project_directory(project)
27
+ cd(project.to_s) do
28
+ # Aruba resets ENV and its API to set new env vars is broken.
29
+ #
30
+ # We need to manually setup the following env vars:
31
+ #
32
+ # ENV["PATH"] is required by Capybara's selenium/poltergeist drivers
33
+ ENV["PATH"] = RSpec::Support::Env.fetch_from_original("PATH")
34
+ # Bundler on CI can't find HOME and it fails to run Hanami commands
35
+ ENV["HOME"] = RSpec::Support::Env.fetch_from_original("HOME")
36
+
37
+ yield
38
+ end
39
+ end
40
+
41
+ def create_project(name, args)
42
+ silently "dry-web-roda new #{name} #{_create_project_args(args)}"
43
+ end
44
+
45
+ def _create_project_args(args)
46
+ return if args.empty?
47
+
48
+ flags = args.dup.keep_if { |k, _| KNOWN_ARGUMENTS.include?(k) }
49
+
50
+ flags.map { |arg, value|
51
+ "--#{arg}=#{value}"
52
+ }.join(" ")
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ RSpec.configure do |config|
59
+ config.include RSpec::Support::Project, type: :cli
60
+ end