omnibus 4.0.0.beta.1 → 4.0.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -0
  3. data/docs/Building on RHEL.md +1 -0
  4. data/lib/omnibus/builder.rb +48 -1
  5. data/lib/omnibus/config.rb +13 -0
  6. data/lib/omnibus/digestable.rb +2 -2
  7. data/lib/omnibus/exceptions.rb +21 -0
  8. data/lib/omnibus/fetchers/git_fetcher.rb +75 -9
  9. data/lib/omnibus/fetchers/net_fetcher.rb +5 -3
  10. data/lib/omnibus/generator.rb +0 -13
  11. data/{resources/bff/postinstall.sh → lib/omnibus/generator_files/package_scripts/makeselfinst.erb} +0 -0
  12. data/lib/omnibus/packagers/base.rb +25 -1
  13. data/lib/omnibus/packagers/bff.rb +99 -12
  14. data/lib/omnibus/packagers/deb.rb +10 -8
  15. data/lib/omnibus/packagers/makeself.rb +24 -16
  16. data/lib/omnibus/packagers/msi.rb +6 -5
  17. data/lib/omnibus/packagers/pkg.rb +59 -10
  18. data/lib/omnibus/packagers/rpm.rb +42 -25
  19. data/lib/omnibus/packagers/solaris.rb +5 -5
  20. data/lib/omnibus/project.rb +54 -5
  21. data/lib/omnibus/software.rb +37 -39
  22. data/lib/omnibus/version.rb +1 -1
  23. data/omnibus.gemspec +1 -0
  24. data/resources/bff/gen.template.erb +3 -2
  25. data/resources/rpm/signing.erb +1 -1
  26. data/spec/functional/builder_spec.rb +75 -3
  27. data/spec/functional/fetchers/git_fetcher_spec.rb +31 -2
  28. data/spec/support/examples.rb +8 -2
  29. data/spec/support/git_helpers.rb +8 -0
  30. data/spec/unit/builder_spec.rb +6 -0
  31. data/spec/unit/config_spec.rb +1 -0
  32. data/spec/unit/generator_spec.rb +0 -12
  33. data/spec/unit/packagers/base_spec.rb +16 -0
  34. data/spec/unit/packagers/bff_spec.rb +58 -5
  35. data/spec/unit/packagers/deb_spec.rb +15 -3
  36. data/spec/unit/packagers/makeself_spec.rb +56 -9
  37. data/spec/unit/packagers/pkg_spec.rb +57 -4
  38. data/spec/unit/packagers/rpm_spec.rb +38 -23
  39. data/spec/unit/project_spec.rb +16 -5
  40. data/spec/unit/software_spec.rb +0 -1
  41. metadata +18 -6
  42. data/resources/bff/unpostinstall.sh +0 -0
  43. data/resources/makeself/post_extract.sh.erb +0 -27
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dec9872ce88998ffa0792cb936e9f81a5955c5f3
4
- data.tar.gz: 114a41ab14dc94359e1efb6a8f1f6e375031438e
3
+ metadata.gz: f6839ae316c6146ee459f8acbd869d83d495d90c
4
+ data.tar.gz: 30a70eb80420dbab5e8196eb1a626b7b62c7b65f
5
5
  SHA512:
6
- metadata.gz: e3cf0b1538b35bb9750427bab3c3779d1355c491e55ac889b81f4b970e85657c2053ec0a6872fd9318e82be70561b77cb354added176c59b6e3b11d536a1dc43
7
- data.tar.gz: f551ee709ea94e53af2a6b0bc5e09c7e144a686eab51c692fdbc84f74e13b17bd588c4d2c8fc779ec9bf912784583919edadc09d2120f2f94e1554b4e504437f
6
+ metadata.gz: 4b8c99b56cd409f5b4df98dea2e19ade09fdeac89e42ee53a3724cf0a1c6440430d9994fd41b36aecd68c1c9239709bf578590b46ad1602f4fc2a6fbb21e3ba4
7
+ data.tar.gz: d07dbc0bcab759ecc4f6017d71e662cd07d81ff7919854fd790fe4ec476eacdf11f8eb8a8163d2005808d8618d947d791df6f62da8e620f5cf009647bef685f9
@@ -1,6 +1,35 @@
1
1
  Omnibus CHANGELOG
