rake-funnel 0.0.1.pre

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.
Files changed (111) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +21 -0
  5. data/Gemfile +29 -0
  6. data/Guardfile +24 -0
  7. data/README.md +29 -0
  8. data/Rakefile +77 -0
  9. data/build.cmd +30 -0
  10. data/bundle.cmd +26 -0
  11. data/config/.gitignore +1 -0
  12. data/config/.local.yaml.example +9 -0
  13. data/config/default.yaml +5 -0
  14. data/config/dev.yaml +0 -0
  15. data/config/production.yaml +3 -0
  16. data/lib/rake/funnel/ambiguous_file_error.rb +29 -0
  17. data/lib/rake/funnel/execution_error.rb +26 -0
  18. data/lib/rake/funnel/extensions/camel_case.rb +19 -0
  19. data/lib/rake/funnel/extensions/common_path.rb +52 -0
  20. data/lib/rake/funnel/extensions/disable_colors.rb +27 -0
  21. data/lib/rake/funnel/extensions/rexml.rb +23 -0
  22. data/lib/rake/funnel/extensions/shell.rb +56 -0
  23. data/lib/rake/funnel/framework.rb +15 -0
  24. data/lib/rake/funnel/integration/progress_report.rb +70 -0
  25. data/lib/rake/funnel/integration/sync_output.rb +8 -0
  26. data/lib/rake/funnel/integration/teamcity/nunit_plugin.rb +59 -0
  27. data/lib/rake/funnel/integration/teamcity/progress_report.rb +33 -0
  28. data/lib/rake/funnel/integration/teamcity/service_messages.rb +40 -0
  29. data/lib/rake/funnel/integration/teamcity/teamcity.rb +15 -0
  30. data/lib/rake/funnel/integration/teamcity.rb +5 -0
  31. data/lib/rake/funnel/support/finder.rb +51 -0
  32. data/lib/rake/funnel/support/mapper.rb +81 -0
  33. data/lib/rake/funnel/support/mapper_styles/default.rb +31 -0
  34. data/lib/rake/funnel/support/mapper_styles/msbuild.rb +33 -0
  35. data/lib/rake/funnel/support/mapper_styles/msdeploy.rb +47 -0
  36. data/lib/rake/funnel/support/mapper_styles/nunit.rb +33 -0
  37. data/lib/rake/funnel/support/mono.rb +17 -0
  38. data/lib/rake/funnel/support/patch.rb +37 -0
  39. data/lib/rake/funnel/support/template_engine.rb +26 -0
  40. data/lib/rake/funnel/support/which.rb +15 -0
  41. data/lib/rake/funnel/tasks/bin_path.rb +34 -0
  42. data/lib/rake/funnel/tasks/copy.rb +54 -0
  43. data/lib/rake/funnel/tasks/environments.rb +74 -0
  44. data/lib/rake/funnel/tasks/environments_support/loader.rb +37 -0
  45. data/lib/rake/funnel/tasks/msbuild.rb +52 -0
  46. data/lib/rake/funnel/tasks/msbuild_support/build_tool.rb +28 -0
  47. data/lib/rake/funnel/tasks/msdeploy.rb +58 -0
  48. data/lib/rake/funnel/tasks/msdeploy_support/registry_patch.rb +84 -0
  49. data/lib/rake/funnel/tasks/nunit.rb +46 -0
  50. data/lib/rake/funnel/tasks/paket.rb +39 -0
  51. data/lib/rake/funnel/tasks/quick_template.rb +45 -0
  52. data/lib/rake/funnel/tasks/side_by_side_specs.rb +33 -0
  53. data/lib/rake/funnel/tasks/side_by_side_specs_support/remover.rb +62 -0
  54. data/lib/rake/funnel/tasks/timing.rb +100 -0
  55. data/lib/rake/funnel/tasks/timing_support/report.rb +89 -0
  56. data/lib/rake/funnel/tasks/timing_support/statistics.rb +26 -0
  57. data/lib/rake/funnel/tasks/zip.rb +66 -0
  58. data/lib/rake/funnel/version.rb +5 -0
  59. data/lib/rake/funnel.rb +7 -0
  60. data/rake-funnel.gemspec +28 -0
  61. data/spec/rake/funnel/execution_error_spec.rb +67 -0
  62. data/spec/rake/funnel/extensions/camel_case_spec.rb +17 -0
  63. data/spec/rake/funnel/extensions/common_path_spec.rb +56 -0
  64. data/spec/rake/funnel/extensions/disable_colors_spec.rb +33 -0
  65. data/spec/rake/funnel/extensions/rexml_spec.rb +20 -0
  66. data/spec/rake/funnel/extensions/shell_spec.rb +237 -0
  67. data/spec/rake/funnel/integration/progress_report_spec.rb +149 -0
  68. data/spec/rake/funnel/integration/sync_output_spec.rb +16 -0
  69. data/spec/rake/funnel/integration/teamcity/nunit_plugin_spec.rb +112 -0
  70. data/spec/rake/funnel/integration/teamcity/progress_report_spec.rb +174 -0
  71. data/spec/rake/funnel/integration/teamcity/service_messages_spec.rb +136 -0
  72. data/spec/rake/funnel/integration/teamcity/teamcity_spec.rb +34 -0
  73. data/spec/rake/funnel/support/finder_spec.rb +210 -0
  74. data/spec/rake/funnel/support/mapper_spec.rb +87 -0
  75. data/spec/rake/funnel/support/mapper_styles/msdeploy_spec.rb +222 -0
  76. data/spec/rake/funnel/support/mapper_styles/nunit_spec.rb +25 -0
  77. data/spec/rake/funnel/support/mapper_styles/styles_spec.rb +214 -0
  78. data/spec/rake/funnel/support/mono_spec.rb +57 -0
  79. data/spec/rake/funnel/support/patch_spec.rb +108 -0
  80. data/spec/rake/funnel/support/template_engine_spec.rb +65 -0
  81. data/spec/rake/funnel/support/which_spec.rb +65 -0
  82. data/spec/rake/funnel/tasks/bin_path_spec.rb +40 -0
  83. data/spec/rake/funnel/tasks/copy_spec.rb +101 -0
  84. data/spec/rake/funnel/tasks/environments_spec.rb +237 -0
  85. data/spec/rake/funnel/tasks/environments_support/loader_spec.rb +114 -0
  86. data/spec/rake/funnel/tasks/msbuild_spec.rb +91 -0
  87. data/spec/rake/funnel/tasks/msbuild_support/build_tool_spec.rb +21 -0
  88. data/spec/rake/funnel/tasks/msdeploy_spec.rb +243 -0
  89. data/spec/rake/funnel/tasks/msdeploy_support/registry_patch_spec.rb +139 -0
  90. data/spec/rake/funnel/tasks/nunit_spec.rb +76 -0
  91. data/spec/rake/funnel/tasks/paket_spec.rb +184 -0
  92. data/spec/rake/funnel/tasks/quick_template_spec.rb +89 -0
  93. data/spec/rake/funnel/tasks/side_by_side_specs_spec.rb +58 -0
  94. data/spec/rake/funnel/tasks/side_by_side_specs_support/example/FooCode.cs +0 -0
  95. data/spec/rake/funnel/tasks/side_by_side_specs_support/example/FooSpecs.cs +0 -0
  96. data/spec/rake/funnel/tasks/side_by_side_specs_support/example/Sample.csproj +28 -0
  97. data/spec/rake/funnel/tasks/side_by_side_specs_support/example/Specs.cs +0 -0
  98. data/spec/rake/funnel/tasks/side_by_side_specs_support/example/subdir/BarCode.cs +0 -0
  99. data/spec/rake/funnel/tasks/side_by_side_specs_support/example/subdir/BarSpecs.cs +0 -0
  100. data/spec/rake/funnel/tasks/side_by_side_specs_support/remover_spec.rb +116 -0
  101. data/spec/rake/funnel/tasks/timing_spec.rb +133 -0
  102. data/spec/rake/funnel/tasks/timing_support/report_spec.rb +129 -0
  103. data/spec/rake/funnel/tasks/zip_spec.rb +119 -0
  104. data/spec/spec_helper.rb +32 -0
  105. data/tools/MSDeploy/Microsoft.Web.Delegation.dll +0 -0
  106. data/tools/MSDeploy/Microsoft.Web.Deployment.Tracing.dll +0 -0
  107. data/tools/MSDeploy/Microsoft.Web.Deployment.dll +0 -0
  108. data/tools/MSDeploy/en/msdeploy.resources.dll +0 -0
  109. data/tools/MSDeploy/msdeploy.exe +0 -0
  110. data/tools/MSDeploy/msdeploy.exe.config +6 -0
  111. metadata +253 -0
