omnibus 5.5.0 → 5.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/.github/PULL_REQUEST_TEMPLATE.md +11 -0
  3. data/.travis.yml +2 -1
  4. data/CHANGELOG.md +37 -0
  5. data/Gemfile +5 -4
  6. data/MAINTAINERS.md +12 -17
  7. data/README.md +98 -107
  8. data/appveyor.yml +1 -1
  9. data/lib/omnibus.rb +4 -4
  10. data/lib/omnibus/builder.rb +42 -9
  11. data/lib/omnibus/cli.rb +5 -0
  12. data/lib/omnibus/cli/base.rb +1 -1
  13. data/lib/omnibus/cli/publish.rb +5 -3
  14. data/lib/omnibus/compressors/dmg.rb +2 -2
  15. data/lib/omnibus/config.rb +42 -5
  16. data/lib/omnibus/core_extensions/open_uri.rb +1 -0
  17. data/lib/omnibus/download_helpers.rb +4 -4
  18. data/lib/omnibus/fetchers/git_fetcher.rb +15 -5
  19. data/lib/omnibus/fetchers/net_fetcher.rb +1 -1
  20. data/lib/omnibus/fetchers/path_fetcher.rb +1 -1
  21. data/lib/omnibus/file_syncer.rb +2 -2
  22. data/lib/omnibus/generator_files/omnibus.rb.erb +1 -0
  23. data/lib/omnibus/git_cache.rb +31 -13
  24. data/lib/omnibus/health_check.rb +1 -173
  25. data/lib/omnibus/licensing.rb +48 -7
  26. data/lib/omnibus/manifest.rb +3 -5
  27. data/lib/omnibus/manifest_entry.rb +1 -1
  28. data/lib/omnibus/metadata.rb +2 -1
  29. data/lib/omnibus/packager.rb +3 -1
  30. data/lib/omnibus/packagers/appx.rb +3 -3
  31. data/lib/omnibus/packagers/base.rb +9 -0
  32. data/lib/omnibus/packagers/bff.rb +4 -6
  33. data/lib/omnibus/packagers/deb.rb +95 -1
  34. data/lib/omnibus/packagers/ips.rb +50 -4
  35. data/lib/omnibus/packagers/pkgsrc.rb +112 -0
  36. data/lib/omnibus/packagers/rpm.rb +72 -3
  37. data/lib/omnibus/packagers/solaris.rb +0 -4
  38. data/lib/omnibus/packagers/windows_base.rb +1 -1
  39. data/lib/omnibus/project.rb +13 -3
  40. data/lib/omnibus/publishers/artifactory_publisher.rb +4 -6
  41. data/lib/omnibus/publishers/s3_publisher.rb +8 -3
  42. data/lib/omnibus/reports.rb +1 -1
  43. data/lib/omnibus/s3_cache.rb +18 -5
  44. data/lib/omnibus/s3_helpers.rb +45 -8
  45. data/lib/omnibus/software.rb +55 -37
  46. data/lib/omnibus/sugarable.rb +4 -0
  47. data/lib/omnibus/templating.rb +29 -13
  48. data/lib/omnibus/util.rb +81 -2
  49. data/lib/omnibus/version.rb +1 -1
  50. data/lib/omnibus/whitelist.rb +228 -0
  51. data/omnibus.gemspec +9 -8
  52. data/resources/dmg/create_dmg.osascript.erb +33 -13
  53. data/resources/ips/doc-transform.erb +2 -0
  54. data/resources/rpm/spec.erb +1 -2
  55. data/spec/functional/builder_spec.rb +21 -21
  56. data/spec/functional/fetchers/git_fetcher_spec.rb +6 -6
  57. data/spec/functional/fetchers/net_fetcher_spec.rb +7 -7
  58. data/spec/functional/fetchers/path_fetcher_spec.rb +5 -5
  59. data/spec/functional/file_syncer_spec.rb +6 -6
  60. data/spec/functional/licensing_spec.rb +29 -16
  61. data/spec/functional/templating_spec.rb +23 -22
  62. data/spec/support/git_helpers.rb +30 -24
  63. data/spec/unit/build_version_spec.rb +1 -1
  64. data/spec/unit/builder_spec.rb +36 -24
  65. data/spec/unit/changelogprinter_spec.rb +10 -8
  66. data/spec/unit/cleanroom_spec.rb +6 -6
  67. data/spec/unit/compressors/dmg_spec.rb +23 -37
  68. data/spec/unit/compressors/null_spec.rb +2 -2
  69. data/spec/unit/compressors/tgz_spec.rb +2 -2
  70. data/spec/unit/config_spec.rb +2 -1
  71. data/spec/unit/digestable_spec.rb +2 -2
  72. data/spec/unit/fetchers/git_fetcher_spec.rb +5 -5
  73. data/spec/unit/fetchers/net_fetcher_spec.rb +46 -6
  74. data/spec/unit/fetchers/path_fetcher_spec.rb +5 -5
  75. data/spec/unit/file_syncer_spec.rb +19 -0
  76. data/spec/unit/git_cache_spec.rb +76 -22
  77. data/spec/unit/health_check_spec.rb +1 -1
  78. data/spec/unit/library_spec.rb +2 -2
  79. data/spec/unit/manifest_spec.rb +6 -6
  80. data/spec/unit/metadata_spec.rb +4 -4
  81. data/spec/unit/omnibus_spec.rb +4 -4
  82. data/spec/unit/package_spec.rb +6 -6
  83. data/spec/unit/packagers/appx_spec.rb +16 -12
  84. data/spec/unit/packagers/base_spec.rb +5 -5
  85. data/spec/unit/packagers/bff_spec.rb +45 -15
  86. data/spec/unit/packagers/deb_spec.rb +95 -17
  87. data/spec/unit/packagers/ips_spec.rb +61 -17
  88. data/spec/unit/packagers/makeself_spec.rb +5 -5
  89. data/spec/unit/packagers/msi_spec.rb +43 -43
  90. data/spec/unit/packagers/pkg_spec.rb +15 -15
  91. data/spec/unit/packagers/pkgsrc_spec.rb +77 -0
  92. data/spec/unit/packagers/rpm_spec.rb +94 -17
  93. data/spec/unit/packagers/solaris_spec.rb +11 -11
  94. data/spec/unit/project_spec.rb +53 -22
  95. data/spec/unit/publisher_spec.rb +2 -2
  96. data/spec/unit/publishers/artifactory_publisher_spec.rb +7 -3
  97. data/spec/unit/publishers/s3_publisher_spec.rb +1 -1
  98. data/spec/unit/s3_helpers_spec.rb +41 -3
  99. data/spec/unit/software_spec.rb +115 -37
  100. data/spec/unit/sugarable_spec.rb +23 -3
  101. data/spec/unit/util_spec.rb +42 -11
  102. metadata +49 -29