2
2
  =================
3
3
 
4
+ v4.0.0.rc.1 (September 23, 2014)
5
+ --------------------------------
6
+
7
+ ### New Features
8
+ - Expose `build_version` to all `pkg` templates
9
+ - Improve info messages during RPM creation
10
+ - Make PKG packager aware of scripts with default Omnibus naming
11
+ - Make RPM packager aware of scripts with default Omnibus naming
12
+ - Clean up script logic in BFF packager
13
+ - Add an option for configuring Fetcher read timeout
14
+
15
+ ### DSL Changes
16
+ #### Builder
17
+ - Add an `appbundle` function to the builder DSL
18
+
19
+ #### Packager
20
+ - Expose `install_dir` in Packager DSL
21
+ - Expose `windows_safe_path` in Packager DSL
22
+
23
+ ### Bugfixes
24
+ - Replace dashes with underscores in RPM version names.
25
+ - The achitecture of deb package is i386, not i686.
26
+ - Re-ignore 204 exit code from `light.exe`
27
+ - Use single quotes in main `rpmbuild` command
28
+ - Be sure to create and sign the RPM if `~/.rpmmacros` exists
29
+ - Switch to OpenSSL::Digest which is threadsafe on 2.1.2
30
+ - Ensure `GitFetcher` properly resolves remote refs
31
+ - Ensure we clean ALL Ruby environment vars
32
+
4
33
  v4.0.0.beta.1 (August 20, 2014)
5
34
  -------------------------------
6
35
  ### New Features
@@ -19,6 +19,7 @@ The following Project values are taken into consideration when building RPMs:
19
19
  - `extra_package_files`
20
20
  - `iteration`
21
21
  - `maintainer`
22
+ - `package_name`
22
23
  - `package_user`
23
24
  - `package_group`
24
25
  - `package_scripts_path`
@@ -261,6 +261,46 @@ module Omnibus
261
261
  end
262
262
  expose :bundle
263
263
 
264
+ #
265
+ # Execute the given appbundler command against the embedded Ruby's
266
+ # appbundler. This command assumes the +appbundle+ gem is installed and
267
+ # in the embedded Ruby. You should add a dependency on the +appbundler+
268
+ # software definition if you want to use this command.
269
+ #
270
+ # @example
271
+ # appbundle 'chef'
272
+ #
273
+ # @param (see #command)
274
+ # @return (see #command)
275
+ #
276
+ def appbundle(app_name, options = {})
277
+ build_commands << BuildCommand.new("appbundle `#{app_name}'") do
278
+ bin_dir = "#{install_dir}/bin"
279
+ embedded_apps_root = "#{install_dir}/embedded/apps"
280
+ embedded_app_dir = "#{embedded_apps_root}/#{app_name}"
281
+ gemfile_lock = "#{embedded_app_dir}/Gemfile.lock"
282
+ appbundler_bin = windows_safe_path("#{install_dir}/embedded/bin/appbundler")
283
+
284
+ # Ensure the main bin dir exists
285
+ FileUtils.mkdir_p(bin_dir)
286
+ # Ensure the embedded app directory exists
287
+ FileUtils.mkdir_p(embedded_apps_root)
288
+ # Copy the application code into place
289
+ FileUtils.cp_r("#{Omnibus::Config.source_dir}/#{app_name}", embedded_apps_root)
290
+ # Delete any top-level `.git` directory
291
+ FileUtils.rm_rf("#{embedded_app_dir}/.git")
292
+
293
+ # Prepare the environment
294
+ options[:env] ||= {}
295
+ env = with_embedded_path || {}
296
+ env["BUNDLE_GEMFILE"] = gemfile_lock
297
+ options[:env].merge!(env)
298
+
299
+ shellout!("#{appbundler_bin} '#{embedded_app_dir}' '#{bin_dir}'", options)
300
+ end
301
+ end
302
+ expose :appbundle
303
+
264
304
  #
265
305
  # Execute the given Rake command against the embedded Ruby's rake. This
266
306
  # command assumes the +rake+ gem has been installed.
@@ -704,11 +744,17 @@ module Omnibus
704
744
  # which only removes Bundler-specific values. We need to remove all
