class Omnibus::ArtifactoryPublisher

Public Instance Methods

publish() { |package| ... } click to toggle source
# File lib/omnibus/publishers/artifactory_publisher.rb, line 22
def publish(&block)
  log.info(log_key) { "Starting artifactory publisher" }
  safe_require("artifactory")

  packages.each do |package|
    # Make sure the package is good to go!
    log.debug(log_key) { "Validating '#{package.name}'" }
    package.validate!

    retries = Config.publish_retries

    begin
      upload_time = Benchmark.realtime do
        remote_path = remote_path_for(package)
        properties  = default_properties.merge(metadata_properties_for(package))

        # Upload the package
        log.info(log_key) { "Uploading '#{package.name}'" }
        artifact_for(package).upload(
          repository,
          remote_path,
          properties
        )
        # Upload the package's assoacited `*.metadata.json` file
        log.info(log_key) { "Uploading '#{package.name}.metadata.json'" }
        artifact_for(package.metadata).upload(
          repository,
          "#{remote_path}.metadata.json",
          # *.metadata.json files should not include
          # the checksum properties
          properties.dup.delete_if { |k, v| k =~ /^omnibus\.(md5|sha)/ }
        )
      end
    rescue Artifactory::Error::HTTPError => e
      if (retries -= 1) != 0
        log.info(log_key) { "Upload failed with exception: #{e}" }
        log.info(log_key) { "Retrying failed publish #{retries} more time(s)..." }
        retry
      else
        raise e
      end
    end

    log.debug(log_key) { "Elapsed time to publish #{package.name}:  #{1000 * upload_time} ms" }

    # If a block was given, "yield" the package to the caller
    yield(package) if block
  end

  if build_record?
    if packages.empty?
      log.warn(log_key) { "No packages were uploaded, build record will not be created." }
    else
      build_for(packages).save
    end
  end
end

Private Instance Methods

artifact_for(artifact) click to toggle source

The artifact object that corresponds to this package.

@param [Package,Metadata] artifact

the package or metadata file to create the artifact from

@return [Artifactory::Resource::Artifact]

# File lib/omnibus/publishers/artifactory_publisher.rb, line 90
def artifact_for(artifact)
  md5  = artifact.respond_to?(:metadata) ? artifact.metadata[:md5] : digest(artifact.path, :md5)
  sha1 = artifact.respond_to?(:metadata) ? artifact.metadata[:sha1] : digest(artifact.path, :sha1)

  Artifactory::Resource::Artifact.new(
    local_path: artifact.path,
    client:     client,
    checksums: {
      "md5" => md5,
      "sha1" => sha1,
    }
  )
end
build_for(packages) click to toggle source

The build object that corresponds to this package.

@param [Array<Package>] packages

the packages to create the build from

@return [Artifactory::Resource::Build]

# File lib/omnibus/publishers/artifactory_publisher.rb, line 112
def build_for(packages)
  metadata = packages.first.metadata
  name     = metadata[:name]

  # Attempt to load the version manifest data from the packages metadata
  manifest = if version_manifest = metadata[:version_manifest]
               Manifest.from_hash(version_manifest)
             else
               Manifest.new(
                 metadata[:version],
                 # we already know the `version_manifest` entry is
                 # missing so we can't pull in the `build_git_revision`
                 nil,
                 metadata[:license]
               )
             end

  # Upload the actual package
  log.info(log_key) { "Saving build info for #{name}, Build ##{manifest.build_version}" }

  Artifactory::Resource::Build.new(
    client: client,
    name:   name,
    number: manifest.build_version,
    vcs_revision: manifest.build_git_revision,
    build_agent: {
      name: "omnibus",
      version: Omnibus::VERSION,
    },
    modules: [
      {
        # com.getchef:chef-server:12.0.0
        id: [
          Config.artifactory_base_path.tr("/", "."),
          name,
          manifest.build_version,
        ].join(":"),
        artifacts: packages.map do |package|
          [
            {
              type: File.extname(package.path).split(".").last,
              sha1: package.metadata[:sha1],
              md5: package.metadata[:md5],
              name: package.metadata[:basename],
            },
            {
              type: File.extname(package.metadata.path).split(".").last,
              sha1: digest(package.metadata.path, :sha1),
              md5: digest(package.metadata.path, :md5),
              name: File.basename(package.metadata.path),
            },
          ]
        end.flatten,
      },
    ]
  )