@@ -368,7 +368,7 @@ module Omnibus
368
368
  def build_version(val = NULL, &block)
369
369
  if block && !null?(val)
370
370
  raise Error, "You cannot specify additional parameters to " \
371
- '#build_version when a block is given!'
371
+ "#build_version when a block is given!"
372
372
  end
373
373
 
374
374
  if block
@@ -1034,7 +1034,7 @@ module Omnibus
1034
1034
  # @return [1, 0, -1]
1035
1035
  #
1036
1036
  def <=>(other)
1037
- self.name <=> other.name
1037
+ name <=> other.name
1038
1038
  end
1039
1039
 
1040
1040
  #
@@ -1076,6 +1076,9 @@ module Omnibus
1076
1076
  softwares.each do |software|
1077
1077
  software.build_me([license_collector])
1078
1078
  end
1079
+
1080
+ # If nothing has dirtied the cache, checkout the last cache dir
1081
+ restore_complete_build unless dirty?
1079
1082
  end
1080
1083
 
1081
1084
  write_json_manifest
@@ -1085,6 +1088,13 @@ module Omnibus
1085
1088
  compress_me
1086
1089
  end
1087
1090
 
1091
+ def restore_complete_build
1092
+ if Config.use_git_caching
1093
+ log.info(log_key) { "Cache not dirtied, restoring last marker" }
1094
+ GitCache.new(softwares.last).restore_from_cache
1095
+ end
1096
+ end
1097
+
1088
1098
  def write_json_manifest
1089
1099
  File.open(json_manifest_path, "w") do |f|
1090
1100
  f.write(FFI_Yajl::Encoder.encode(built_manifest.to_hash, pretty: true))
