class Omnibus::Packager::DEB

Public Instance Methods

compression_level(val = NULL) click to toggle source

Compression level (1-9) to use (-Z).

@example

compression_level 1

@param [Integer] val

level of compression (1, .., 9)

@return [Integer]

level of compression for this package
# File lib/omnibus/packagers/deb.rb, line 231
def compression_level(val = NULL)
  if null?(val)
    @compression_level || 9
  else
    unless val.is_a?(Integer) && 1 <= val && 9 >= val
      raise InvalidValue.new(:compression_level, "be an Integer between 1 and 9")
    end

    @compression_level = val
  end
end
compression_params() click to toggle source

Return the parameters passed to dpkg-deb for setting the compression according to configuration.

@return [String]

# File lib/omnibus/packagers/deb.rb, line 406
def compression_params
  if compression_strategy
    "-z#{compression_level} -Z#{compression_type} -S#{compression_strategy}"
  else
    "-z#{compression_level} -Z#{compression_type}"
  end
end
compression_strategy(val = NULL) click to toggle source

Compression strategy to use (-Z). For gzip: :filtered, :huffman, :rle, or :fixed; for xz: :extreme (nil means parameter will not be passsed to dpkg-deb)

@example

compression_strategy :extreme

@param [Symbol] val

compression strategy

@return [Symbol]

compression strategy for this package
# File lib/omnibus/packagers/deb.rb, line 259
def compression_strategy(val = NULL)
  if null?(val)
    @compression_strategy
  else
    unless val.is_a?(Symbol) &&
        %i{filtered huffman rle fixed extreme}.member?(val)
      raise InvalidValue.new(:compression_strategy, "be a Symbol (:filtered, "\
                                                    ":huffman, :rle, :fixed, or :extreme)")
    end

    @compression_strategy = val
  end
end
compression_type(val = NULL) click to toggle source

Compression algorithm (gzip, xz, none) to use (-Z).

@example

compression_type :xz

@param [Symbol] val

type of compression (:gzip, :xz, :none)

@return [Symbol]

type of compression for this package
# File lib/omnibus/packagers/deb.rb, line 206
def compression_type(val = NULL)
  if null?(val)
    @compression_type || :gzip
  else
    unless val.is_a?(Symbol) && %i{gzip xz none}.member?(val)
      raise InvalidValue.new(:compression_type, "be a Symbol (:gzip, :xz, or :none)")
    end

    @compression_type = val
  end
end
create_deb_file() click to toggle source

Create the .deb file, compressing at gzip level 9. The use of the fakeroot command is required so that the package is owned by root:root, but the build user does not need to have sudo permissions.

@return [void]

# File lib/omnibus/packagers/deb.rb, line 391
def create_deb_file
  log.info(log_key) { "Creating .deb file" }

  # Execute the build command
  Dir.chdir(Config.package_dir) do
    shellout!("fakeroot dpkg-deb #{compression_params} -D --build #{staging_dir} #{package_name}")
  end
end
debian_dir() click to toggle source

The path where Debian-specific files will live.

@example

/var/.../chef-server_11.12.4/DEBIAN

@return [String]

# File lib/omnibus/packagers/deb.rb, line 294
def debian_dir
  @debian_dir ||= File.join(staging_dir, "DEBIAN")
end
license(val = NULL) click to toggle source

Set or return the license for this package.

@example

license "Apache 2.0"

@param [String] val

the license for this package

@return [String]

the license for this package
# File lib/omnibus/packagers/deb.rb, line 131
def license(val = NULL)
  if null?(val)
    @license || project.license
  else
    unless val.is_a?(String)
      raise InvalidValue.new(:license, "be a String")
    end

    @license = val
  end
end
package_name() click to toggle source

The name of the package to create. Note, this does not include the extension.

# File lib/omnibus/packagers/deb.rb, line 282
def package_name
  "#{safe_base_package_name}_#{safe_version}-#{safe_build_iteration}_#{safe_architecture}.deb"
end
package_size() click to toggle source

The size of this Debian package. This is dynamically calculated.

@return [Fixnum]

# File lib/omnibus/packagers/deb.rb, line 475
def package_size
  @package_size ||= begin
    path  = "#{project.install_dir}/**/*"
    total = FileSyncer.glob(path).inject(0) do |size, path|
      unless File.directory?(path) || File.symlink?(path)
        size += File.size(path)
      end

      size
    end

    # Per http://www.debian.org/doc/debian-policy/ch-controlfields.html, the
    # disk space is given as the integer value of the estimated installed
    # size in bytes, divided by 1024 and rounded up.
    total / 1024
  end
end
priority(val = NULL) click to toggle source

Set or return the priority for this package.

@example

priority "extra"

@param [String] val

the priority for this package

@return [String]