end
build_record?() click to toggle source

Indicates if an Artifactory build record should be created for the published set of packages.

@return [Boolean]

# File lib/omnibus/publishers/artifactory_publisher.rb, line 176
def build_record?
  # We want to create a build record by default
  if @options[:build_record].nil?
    true
  else
    @options[:build_record]
  end
end
client() click to toggle source

The Artifactory client object to communicate with the Artifactory API.

@return [Artifactory::Client]

# File lib/omnibus/publishers/artifactory_publisher.rb, line 190
def client
  @client ||= Artifactory::Client.new(
    endpoint:       Config.artifactory_endpoint,
    username:       Config.artifactory_username,
    password:       Config.artifactory_password,
    ssl_pem_file:   Config.artifactory_ssl_pem_file,
    ssl_verify:     Config.artifactory_ssl_verify,
    proxy_username: Config.artifactory_proxy_username,
    proxy_password: Config.artifactory_proxy_password,
    proxy_address:  Config.artifactory_proxy_address,
    proxy_port:     Config.artifactory_proxy_port
  )
end
default_properties() click to toggle source

Properties to attach to published artifacts (and build record).

@return [Hash<String, String>]

# File lib/omnibus/publishers/artifactory_publisher.rb, line 244
def default_properties
  @properties ||= @options[:properties] || {}
end
metadata_properties_for(package) click to toggle source

The metadata for this package.

@param [Package] package

the package to generate the metadata for

@return [Hash<String, String>]

# File lib/omnibus/publishers/artifactory_publisher.rb, line 212
def metadata_properties_for(package)
  metadata = {
    "omnibus.project" => package.metadata[:name],
    "omnibus.platform" => package.metadata[:platform],
    "omnibus.platform_version" => package.metadata[:platform_version],
    "omnibus.architecture" => package.metadata[:arch],
    "omnibus.version" => package.metadata[:version],
    "omnibus.iteration" => package.metadata[:iteration],
    "omnibus.license" => package.metadata[:license],
    "omnibus.md5" => package.metadata[:md5],
    "omnibus.sha1" => package.metadata[:sha1],
    "omnibus.sha256" => package.metadata[:sha256],
    "omnibus.sha512" => package.metadata[:sha512],
    "md5" => package.metadata[:md5],
    "sha1" => package.metadata[:sha1],
    "sha256" => package.metadata[:sha256],
    "sha512" => package.metadata[:sha512],
  }.tap do |h|
    if build_record?
      h["build.name"] = package.metadata[:name]
      h["build.number"] = package.metadata[:version]
    end
  end

  metadata
end
remote_path_for(package) click to toggle source

The path where the package will live inside of the Artifactory repository. This is dynamically computed from the values in the project definition and the package metadata.

@example

com/getchef/chef/11.6.0/ubuntu/14.04/chef-11.6.0-1.el6.x86_64.rpm

@param [Package] package

the package to generate the remote path for

@return [String]

# File lib/omnibus/publishers/artifactory_publisher.rb, line 270
def remote_path_for(package)
  File.join(
    Config.artifactory_base_path,
    Config.artifactory_publish_pattern % package.metadata
  )
end
repository() click to toggle source

The name of the Artifactory repository (as supplied as an option).

@return [String]

# File lib/omnibus/publishers/artifactory_publisher.rb, line 253
def repository
  @options[:repository]
end