@@ -1189,7 +1199,7 @@ module Omnibus
1189
1199
  # @return [true, false]
1190
1200
  #
1191
1201
  def ==(other)
1192
- self.hash == other.hash
1202
+ hash == other.hash
1193
1203
  end
1194
1204
  alias_method :eql?, :==
1195
1205
 
@@ -138,12 +138,6 @@ module Omnibus
138
138
  name: "omnibus",
139
139
  version: Omnibus::VERSION,
140
140
  },
141
- properties: default_properties.merge(
142
- "omnibus.project" => name,
143
- "omnibus.version" => manifest.build_version,
144
- "omnibus.build_git_revision" => manifest.build_git_revision,
145
- "omnibus.license" => manifest.license
146
- ),
147
141
  modules: [
148
142
  {
149
143
  # com.getchef:chef-server:12.0.0
@@ -228,6 +222,10 @@ module Omnibus
228
222
  "omnibus.sha1" => package.metadata[:sha1],
229
223
  "omnibus.sha256" => package.metadata[:sha256],
230
224
  "omnibus.sha512" => package.metadata[:sha512],
225
+ "md5" => package.metadata[:md5],
226
+ "sha1" => package.metadata[:sha1],
227
+ "sha256" => package.metadata[:sha256],
228
+ "sha512" => package.metadata[:sha512],
231
229
  }.tap do |h|
232
230
  if build_record?
233
231
  h["build.name"] = package.metadata[:name]
@@ -46,12 +46,17 @@ module Omnibus
46
46
  private
47
47
 
48
48
  def s3_configuration
49
- {
49
+ config = {
50
50
  region: @options[:region],
51
- access_key_id: Config.publish_s3_access_key,
52
- secret_access_key: Config.publish_s3_secret_key,
53
51
  bucket_name: @options[:bucket],
54
52
  }
53
+
54
+ if Config.publish_s3_profile
55
+ config[:profile] = Config.publish_s3_profile
56
+ else
57
+ config[:access_key_id] = Config.publish_s3_access_key
58
+ config[:secret_access_key] = Config.publish_s3_secret_key
59
+ end
55
60
  end
56
61
 
57
62
  #
@@ -25,7 +25,7 @@ module Omnibus
25
25
  # will be stored in the column, the width is 0 (i.e., nothing
26
26
  # should be printed, not even the column header)
27
27
  def column_width(items, column_name)
28
- widest_item = items.max { |a, b| a.size <=> b.size }
28
+ widest_item = items.max_by(&:size)
29
29
  if widest_item
30
30
  widest = (widest_item.size >= column_name.size) ? widest_item : column_name
31
31
  widest.size + PADDING
@@ -132,15 +132,28 @@ module Omnibus
132
132
  "#{software.name}-#{software.version}-#{software.fetcher.checksum}"
133
133
  end
134
134
 
135
+ def url_for(software)
136
+ client.bucket(Config.s3_bucket).object(S3Cache.key_for(software)).public_url
137
+ end
138
+
135
139
  private
136
140
 
137
141
  def s3_configuration
138
- {
139
- region: Config.s3_region,
140
- access_key_id: Config.s3_access_key,
141
- secret_access_key: Config.s3_secret_key,
142
- bucket_name: Config.s3_bucket,
142
+ config = {
143
+ region: Config.s3_region,
144
+ bucket_name: Config.s3_bucket,
145
+ endpoint: Config.s3_endpoint,
146
+ use_accelerate_endpoint: Config.s3_accelerate,
143
147
  }
148
+
149
+ if Config.s3_profile
150
+ config[:profile] = Config.s3_profile
151
+ else
152
+ config[:access_key_id] = Config.s3_access_key,
153
+ config[:secret_access_key] = Config.s3_secret_key
154
+ end
155
+
156
+ config
144
157
  end
145
158
 
146
159
  #
@@ -15,6 +15,8 @@
15
15
  #
16
16
 
17
17
  require "aws-sdk"
18
+ require "aws-sdk-core/credentials"
19
+ require "aws-sdk-core/shared_credentials"
18
20
  require "base64"
19
21
 
20
22
  module Omnibus
@@ -32,10 +34,10 @@ module Omnibus
32
34
  #
33
35
  # @example
34
36
  # {
35
- # region: 'us-east-1',
36
- # access_key_id: Config.s3_access_key,
37
- # secret_access_key: Config.s3_secret_key,
38
- # bucket_name: Config.s3_bucket
37
+ # region: 'us-east-1',
38
+ # bucket_name: Config.s3_bucket,
39
+ # endpoint: Config.s3_endpoint,
40
+ # use_accelerate_endpoint: Config.s3_accelerate
39
41
  # }
40
42
  #
41
43
  # @return [Hash<String, String>]
@@ -50,11 +52,46 @@ module Omnibus
50
52
  # @return [Aws::S3::Resource]
51
53
  #
52
54
  def client
53
- @s3_client ||= Aws::S3::Resource.new(
54
- region: s3_configuration[:region],
55
- access_key_id: s3_configuration[:access_key_id],
56
- secret_access_key: s3_configuration[:secret_access_key]
55
+ Aws.config.update(
56
+ region: s3_configuration[:region],
57
+ credentials: get_credentials
57
58
  )
59
+
60
+ @s3_client ||= Aws::S3::Resource.new(resource_params)
61
+ end
62
+
63
+ #
64
+ # S3 Resource Parameters
65
+ #
66
+ # @return [Hash]
67
+ #
68
+ def resource_params
69
+ params = {
70
+ use_accelerate_endpoint: s3_configuration[:use_accelerate_endpoint],
71
+ }
72
+
73
+ if s3_configuration[:use_accelerate_endpoint]
74
+ params[:endpoint] = "https://s3-accelerate.amazonaws.com"
75
+ end
76
+
77
+ if s3_configuration[:endpoint]
78
+ params[:endpoint] = s3_configuration[:endpoint]
79
+ end
80
+
81
+ params
82
+ end
83
+
84
+ #
85
+ # Create credentials object based on credential profile or access key
86
+ # parameters for use by the client object.
87
+ #
88
+ # @return [Aws::SharedCredentials, Aws::Credentials]
89
+ def get_credentials
90
+ if s3_configuration[:profile]
91
+ Aws::SharedCredentials.new(profile_name: s3_configuration[:profile])
92
+ elsif s3_configuration[:access_key_id] && s3_configuration[:secret_access_key]
93
+ Aws::Credentials.new(s3_configuration[:access_key_id], s3_configuration[:secret_access_key])
94
+ end
58
95
  end
59
96
 
60
97
  #
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright 2012 Chef Software, Inc.
2
+ # Copyright 2012-2017, Chef Software Inc.
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -123,7 +123,7 @@ module Omnibus
123
123
  # @return [1, 0, -1]
124
124
  #
125
125
  def <=>(other)
126
- self.name <=> other.name
126
+ name <=> other.name
127
127
  end
128
128
 
129
129
  #
@@ -399,6 +399,39 @@ module Omnibus
399
399
  end
400
400
  expose :skip_transitive_dependency_licensing
401
401
 
402
+ #
403
+ # Set or retrieve licensing information of the dependencies.
404
+ # The information set is not validated or inspected. It is directly
405
+ # passed to LicenseScout.
406
+ #
407
+ # @example
408
+ # dependency_licenses [
409
+ # {
410
+ # dependency_name: "logstash-output-websocket",
411
+ # dependency_manager: "logstash_plugin",
412
+ # license: "Apache-2.0",
413
+ # license_file: [
414
+ # "relative/path/to/license/file",
415
+ # "https://download.elastic.co/logstash/LICENSE"
416
+ # ]
417
+ # },
418
+ # ...
419
+ # ]
420
+ #
421
+ # @param [Hash] val
422
+ # @param [Array<Hash>] val
423
+ # dependency license information.
424
+ # @return [Array<Hash>]
425
+ #
426
+ def dependency_licenses(val = NULL)
427
+ if null?(val)
428
+ @dependency_licenses || nil
429
+ else
430
+ @dependency_licenses = Array(val)
431
+ end
432
+ end
433
+ expose :dependency_licenses
434
+
402
435
  #
403
436
  # Evaluate a block only if the version matches.
404
437
  #
@@ -454,7 +487,7 @@ module Omnibus
454
487
  rescue ArgumentError
455
488
  log.warn(log_key) do
456
489
  "Version #{final_version} for software #{name} was not parseable. " \
457
- 'Comparison methods such as #satisfies? will not be available for this version.'
490
+ "Comparison methods such as #satisfies? will not be available for this version."
458
491
  end
459
492
  final_version
460
493
  end
@@ -644,7 +677,7 @@ module Omnibus
644
677
  # http://lists.gnu.org/archive/html/bug-libtool/2005-10/msg00004.html
645
678
  "CC" => "gcc -static-libgcc",
646
679
  "LDFLAGS" => "-R#{install_dir}/embedded/lib -L#{install_dir}/embedded/lib -static-libgcc",
647
- "CFLAGS" => "-I#{install_dir}/embedded/include",
680
+ "CFLAGS" => "-I#{install_dir}/embedded/include -O2",
648
681
  }
649
682
  elsif platform_version.satisfies?(">= 5.11")
650
683
  solaris_flags = {
@@ -670,6 +703,17 @@ module Omnibus
670
703
  freebsd_flags["CXX"] = "clang++"
671
704
  end
672
705
  freebsd_flags
706
+ when "suse"
707
+ suse_flags = {
708
+ "LDFLAGS" => "-Wl,-rpath,#{install_dir}/embedded/lib -L#{install_dir}/embedded/lib",
709
+ "CFLAGS" => "-I#{install_dir}/embedded/include -O2",
710
+ }
711
+ # Enable gcc version 4.8 if it is available
712
+ if which("gcc-4.8")
713
+ suse_flags["CC"] = "gcc-4.8"
714
+ suse_flags["CXX"] = "g++-4.8"
715
+ end
716
+ suse_flags
673
717
  when "windows"
674
718
  arch_flag = windows_arch_i386? ? "-m32" : "-m64"
675
719
  opt_flag = windows_arch_i386? ? "-march=i686" : "-march=x86-64"
@@ -684,13 +728,7 @@ module Omnibus
684
728
  # soon as gcc emits aligned SSE xmm register spills which generate
685
729
  # GPEs and terminate the application very rudely with very little
686
730
  # to debug with.
687
- #
688
- # TODO: This was true of our old TDM gcc 4.7 compilers. Is it still
689
- # true with mingw-w64?
690
- #
691
- # XXX: Temporarily turning -O3 into -O2 -fno-lto to work around some
692
- # weird linker issues.
693
- "CFLAGS" => "-I#{install_dir}/embedded/include #{arch_flag} -O2 -fno-lto #{opt_flag}",
731
+ "CFLAGS" => "-I#{install_dir}/embedded/include #{arch_flag} -O3 #{opt_flag}",
694
732
  }
695
733
  else
696
734
  {
@@ -737,7 +775,8 @@ module Omnibus
737
775
  merge({ "PKG_CONFIG_PATH" => "#{install_dir}/embedded/lib/pkgconfig" }).
738
776
  # Set default values for CXXFLAGS and CPPFLAGS.
739
777
  merge("CXXFLAGS" => compiler_flags["CFLAGS"]).
740
- merge("CPPFLAGS" => compiler_flags["CFLAGS"])
778
+ merge("CPPFLAGS" => compiler_flags["CFLAGS"]).
779
+ merge("OMNIBUS_INSTALL_DIR" => install_dir)
741
780
  end
742
781
  expose :with_standard_compiler_flags
743
782
 
@@ -920,6 +959,7 @@ module Omnibus
920
959
 
921
960
  @overrides
922
961
  end
962
+ expose :overrides
923
963
 
924
964
  #
925
965
  # Determine if this software version overridden externally, relative to the
@@ -996,9 +1036,9 @@ module Omnibus
996
1036
  def fetcher
997
1037
  @fetcher ||=
998
1038
  if source_type == :url && File.basename(source[:url], "?*").end_with?(*NetFetcher::ALL_EXTENSIONS)
999
- Fetcher.fetcher_class_for_source(self.source).new(manifest_entry, fetch_dir, build_dir)
1039
+ Fetcher.fetcher_class_for_source(source).new(manifest_entry, fetch_dir, build_dir)
1000
1040
  else
1001
- Fetcher.fetcher_class_for_source(self.source).new(manifest_entry, project_dir, build_dir)
1041
+ Fetcher.fetcher_class_for_source(source).new(manifest_entry, project_dir, build_dir)
1002
1042
  end
1003
1043
  end
1004
1044
 
@@ -1080,7 +1120,7 @@ module Omnibus
1080
1120
  # @return [true, false]
1081
1121
  #
1082
1122
  def ==(other)
1083
- self.hash == other.hash
1123
+ hash == other.hash
1084
1124
  end
1085
1125
  alias_method :eql?, :==
1086
1126
 
@@ -1124,28 +1164,6 @@ module Omnibus
1124
1164
  @git_cache ||= GitCache.new(self)
1125
1165
  end
1126
1166
 
1127
- #
1128
- # The proper platform-specific "$PATH" key.
1129
- #
1130
- # @return [String]
1131
- #
1132
- def path_key
1133
- # The ruby devkit needs ENV['Path'] set instead of ENV['PATH'] because
1134
- # $WINDOWSRAGE, and if you don't set that your native gem compiles
1135
- # will fail because the magic fixup it does to add the mingw compiler
1136
- # stuff won't work.
1137
- #
1138
- # Turns out there is other build environments that only set ENV['PATH'] and if we
1139
- # modify ENV['Path'] then it ignores that. So, we scan ENV and returns the first
1140
- # one that we find.
1141
- #
1142
- if Ohai["platform"] == "windows"
1143
- ENV.keys.grep(/\Apath\Z/i).first
1144
- else
1145
- "PATH"
1146
- end
1147
- end
1148
-
1149
1167
  #
1150
1168
  # Apply overrides in the @overrides hash that mask instance variables
1151
1169
  # that are set by parsing the DSL
@@ -67,5 +67,9 @@ module Omnibus
67
67
  def windows_arch_i386?
68
68
  Config.windows_arch.to_sym == :x86
69
69
  end
70
+
71
+ def fips_mode?
72
+ !!Config.fips_mode
73
+ end
70
74
  end
71
75
  end
@@ -13,7 +13,6 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
  #
16
-
17
16
  require "erb"
18
17
 
19
18
  module Omnibus
@@ -23,6 +22,32 @@ module Omnibus
23
22
  base.send(:include, Logging)
24
23
  end
25
24
 
25
+ #
26
+ # Render an erb template to a String variable.
27
+ #
28
+ # @return [String]
29
+ #
30
+ # @param [String] source
31
+ # the path on disk where the ERB template lives
32
+ #
33
+ # @option options [Fixnum] :mode (default: +0644+)
34
+ # the mode of the rendered file
35
+ # @option options [Hash] :variables (default: +{}+)
36
+ # the list of variables to pass to the template
37
+ #
38
+ def render_template_content(source, variables = {})
39
+ template = ERB.new(File.read(source), nil, "-")
40
+
41
+ struct =
42
+ if variables.empty?
43
+ Struct.new("Empty")
44
+ else
45
+ Struct.new(*variables.keys).new(*variables.values)
46
+ end
47
+
48
+ template.result(struct.instance_eval { binding })
49
+ end
50
+
26
51
  #
27
52
  # Render an erb template on disk at +source+. If the +:destination+ option
28
53
  # is given, the file will be rendered at +:destination+, otherwise the
@@ -41,8 +66,7 @@ module Omnibus
41
66
  #
42
67
  def render_template(source, options = {})
43
68
  destination = options.delete(:destination) || source.chomp(".erb")
44
-
45
- mode = options.delete(:mode) || 0644
69
+ mode = options.delete(:mode) || 0644
46
70
  variables = options.delete(:variables) || {}
47
71
 
48
72
  log.info(log_key) { "Rendering `#{source}' to `#{destination}'" }
@@ -52,16 +76,8 @@ module Omnibus
52
76
  "Unknown option(s): #{options.keys.map(&:inspect).join(', ')}"
53
77
  end
54
78
 
55
- template = ERB.new(File.read(source), nil, "-")
56
-
57
- struct =
58
- if variables.empty?
59
- Struct.new("Empty")
60
- else
61
- Struct.new(*variables.keys).new(*variables.values)
62
- end
63
-
64
- result = template.result(struct.instance_eval { binding })
79
+ # String value returned from #render_template_content
80
+ result = render_template_content(source, variables)
65
81
 
66
82
  File.open(destination, "w", mode) do |file|
67
83
  file.write(result)