require 'spec_helper' module Omnibus describe ArtifactoryPublisher do let(:path) { '/path/to/files/*.deb' } let(:repository) { 'REPO' } let(:package) do double(Package, path: '/path/to/files/chef.deb', name: 'chef.deb', content: 'BINARY', validate!: true, ) end let(:metadata) do Metadata.new(package, name: 'chef', friendly_name: 'Chef', homepage: 'https://www.getchef.com', version: '11.0.6', iteration: 1, basename: 'chef.deb', platform: 'ubuntu', platform_version: '14.04', arch: 'x86_64', sha1: 'SHA1', sha256: 'SHA256', sha512: 'SHA512', md5: 'ABCDEF123456', ) end let(:packages) { [package] } let(:client) { double('Artifactory::Client') } let(:artifact) { double('Artifactory::Resource::Artifact', upload: nil) } let(:build) { double('Artifactory::Resource::Build') } let(:transformed_metadata_values) do { "omnibus.architecture" => "x86_64", "omnibus.iteration" => 1, "omnibus.md5" => "ABCDEF123456", "omnibus.platform" => "ubuntu", "omnibus.platform_version" => "14.04", "omnibus.project" => "chef", "omnibus.sha1" => "SHA1", "omnibus.sha256" => "SHA256", "omnibus.sha512" => "SHA512", "omnibus.version" => "11.0.6", } end let(:build_values) do { "build.name" => "chef", "build.number" => "11.0.6", } end let(:options) { {repository: repository} } before do allow(subject).to receive(:client).and_return(client) allow(subject).to receive(:artifact_for).and_return(artifact) allow(subject).to receive(:build_for).and_return(build) allow(package).to receive(:metadata).and_return(metadata) allow(build).to receive(:save) end subject { described_class.new(path, options) } describe '#publish' do before do allow(subject).to receive(:packages).and_return(packages) Config.artifactory_base_path('com/getchef') Config.publish_retries(1) end it 'validates the package' do expect(package).to receive(:validate!).once subject.publish end it 'uploads the package' do expect(artifact).to receive(:upload).with( repository, 'com/getchef/chef/11.0.6/ubuntu/14.04/chef.deb', hash_including(transformed_metadata_values), ).once subject.publish end it 'it creates a build record for all packages' do expect(build).to receive(:save).once subject.publish end context 'when no packages exist' do let(:packages) { [] } it 'does nothing' do expect(artifact).to_not receive(:upload) expect(build).to_not receive(:save) end end context 'when upload fails' do before do Config.publish_retries(3) # This is really ugly but there is no easy way to stub a method to # raise an exception a set number of times. @times = 0 allow(artifact).to receive(:upload) do @times += 1; raise Artifactory::Error::HTTPError.new('status' => '409', 'message' => 'CONFLICT') unless @times > 1 end end it 'retries the upload ' do output = capture_logging { subject.publish } expect(output).to include('Retrying failed publish') end end context 'when a block is given' do it 'yields the package to the block' do block = ->(package) { package.do_something! } expect(package).to receive(:do_something!).once subject.publish(&block) end end context 'when the :build_record option is false' do subject { described_class.new(path, repository: repository, build_record: false) } it 'does not create a build record at the end of publishing' do expect(build).to_not receive(:save) subject.publish end end context 'additional properties are provided' do let(:delivery_props) do { 'delivery.change' => '4dbf38de-3e82-439f-8090-c5f3e11aeba6', 'delivery.sha' => 'ec1cb62616350176fc6fd9b1dc4ad3153caa0791', } end let(:options) do { properties: delivery_props, repository: repository, } end it 'uploads the package with the provided properties' do expect(artifact).to receive(:upload).with( repository, 'com/getchef/chef/11.0.6/ubuntu/14.04/chef.deb', hash_including(transformed_metadata_values.merge(delivery_props)), ).once subject.publish end end end describe '#metadata_properties_for' do it 'returns the transformed package metadata values' do expect(subject.send(:metadata_properties_for, package)).to include(transformed_metadata_values.merge(build_values)) end context ':build_record is false' do let(:options) do { build_record: false, repository: repository, } end it 'does not include `build.*` values' do expect(subject.send(:metadata_properties_for, package)).to include(transformed_metadata_values) expect(subject.send(:metadata_properties_for, package)).to_not include(build_values) end end end end end