705
745
  # values, specifically:
706
746
  #
747
+ # - _ORIGINAL_GEM_PATH
707
748
  # - GEM_PATH
708
749
  # - GEM_HOME
709
750
  # - GEM_ROOT
751
+ # - BUNDLE_BIN_PATH
710
752
  # - BUNDLE_GEMFILE
753
+ # - RUBYLIB
711
754
  # - RUBYOPT
755
+ # - RUBY_ENGINE
756
+ # - RUBY_ROOT
757
+ # - RUBY_VERSION
712
758
  #
713
759
  # The original environment restored at the end of this call.
714
760
  #
@@ -718,9 +764,10 @@ module Omnibus
718
764
  def with_clean_env(&block)
719
765
  original = ENV.to_hash
720
766
 
721
- ENV.delete('RUBYOPT')
767
+ ENV.delete('_ORIGINAL_GEM_PATH')
722
768
  ENV.delete_if { |k,_| k.start_with?('BUNDLE_') }
723
769
  ENV.delete_if { |k,_| k.start_with?('GEM_') }
770
+ ENV.delete_if { |k,_| k.start_with?('RUBY') }
724
771
 
725
772
  block.call
726
773
  ensure
@@ -466,6 +466,19 @@ module Omnibus
466
466
  # @!endgroup
467
467
  #
468
468
 
469
+ #
470
+ # @!group Fetcher Parameters
471
+ # --------------------------------------------------
472
+
473
+ # The number of seconds to wait
474
+ #
475
+ # @return [Integer]
476
+ default(:fetcher_read_timeout, 60)
477
+
478
+ # --------------------------------------------------
479
+ # @!endgroup
480
+ #
481
+
469
482
  private
470
483
 
471
484
  #
@@ -14,7 +14,7 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
- require 'digest'
17
+ require 'openssl'
18
18
  require 'pathname'
19
19
 
20
20
  module Omnibus
@@ -96,7 +96,7 @@ module Omnibus
96
96
  #
97
97
  def digest_from_type(type)
98
98
  id = type.to_s.upcase
99
- instance = Digest.const_get(id).new
99
+ instance = OpenSSL::Digest.const_get(id).new
100
100
  end
101
101
 
102
102
  #