@@ -0,0 +1,33 @@
1
+ require 'rake'
2
+
3
+ module Rake::Funnel::Integration::TeamCity
4
+ class ProgressReport < Rake::Funnel::Integration::ProgressReport
5
+ include Rake::Funnel::Integration
6
+
7
+ def initialize
8
+ super do
9
+ task_starting do |task, args|
10
+ next unless TeamCity.running?
11
+
12
+ unless TeamCity.rake_runner?
13
+ ServiceMessages.block_opened({ name: task.name })
14
+ end
15
+ end
16
+
17
+ task_finished do |task, args, error|
18
+ next unless TeamCity.running?
19
+
20
+ if error.respond_to?(:inner_exception)
21
+ error = error.inner_exception
22
+ end
23
+
24
+ ServiceMessages.build_problem({ description: error.message[0..4000 - 1] }) if error
25
+
26
+ next if Rake::Funnel::Integration::TeamCity.rake_runner?
27
+
28
+ ServiceMessages.block_closed({ name: task.name })
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,40 @@
1
+ module Rake::Funnel::Integration::TeamCity
2
+ class ServiceMessages
3
+ class << self
4
+ def method_missing(method, *args, &block)
5
+ return unless Rake::Funnel::Integration::TeamCity.running?
6
+
7
+ message_name = method.camelize
8
+ publish message_name, args[0]
9
+ end
10
+
11
+ private
12
+ def publish(message_name, args)
13
+ args = [message_name] << escaped_array_of(args)
14
+ args = args.flatten.reject(&:nil?)
15
+
16
+ puts "##teamcity[#{args.join(' ')}]"
17
+ end
18
+
19
+ def escape(string)
20
+ string
21
+ .gsub(/\|/, '||')
22
+ .gsub(/'/, "|'")
23
+ .gsub(/\r/, '|r')
24
+ .gsub(/\n/, '|n')
25
+ .gsub(/\u0085/, '|x')
26
+ .gsub(/\u2028/, '|l')
27
+ .gsub(/\u2029/, '|p')
28
+ .gsub(/\[/, '|[')
29
+ .gsub(/\]/, '|]')
30
+ end
31
+
32
+ def escaped_array_of(args)
33
+ return [] if args.nil?
34
+
35
+ return "'#{escape args}'" unless args.is_a?(Hash)
36
+ args.map { |key, value| "#{key.camelize}='#{escape value.to_s}'" }
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,15 @@
1
+ module Rake::Funnel::Integration
2
+ module TeamCity
3
+ ENV_VAR = 'TEAMCITY_PROJECT_NAME'
4
+
5
+ class << self
6
+ def running?
7
+ ENV.include?(ENV_VAR)
8
+ end
9
+
10
+ def rake_runner?
11
+ running? && Object.const_defined?('Rake') && Rake.const_defined?('TeamCityApplication')
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ module Rake::Funnel::Integration::TeamCity; end
2
+
3
+ Dir["#{File.dirname(__FILE__)}/teamcity/*.rb"].each do |path|
4
+ require path
5
+ end
@@ -0,0 +1,51 @@
1
+ module Rake::Funnel::Support
2
+ class Finder
3
+ include Enumerable
4
+
5
+ def initialize(search_pattern, task, message = nil)
6
+ @search_pattern = search_pattern
7
+ @task = task
8
+ @message = message
9
+ end
10
+
11
+ def each
12
+ block_given? or return enum_for(__method__)
13
+ all_or_default.each { |x| yield x }
14
+ end
15
+
16
+ def single_or_default
17
+ first_sln
18
+ end
19
+
20
+ def single
21
+ if first_sln.nil?
22
+ raise Rake::Funnel::AmbiguousFileError.new(@message, @task.name, @search_pattern, candidates)
23
+ end
24
+
25
+ first_sln
26
+ end
27
+
28
+ def all_or_default
29
+ candidates
30
+ end
31
+
32
+ def all
33
+ if candidates.empty?
34
+ raise Rake::Funnel::AmbiguousFileError.new(@message, @task.name, @search_pattern, candidates)
35
+ end
36
+
37
+ candidates
38
+ end
39
+
40
+ private
41
+ def first_sln
42
+ return candidates.first if candidates.one?
43
+
44
+ nil
45
+ end
46
+
47
+ def candidates
48
+ Dir[*@search_pattern].select { |f| File.file?(f) }.uniq
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,81 @@
1
+ Dir["#{File.dirname(__FILE__)}/mapper_styles/*.rb"].each do |path|
2
+ require path
3
+ end
4
+
5
+ module Rake::Funnel::Support
6
+ class Switch
7
+ attr_reader :switch, :values
8
+
9
+ def initialize(switch, values)
10
+ @values = values
11
+ @switch = switch
12
+ end
13
+ end
14
+
15
+ class Value
16
+ attr_reader :key, :value
17
+
18
+ def initialize(value)
19
+ @key = nil
20
+ @value = value
21
+ end
22
+ end
23
+
24
+ class KeyValuePair
25
+ attr_reader :key, :value
26
+
27
+ def initialize(key, value)
28
+ @key = key
29
+ @value = value
30
+ end
31
+ end
32
+
33
+ class Mapper
34
+ def initialize(style = :Default)
35
+ raise "You cannot use a 'nil' mapper. Available mappers are: #{MapperStyles.constants.sort.join(', ')}" if style.nil?
36
+
37
+ @style = style
38
+ begin
39
+ @style = MapperStyles.const_get(style).new if style.kind_of?(Symbol)
40
+ rescue => ex
41
+ raise "Something went wrong while creating the '#{style}' mapper: #{ex}"
42
+ end
43
+ end
44
+
45
+ def map(args = {})
46
+ model = (args || {}).map { |switch, value|
47
+ value = [value] unless value.kind_of?(Array)
48
+
49
+ values = value.map do |val|
50
+ get_values(val)
51
+ end
52
+
53
+ Switch.new(switch, values)
54
+ }.flatten
55
+
56
+ @style
57
+ .generate_from(model)
58
+ .map { |args| args.map { |arg| camel_case_symbols(arg) }}
59
+ .map(&:join)
60
+ end
61
+
62
+ private
63
+ def get_values(value)
64
+ if value.kind_of?(Enumerable)
65
+ pairs = value.map { |k, v|
66
+ KeyValuePair.new(k, v)
67
+ }
68
+
69
+ return Array.new(pairs) if value.kind_of?(Array)
70
+ pairs
71
+ else
72
+ Value.new(value)
73
+ end
74
+ end
75
+
76
+ def camel_case_symbols(value)
77
+ return value unless value.kind_of?(Symbol)
78
+ value.camelize
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,31 @@
1
+ module Rake::Funnel::Support::MapperStyles
2
+ class Default
3
+ attr_reader :prefix, :value_separator
4
+
5
+ def initialize
6
+ @prefix = '/'
7
+ @value_separator = ','
8
+ end
9
+
10
+ def generate_from(model)
11
+ model.map { |switch|
12
+ switch.values.flatten.map { |value|
13
+ [top_level(switch), nested(value)].reject(&:empty?)
14
+ }
15
+ }.flatten(2)
16
+ end
17
+
18
+ private
19
+ def top_level(switch)
20
+ [prefix, switch.switch]
21
+ end
22
+
23
+ def nested(value)
24
+ res = []
25
+ res << value.key
26
+ res << value_separator unless value.key.nil? || value.value.nil?
27
+ res << value.value
28
+ res.compact
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,33 @@
1
+ module Rake::Funnel::Support::MapperStyles
2
+ class MSBuild
3
+ attr_reader :prefix, :separator, :value_separator
4
+
5
+ def initialize
6
+ @prefix = '/'
7
+ @separator = ':'
8
+ @value_separator = '='
9
+ end
10
+
11
+ def generate_from(model)
12
+ model.map { |switch|
13
+ switch.values.flatten.map { |value|
14
+ top_level(switch) + nested(value)
15
+ }
16
+ }.flatten(1)
17
+ end
18
+
19
+ private
20
+ def top_level(switch)
21
+ [prefix, switch.switch]
22
+ end
23
+
24
+ def nested(value)
25
+ res = []
26
+ res << separator unless value.key.nil? && value.value.nil?
27
+ res << value.key
28
+ res << value_separator unless value.key.nil? || value.value.nil?
29
+ res << value.value
30
+ res.compact
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,47 @@
1
+ module Rake::Funnel::Support::MapperStyles
2
+ class MSDeploy
3
+ attr_reader :prefix, :separator, :value_separator, :value_list_separator
4
+
5
+ def initialize
6
+ @prefix = '-'
7
+ @separator = ':'
8
+ @value_separator = '='
9
+ @value_list_separator = ','
10
+ end
11
+
12
+ def generate_from(model)
13
+ model.map { |switch|
14
+ switch.values.map { |item|
15
+ if item.kind_of? Enumerable
16
+ values = item.map.with_index { |nested, index| nested(nested, index) }
17
+ else
18
+ values = nested(item)
19
+ end
20
+
21
+ (top_level(switch) + values).flatten
22
+ }
23
+ }.flatten(1)
24
+ end
25
+
26
+ private
27
+ def top_level(switch)
28
+ [prefix, quote(switch.switch)]
29
+ end
30
+
31
+ def nested(value, index = 0)
32
+ res = []
33
+ res << value_list_separator unless index == 0
34
+ res << separator unless value.key.nil? && value.value.nil? || index != 0
35
+ res << quote(value.key)
36
+ res << value_separator unless value.key.nil? || value.value.nil?
37
+ res << quote(value.value)
38
+ res.compact
39
+ end
40
+
41
+ def quote(value)
42
+ value = value.gsub(/"/, '""') if value.kind_of?(String)
43
+ return %Q{"#{value}"} if value =~ /\s/
44
+ value
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,33 @@
1
+ module Rake::Funnel::Support::MapperStyles
2
+ class NUnit
3
+ attr_reader :prefix, :separator, :value_separator
4
+
5
+ def initialize
6
+ @prefix = Rake::Win32.windows? ? '/' : '-'
7
+ @separator = '='
8
+ @value_separator = ':'
9
+ end
10
+
11
+ def generate_from(model)
12
+ model.map { |switch|
13
+ switch.values.flatten.map { |value|
14
+ top_level(switch) + nested(value)
15
+ }
16
+ }.flatten(1)
17
+ end
18
+
19
+ private
20
+ def top_level(switch)
21
+ [prefix, switch.switch]
22
+ end
23
+
24
+ def nested(value)
25
+ res = []
26
+ res << separator unless value.key.nil? && value.value.nil?
27
+ res << value.key
28
+ res << value_separator unless value.key.nil? || value.value.nil?
29
+ res << value.value
30
+ res.compact
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,17 @@
1
+ module Rake::Funnel::Support
2
+ class Mono
3
+ class << self
4
+ def invocation(executable, *args)
5
+ exe_args = ([executable] << args).flatten.compact
6
+
7
+ if Rake::Win32.windows?
8
+ return exe_args
9
+ end
10
+
11
+ executable = exe_args.shift
12
+ found = Which.which(executable) || executable
13
+ exe_args.unshift('mono', found)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,37 @@
1
+ module Rake::Funnel::Support
2
+ class Patch
3
+ def initialize(context = nil)
4
+ @context = context
5
+
6
+ yield self if block_given?
7
+ end
8
+
9
+ def setup(&block)
10
+ @setup = block
11
+ end
12
+
13
+ def reset(&block)
14
+ @reset = block
15
+ end
16
+
17
+ def apply!
18
+ return self if @memo
19
+ @memo = (@setup || noop).call(@context)
20
+
21
+ self
22
+ end
23
+
24
+ def revert!
25
+ return self unless @memo
26
+ (@reset || noop).call(@memo)
27
+ @memo = nil
28
+
29
+ self
30
+ end
31
+
32
+ private
33
+ def noop
34
+ Proc.new { }
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,26 @@
1
+ require 'erb'
2
+
3
+ module Rake::Funnel::Support
4
+ class TemplateEngine
5
+ class << self
6
+ def render(template, filename = nil, binding = nil)
7
+ render = ERB.new(replace_at_markers(template), nil, '%<>')
8
+ render.filename = filename
9
+ render.result(binding || top_level_binding)
10
+ end
11
+
12
+ private
13
+ def replace_at_markers(template)
14
+ tags = /(@\w[\w\.]+\w@)/
15
+
16
+ (template || '').gsub(tags) do |match|
17
+ "<%= #{match[1...-1]} %>"
18
+ end
19
+ end
20
+
21
+ def top_level_binding
22
+ TOPLEVEL_BINDING.dup
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,15 @@
1
+ module Rake::Funnel::Support
2
+ class Which
3
+ class << self
4
+ def which(executable)
5
+ return executable if File.file?(executable)
6
+
7
+ ENV['PATH']
8
+ .split(File::PATH_SEPARATOR)
9
+ .map { |path| File.join(path, executable) }
10
+ .select { |path| File.file?(path) }
11
+ .first
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,34 @@
1
+ require 'rake/tasklib'
2
+
3
+ module Rake::Funnel::Tasks
4
+ class BinPath < Rake::TaskLib
5
+ attr_accessor :name, :pattern
6
+
7
+ def initialize(name = :bin_path)
8
+ @name = name
9
+ @pattern = %w(tools/* tools/*/bin packages/**/tools)
10
+
11
+ yield self if block_given?
12
+ define
13
+ end
14
+
15
+ private
16
+ def define
17
+ task @name do
18
+ Rake.rake_output_message 'Added the following paths to the PATH environment variable:'
19
+ add_pattern_to_path_environment.each do |p|
20
+ Rake.rake_output_message " - #{p}"
21
+ end
22
+ end
23
+
24
+ self
25
+ end
26
+
27
+ def add_pattern_to_path_environment
28
+ bin_paths = Dir[*@pattern].map { |path| File.expand_path(path) }.sort
29
+
30
+ ENV['PATH'] = ([] << bin_paths << ENV['PATH']).flatten.join(File::PATH_SEPARATOR)
31
+ bin_paths
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,54 @@
1
+ require 'rake/clean'
2
+ require 'rake/tasklib'
3
+
4
+ module Rake::Funnel::Tasks
5
+ class Copy < Rake::TaskLib
6
+ attr_accessor :name, :source, :target
7
+
8
+ def initialize(name = :copy)
9
+ @name = name
10
+
11
+ @source = []
12
+ @target = nil
13
+
14
+ yield self if block_given?
15
+ define
16
+ end
17
+
18
+ private
19
+ def define
20
+ target && CLEAN.include(target)
21
+
22
+ desc "Copy #{files.join(', ')} to #{target}"
23
+ task name do
24
+ raise 'Target not defined' unless target
25
+
26
+ files.each do |source|
27
+ next if File.directory?(source)
28
+
29
+ target = target_path(source)
30
+
31
+ dir = File.dirname(target)
32
+ RakeFileUtils.mkdir_p(dir) unless File.directory?(dir)
33
+
34
+ RakeFileUtils.cp(source, target)
35
+ end
36
+ end
37
+
38
+ self
39
+ end
40
+
41
+ def files
42
+ Rake::Funnel::Support::Finder.new(source, self, 'No files found.').all_or_default
43
+ end
44
+
45
+ def target_path(file)
46
+ target_relative = Pathname.new(file).relative_path_from(Pathname.new(common_path)).to_s
47
+ File.join(target, target_relative)
48
+ end
49
+
50
+ def common_path
51
+ @common_path ||= files.common_path
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,74 @@
1
+ require 'rake/tasklib'
2
+
3
+ Dir["#{File.dirname(__FILE__)}/environments_support/*.rb"].each do |path|
4
+ require path
5
+ end
6
+
7
+ module Rake::Funnel::Tasks
8
+ class Environments < Rake::TaskLib
9
+ attr_accessor :base_dir, :default_env, :default_config, :local_config
10
+
11
+ def initialize
12
+ @default_env = nil
13
+ @default_config = 'default'
14
+ @local_config = 'local'
15
+ @base_dir = 'config'
16
+
17
+ yield self if block_given?
18
+ define
19
+ default_environment_setup
20
+
21
+ self
22
+ end
23
+
24
+ private
25
+ def define
26
+ environments.each do |env|
27
+ desc "Configure for the #{env[:name]} environment"
28
+ task env[:name] do
29
+ EnvironmentsSupport::Loader.load_configuration(env)
30
+ end
31
+ end
32
+ end
33
+
34
+ def environments
35
+ default = File.join(@base_dir, config_ext(default_config))
36
+ local = File.join(@base_dir, config_ext(local_config))
37
+
38
+ Dir[File.join(@base_dir, config_ext('*'))]
39
+ .reject { |config| config == default || config == local }
40
+ .map do |config|
41
+ {
42
+ name: File.basename(config, '.*'),
43
+ config_files: [
44
+ File.exists?(default) ? default : nil,
45
+ config,
46
+ File.exists?(local) ? local : nil
47
+ ].compact
48
+ }
49
+ end
50
+ end
51
+
52
+ def config_ext(name)
53
+ "#{name}.yaml"
54
+ end
55
+
56
+ def default_environment_setup
57
+ return unless @default_env
58
+
59
+ tasks = user_defined_env_tasks
60
+ if tasks.empty?
61
+ tasks = [] << Rake.application.current_scope.path_with_task_name(@default_env)
62
+ end
63
+
64
+ tasks.each do |task|
65
+ Rake::Task[task].invoke
66
+ end
67
+ end
68
+
69
+ def user_defined_env_tasks
70
+ expect_user_defined = environments.map { |env| Rake.application.current_scope.path_with_task_name(env[:name]) }
71
+ Rake.application.top_level_tasks.select { |t| expect_user_defined.include?(t) }
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,37 @@
1
+ require 'configatron'
2
+ require 'yaml'
3
+
4
+ module Rake::Funnel::Tasks::EnvironmentsSupport
5
+ class Loader
6
+ class << self
7
+ def load_configuration(config, store = configatron)
8
+ log("Configuring for #{config[:name]}")
9
+ store.unlock!
10
+ store.reset!
11
+
12
+ store.env = config[:name]
13
+
14
+ operation = 'Loading'
15
+ config.fetch(:config_files, []).each do |file|
16
+ log("#{operation} #{file}")
17
+ operation = 'Merging'
18
+
19
+ yaml = File.read(file)
20
+ yaml = ERB.new(yaml).result
21
+ yaml = YAML.load(yaml) || {}
22
+ store.configure_from_hash(yaml)
23
+ end
24
+
25
+ store.lock!
26
+
27
+ log('')
28
+ log(store.inspect)
29
+ end
30
+
31
+ private
32
+ def log(message)
33
+ Rake.rake_output_message(message)
34
+ end
35
+ end
36
+ end
37
+ end