the priority for this package
# File lib/omnibus/packagers/deb.rb, line 156
def priority(val = NULL)
  if null?(val)
    @priority || "extra"
  else
    unless val.is_a?(String)
      raise InvalidValue.new(:priority, "be a String")
    end

    @priority = val
  end
end
safe_architecture() click to toggle source

Debian does not follow the standards when naming 64-bit packages.

@return [String]

# File lib/omnibus/packagers/deb.rb, line 571
def safe_architecture
  @safe_architecture ||= shellout!("dpkg --print-architecture").stdout.split("\n").first || "noarch"
end
safe_base_package_name() click to toggle source

Return the Debian-ready base package name, converting any invalid characters to dashes (-).

@return [String]

# File lib/omnibus/packagers/deb.rb, line 499
def safe_base_package_name
  if project.package_name =~ /\A[a-z0-9\.\+\-]+\z/
    project.package_name.dup
  else
    converted = project.package_name.downcase.gsub(/[^a-z0-9\.\+\-]+/, "-")

    log.warn(log_key) do
      "The `name' component of Debian package names can only include " \
      "lower case alphabetical characters (a-z), numbers (0-9), dots (.), " \
      "plus signs (+), and dashes (-). Converting `#{project.package_name}' to " \
      "`#{converted}'."
    end

    converted
  end
end
safe_build_iteration() click to toggle source

This is actually just the regular build_iteration, but it felt lonely among all the other safe_* methods.

@return [String]

# File lib/omnibus/packagers/deb.rb, line 522
def safe_build_iteration
  project.build_iteration
end
safe_version() click to toggle source

Return the Debian-ready version, replacing all dashes (-) with tildes (+~+) and converting any invalid characters to underscores (_).

@return [String]

# File lib/omnibus/packagers/deb.rb, line 532
def safe_version
  version = project.build_version.dup

  if version =~ /\-/
    converted = version.tr("-", "~")

    log.warn(log_key) do
      "Dashes hold special significance in the Debian package versions. " \
      "Versions that contain a dash and should be considered an earlier " \
      "version (e.g. pre-releases) may actually be ordered as later " \
      "(e.g. 12.0.0-rc.6 > 12.0.0). We'll work around this by replacing " \
      "dashes (-) with tildes (~). Converting `#{project.build_version}' " \
      "to `#{converted}'."
    end

    version = converted
  end

  if version =~ /\A[a-zA-Z0-9\.\+\:\~]+\z/
    version
  else
    converted = version.gsub(/[^a-zA-Z0-9\.\+\:\~]+/, "_")

    log.warn(log_key) do
      "The `version' component of Debian package names can only include " \
      "alphabetical characters (a-z, A-Z), numbers (0-9), dots (.), " \
      "plus signs (+), dashes (-), tildes (~) and colons (:). Converting " \
      "`#{project.build_version}' to `#{converted}'."
    end

    converted
  end
end
section(val = NULL) click to toggle source

Set or return the section for this package.

@example

section "databases"

@param [String] val

the section for this package

@return [String]

the section for this package
# File lib/omnibus/packagers/deb.rb, line 181
def section(val = NULL)
  if null?(val)
    @section || "misc"
  else
    unless val.is_a?(String)
      raise InvalidValue.new(:section, "be a String")
    end

    @section = val
  end
end
sign_deb_file() click to toggle source

Sign the .deb file with gpg. This has to be done as separate steps from creating the .deb file. See debsigs source for behavior replicated here. +gitlab.com/debsigs/debsigs/blob/master/debsigs.txt#L103-124+

@return [void]

# File lib/omnibus/packagers/deb.rb, line 420
def sign_deb_file
  unless signing_passphrase
    log.info(log_key) { "Signing not enabled for .deb file" }
    return
  end

  log.info(log_key) { "Signing enabled for .deb file" }

  # Check our dependencies and determine command for GnuPG. +Omnibus.which+ returns the path, or nil.
  gpg = nil
  if Omnibus.which("gpg2")
    gpg = "gpg2"
  elsif Omnibus.which("gpg")
    gpg = "gpg"
  end

  if gpg && Omnibus.which("ar")
    # Create a directory that will be cleaned when we leave the block
    Dir.mktmpdir do |tmp_dir|
      Dir.chdir(tmp_dir) do
        # Extract the deb file contents
        shellout!("ar x #{Config.package_dir}/#{package_name}")
        # Concatenate contents, in order per +debsigs+ documentation.
        shellout!("cat debian-binary control.tar.* data.tar.* > complete")
        # Create signature (as +root+)
        gpg_command =  "#{gpg} --armor --sign --detach-sign"
        gpg_command << " --local-user '#{project.maintainer}'"
        gpg_command << " --homedir #{ENV["HOME"]}/.gnupg" # TODO: Make this configurable
        ## pass the +signing_passphrase+ via +STDIN+
        gpg_command << " --batch --no-tty"
        ## Check `gpg` for the compatibility/need of pinentry-mode
        # - We're calling gpg with the +--pinentry-mode+ argument, and +STDIN+ of +/dev/null+
        # - This _will_ fail with exit code 2 no matter what. We want to check the +STDERR+
        #   for the error message about the parameter. If it is _not present_ in the
        #   output, then we _do_ want to add it. (If +grep -q+ is +1+, add parameter)
        if shellout("#{gpg} --pinentry-mode loopback </dev/null 2>&1 | grep -q pinentry-mode").exitstatus == 1
          gpg_command << " --pinentry-mode loopback"
        end
        gpg_command << " --passphrase-fd 0"
        gpg_command << " -o _gpgorigin complete"
        shellout!("fakeroot #{gpg_command}", input: signing_passphrase)
        # Append +_gpgorigin+ to the +.deb+ file (as +root+)
        shellout!("fakeroot ar rc #{Config.package_dir}/#{package_name} _gpgorigin")
      end
    end
  else
    log.info(log_key) { "Signing not possible. Ensure that GnuPG and GNU AR are available" }
  end