@@ -285,6 +285,27 @@ The following shell command timed out at #{timeout} seconds:
285
285
  Please increase the `:timeout' value or run the command manually to make sure it
286
286
  is completing successfully. Sometimes it is common for a command to wait for
287
287
  user input.
288
+ EOH
289
+ end
290
+ end
291
+
292
+ class ProjectAlreadyDirty < Error
293
+ def initialize(project)
294
+ name = project.name
295
+ culprit = project.culprit.name
296
+
297
+ super <<-EOH
298
+ The project `#{name}' was already marked as dirty by `#{culprit}'. You cannot
299
+ mark a project as dirty twice. This is probably a bug in Omnibus and should be
300
+ reported.
301
+ EOH
302
+ end
303
+ end
304
+
305
+ class UnresolvableGitReference < Error
306
+ def initialize(ref)
307
+ super <<-EOH
308
+ Could not resolve `#{ref}' to a valid git SHA-1.
288
309
  EOH
289
310
  end
290
311
  end
@@ -146,15 +146,11 @@ module Omnibus
146
146
  # @return [String]
147
147
  #
148
148
  def target_revision
149
- @target_revision ||= git("rev-parse #{version}").stdout.strip
150
- rescue CommandFailed => e
151
- if e.message.include?('ambiguous argument')
152
- @target_revision = git("rev-parse origin/#{version}").stdout.strip
153
- @target_revision
154
- else
155
- log.warn { 'Could not determine target revision!' }
156
- nil
157
- end
149
+ @target_revision ||= if sha_hash?(version)
150
+ version
151
+ else
152
+ revision_from_remote_reference(version)
153
+ end
158
154
  end
159
155
 
160
156
  #
@@ -166,6 +162,76 @@ module Omnibus
166
162
  current_revision == target_revision
167
163
  end
168
164
 
165
+ #
166
+ # Determine if the given revision is a SHA
167
+ #
168
+ # @return [true, false]
169
+ #
170
+ def sha_hash?(rev)
171
+ rev =~ /^[0-9a-f]{4,40}$/
172
+ end
173
+
174
+ #
175
+ # Return the SHA corresponding to ref. If ref is an annotated tag,
176
+ # return the SHA that was tagged not the SHA of the tag itself.
177
+ #
178
+ # @return [String]
179
+ #
180
+ def revision_from_remote_reference(ref)
181
+ # execute `git ls-remote` the trailing '*' does globbing. This
182
+ # allows us to return the SHA of the tagged commit for annotated
183
+ # tags. We take care to only return exact matches in
184
+ # process_remote_list.
185
+ remote_list = git("ls-remote origin #{ref}*").stdout
186
+ commit_ref = dereference_annotated_tag(remote_list, ref)
187
+
188
+ unless commit_ref
189
+ raise UnresolvableGitReference.new(ref)
190
+ end
191
+ commit_ref
192
+ end
193
+
194
+ #
195
+ # Dereference annotated tags.
196
+ #
197
+ # The +remote_list+ parameter is assumed to look like this:
198
+ #
199
+ # a2ed66c01f42514bcab77fd628149eccb4ecee28 refs/tags/rel-0.11.0
200
+ # f915286abdbc1907878376cce9222ac0b08b12b8 refs/tags/rel-0.11.0^{}
201
+ #
202
+ # The SHA with ^{} is the commit pointed to by an annotated
203
+ # tag. If ref isn't an annotated tag, there will not be a line
204
+ # with trailing ^{}.
205
+ #
206
+ # @param [String] remote_list
207
+ # output from `git ls-remote origin` command
208
+ # @param [String] ref
209
+ # the target git ref
210
+ #
211
+ # @return [String]
212
+ #
213
+ def dereference_annotated_tag(remote_list, ref)
214
+ # We'll return the SHA corresponding to the ^{} which is the
215
+ # commit pointed to by an annotated tag. If no such commit
216
+ # exists (not an annotated tag) then we return the SHA of the
217
+ # ref. If nothing matches, return "".
218
+ lines = remote_list.split("\n")
219
+ matches = lines.map { |line| line.split("\t") }
220
+ # First try for ^{} indicating the commit pointed to by an
221
+ # annotated tag.
222
+ tagged_commit = matches.find { |m| m[1].end_with?("#{ref}^{}") }
223
+ if tagged_commit
224
+ tagged_commit.first
225
+ else
226
+ found = matches.find { |m| m[1].end_with?("#{ref}") }
227
+ if found
228
+ found.first
229
+ else
230
+ nil
231
+ end
232
+ end
233
+ end
234
+
169
235
  #
170
236
  # Execute the given git command, inside the +project_dir+.
171
237
  #
@@ -139,14 +139,16 @@ module Omnibus
139
139
  def download
140
140
  log.warn(log_key) { source[:warning] } if source.key?(:warning)
141
141
 
142
- headers = download_headers
142
+ options = download_headers
143
143
 
144
144
  if source[:unsafe]
145
145
  log.warn(log_key) { "Permitting unsafe redirects!" }
146
- headers[:allow_unsafe_redirects] = true
146
+ options[:allow_unsafe_redirects] = true
147
147
  end
148
148
 
149
- file = open(download_url, headers)
149
+ options[:read_timeout] = Omnibus::Config.fetcher_read_timeout
150
+
151
+ file = open(download_url, options)
150
152
  FileUtils.cp(file.path, downloaded_file)
151
153
  file.close
152
154
  rescue SocketError,
@@ -50,11 +50,6 @@ module Omnibus
50
50
  type: :boolean,
51
51
  default: false
52
52
 
53
- class_option :makeself_assets,
54
- desc: 'Generate makeself assets',
55
- type: :boolean,
56
- default: false
57
-
58
53
  class_option :msi_assets,
59
54
  desc: 'Generate Windows MSI assets',
60
55
  type: :boolean,
@@ -112,8 +107,6 @@ module Omnibus
112
107
  return unless options[:bff_assets]
113
108
 
114
109
  copy_file(resource_path('bff/gen.template.erb'), "#{target}/resources/bff/gen.template.erb")
115
- copy_file(resource_path('bff/postinstall.sh'), "#{target}/resources/bff/postinstall.sh")
116
- copy_file(resource_path('bff/unpostinstall.sh'), "#{target}/resources/bff/unpostinstall.sh")
117
110
  end
118
111
 
119
112
  def create_deb_assets
@@ -131,12 +124,6 @@ module Omnibus
131
124
  copy_file(resource_path('dmg/icon.png'), "#{target}/resources/dmg/icon.png")
132
125
  end
133
126
 
134
- def create_makeself_assets
135
- return unless options[:makeself_assets]
136
-
137
- copy_file(resource_path('makeself/post_extract.sh.erb'), "#{target}/resources/makeself/post_extract.sh.erb")
138
- end
139
-
140
127
  def create_msi_assets
141
128
  return unless options[:msi_assets]
142
129
 
@@ -105,6 +105,30 @@ module Omnibus
105
105
  )
106
106
  end
107
107
 
108
+ #
109
+ # @!group DSL methods
110
+ # --------------------------------------------------
111
+
112
+ #
113
+ # Retrieve the path at which the project will be installed by the
114
+ # generated package.
115
+ #
116
+ # @return [String]
117
+ #
118
+ def install_dir
119
+ project.install_dir
120
+ end
121
+ expose :install_dir
122
+
123
+ #
124
+ # (see Util#windows_safe_path)
125
+ #
126
+ expose :windows_safe_path
127
+
128
+ #
129
+ # @!endgroup
130
+ # --------------------------------------------------
131
+
108
132
  #
109
133
  # Execute this packager by running the following phases in order:
110
134
  #
@@ -149,7 +173,7 @@ module Omnibus
149
173
  # @return [String]
150
174
  #
151
175
  def staging_dir
152
- @staging_dir ||= Dir.mktmpdir(project.name)
176
+ @staging_dir ||= Dir.mktmpdir(project.package_name)
153
177
  end
154
178
 
155
179
  #
@@ -16,6 +16,15 @@
16
16
 
17
17
  module Omnibus
18
18
  class Packager::BFF < Packager::Base
19
+ # @return [Hash]
20
+ SCRIPT_MAP = {
21
+ # Default Omnibus naming
22
+ preinst: 'Pre-installation Script',
23
+ postinst: 'Post-installation Script',
24
+ prerm: 'Pre_rm Script',
25
+ postrm: 'Unconfiguration Script',
26
+ }.freeze
27
+
19
28
  id :bff
20
29
 
21
30
  setup do
@@ -25,6 +34,9 @@ module Omnibus
25
34
  # /opt/hamlet => /tmp/daj29013/opt/hamlet
26
35
  destination = File.join(staging_dir, project.install_dir)
27
36
  FileSyncer.sync(project.install_dir, destination, exclude: exclusions)
37
+
38
+ # Create the scripts staging directory
39
+ create_directory(scripts_staging_dir)
28
40
  end
29
41
 
30
42
  build do
@@ -37,7 +49,42 @@ module Omnibus
37
49
 
38
50
  # @see Base#package_name
39
51
  def package_name
40
- "#{project.name}.#{bff_version}.#{safe_architecture}.bff"
52
+ "#{safe_base_package_name}.#{bff_version}.#{safe_architecture}.bff"
53
+ end
54
+
55
+ #
56
+ # The path where the package scripts in the install directory.
57
+ #
58
+ # @return [String]
59
+ #
60
+ def scripts_install_dir
61
+ File.expand_path("#{project.install_dir}/embedded/share/installp")
62
+ end
63
+
64
+ #
65
+ # The path where the package scripts will staged.
66
+ #
67
+ # @return [String]
68
+ #
69
+ def scripts_staging_dir
70
+ File.expand_path("#{staging_dir}#{scripts_install_dir}")
71
+ end
72
+
73
+ #
74
+ # Copy all scripts in {Project#package_scripts_path} to the package
75
+ # directory.
76
+ #
77
+ # @return [void]
78
+ #
79
+ def write_scripts
80
+ SCRIPT_MAP.each do |script, _installp_name|
81
+ source_path = File.join(project.package_scripts_path, script.to_s)
82
+
83
+ if File.file?(source_path)
84
+ log.debug(log_key) { "Adding script `#{script}' to `#{scripts_staging_dir}'" }
85
+ copy_file(source_path, scripts_staging_dir)
86
+ end
87
+ end
41
88
  end