end
signing_passphrase(val = NULL) click to toggle source

Set or return the signing passphrase. If this value is provided, Omnibus will attempt to sign the DEB.

@example

signing_passphrase "foo"

@param [String] val

the passphrase to use when signing the DEB

@return [String]

the DEB-signing passphrase
# File lib/omnibus/packagers/deb.rb, line 85
def signing_passphrase(val = NULL)
  if null?(val)
    @signing_passphrase
  else
    @signing_passphrase = val
  end
end
vendor(val = NULL) click to toggle source

Set or return the vendor who made this package.

@example

vendor "Seth Vargo <sethvargo@gmail.com>"

@param [String] val

the vendor who make this package

@return [String]

the vendor who make this package
# File lib/omnibus/packagers/deb.rb, line 106
def vendor(val = NULL)
  if null?(val)
    @vendor || "Omnibus <omnibus@getchef.com>"
  else
    unless val.is_a?(String)
      raise InvalidValue.new(:vendor, "be a String")
    end

    @vendor = val
  end
end
write_conffiles_file() click to toggle source

Render the list of config files into the conffile.

@return [void]

# File lib/omnibus/packagers/deb.rb, line 331
def write_conffiles_file
  return if project.config_files.empty?

  render_template(resource_path("conffiles.erb"),
    destination: File.join(debian_dir, "conffiles"),
    variables: {
      config_files: project.config_files,
    })
end
write_control_file() click to toggle source

Render a control file in +#{debian_dir}/control+ using the supplied ERB template.

@return [void]

# File lib/omnibus/packagers/deb.rb, line 304
def write_control_file
  render_template(resource_path("control.erb"),
    destination: File.join(debian_dir, "control"),
    variables: {
      name: safe_base_package_name,
      version: safe_version,
      iteration: safe_build_iteration,
      vendor: vendor,
      license: license,
      architecture: safe_architecture,
      maintainer: project.maintainer,
      installed_size: package_size,
      homepage: project.homepage,
      description: project.description,
      priority: priority,
      section: section,
      conflicts: project.conflicts,
      replaces: project.replaces,
      dependencies: project.runtime_dependencies,
    })
end
write_md5_sums() click to toggle source

Generate a list of the md5 sums of every file in the package and write it to +#{debian_dir}/control/md5sums+.

@return [void]

# File lib/omnibus/packagers/deb.rb, line 366
def write_md5_sums
  path = "#{staging_dir}/**/*"
  hash = FileSyncer.glob(path).inject({}) do |hash, path|
    if File.file?(path) && !File.symlink?(path) && !(File.dirname(path) == debian_dir)
      relative_path = path.gsub("#{staging_dir}/", "")
      hash[relative_path] = digest(path, :md5)
    end

    hash
  end

  render_template(resource_path("md5sums.erb"),
    destination: File.join(debian_dir, "md5sums"),
    variables: {
      md5sums: hash,
    })
end
write_scripts() click to toggle source

Copy all scripts in {Project#package_scripts_path} to the control directory of this repo.

@return [void]

# File lib/omnibus/packagers/deb.rb, line 347
def write_scripts
  %w{preinst postinst prerm postrm}.each do |script|
    path = File.join(project.package_scripts_path, script)

    if File.file?(path)
      log.debug(log_key) { "Adding script `#{script}' to `#{debian_dir}' from #{path}" }
      copy_file(path, debian_dir)
      log.debug(log_key) { "SCRIPT FILE:  #{debian_dir}/#{script}" }
      FileUtils.chmod(0755, File.join(debian_dir, script))
    end
  end
end