42
89
 
43
90
  #
@@ -45,7 +92,50 @@ module Omnibus
45
92
  #
46
93
  # @return [void]
47
94
  #
95
+ # Some details on the various lifecycle scripts:
96
+ #
97
+ # The order of the installp scripts is:
98
+ # - install
99
+ # - pre-install
100
+ # - post-install
101
+ # - config
102
+ # - upgrade
103
+ # - pre-remove (of previous version)
104
+ # - pre-install (previous version of software not present anymore)
105
+ # - post-install
106
+ # - config
107
+ # - remove
108
+ # - unconfig
109
+ # - unpre-install
110
+ #
111
+ # To run the new version of scc, the post-install will do.
112
+ # To run the previous version with an upgrade, use the pre-remove script.
113
+ # To run a source install of scc upon installation of installp package, use the pre-install.
114
+ # Upon upgrade, both the pre-remove and the pre-install scripts will run.
115
+ # As scc has been removed between the runs of these scripts, it will only run once during upgrade.
116
+ #
117
+ # Keywords for scripts:
118
+ #
119
+ # Pre-installation Script: /path/script
120
+ # Unpre-installation Script: /path/script
121
+ # Post-installation Script: /path/script
122
+ # Pre_rm Script: /path/script
123
+ # Configuration Script: /path/script
124
+ # Unconfiguration Script: /path/script
125
+ #
48
126
  def write_gen_template
127
+ # Create a map of scripts that exist and install path
128
+ scripts = SCRIPT_MAP.inject({}) do |hash, (script, installp_key)|
129
+ staging_path = File.join(scripts_staging_dir, script.to_s)
130
+ install_path = File.join(scripts_install_dir, script.to_s)
131
+
132
+ if File.file?(staging_path)
133
+ hash[installp_key] = install_path
134
+ end
135
+
136
+ hash
137
+ end
138
+
49
139
  # Get a list of all files
50
140
  files = FileSyncer.glob("#{staging_dir}/**/*")
51
141
  .map { |path| path.gsub(/^#{staging_dir}/, '') }
@@ -53,16 +143,13 @@ module Omnibus
53
143
  render_template(resource_path('gen.template.erb'),
54
144
  destination: File.join(staging_dir, 'gen.template'),
55
145
  variables: {
56
- name: safe_project_name,
146
+ name: safe_base_package_name,
57
147
  install_dir: project.install_dir,
58
148
  friendly_name: project.friendly_name,
59
149
  version: bff_version,
60
150
  description: project.description,
61
151
  files: files,
62
-
63
- # Add configuration files
64
- configuration_script: resource_path('postinstall.sh'),
65
- unconfiguration_script: resource_path('unpostinstall.sh'),
152
+ scripts: scripts,
66
153
  }
67
154
  )
68
155
  end
@@ -87,21 +174,21 @@ module Omnibus
87
174
  end
88
175
 
89
176
  #
90
- # Return the BFF-ready project name, converting any invalid characters to
177
+ # Return the BFF-ready base package name, converting any invalid characters to
91
178
  # dashes (+-+).
92
179
  #
93
180
  # @return [String]
94
181
  #
95
- def safe_project_name
96
- if project.name =~ /\A[a-z0-9\.\+\-]+\z/
97
- project.name.dup
182
+ def safe_base_package_name
183
+ if project.package_name =~ /\A[a-z0-9\.\+\-]+\z/
184
+ project.package_name.dup
98
185
  else
99
- converted = project.name.downcase.gsub(/[^a-z0-9\.\+\-]+/, '-')
186
+ converted = project.package_name.downcase.gsub(/[^a-z0-9\.\+\-]+/, '-')
100
187
 
101
188
  log.warn(log_key) do
102
189
  "The `name' compontent of BFF package names can only include " \
103
190
  "lowercase alphabetical characters (a-z), numbers (0-9), dots (.), " \
104
- "plus signs (+), and dashes (-). Converting `#{project.name}' to " \
191
+ "plus signs (+), and dashes (-). Converting `#{project.package_name}' to " \
105
192
  "`#{converted}'."
106
193
  end
107
194