spec/unit/publishers/artifactory_publisher_spec.rb (251 lines of code) (raw):

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, license: "Apache-2.0", basename: "chef.deb", platform: "ubuntu", platform_version: "14.04", arch: "x86_64", sha1: "SHA1", sha256: "SHA256", sha512: "SHA512", md5: "ABCDEF123456", version_manifest: { manifest_format: 1, build_version: "11.0.6", build_git_revision: "2e763ac957b308ba95cef256c2491a5a55a163cc", software: { zlib: { locked_source: { md5: "44d667c142d7cda120332623eab69f40", url: "http://iweb.dl.sourceforge.net/project/libpng/zlib/1.2.8/zlib-1.2.8.tar.gz", }, locked_version: "1.2.8", source_type: "url", described_version: "1.2.8", license: "Zlib", }, openssl: { locked_source: { md5: "562986f6937aabc7c11a6d376d8a0d26", extract: "lax_tar", url: "http://iweb.dl.sourceforge.net/project/libpng/zlib/1.2.8/zlib-1.2.8.tar.gz", }, locked_version: "1.0.1s", source_type: "url", described_version: "1.0.1s", license: "OpenSSL", }, ruby: { locked_source: { md5: "091b62f0a9796a3c55de2a228a0e6ef3", url: "https://cache.ruby-lang.org/pub/ruby/2.1/ruby-2.1.8.tar.gz", }, locked_version: "2.1.8", source_type: "url", described_version: "2.1.8", license: "BSD-2-Clause", }, ohai: { locked_source: { git: "https://github.com/chef/ohai.git", }, locked_version: "fec0959aa5da5ce7ba0e07740dbc08546a8f53f0", source_type: "git", described_version: "master", license: "Apache-2.0", }, chef: { locked_source: { path: "/home/jenkins/workspace/chef-build/architecture/x86_64/platform/ubuntu-10.04/project/chef/role/builder/omnibus/files/../..", options: { exclude: [ "omnibus/vendor", ], }, }, locked_version: "local_source", source_type: "path", described_version: "local_source", license: "Apache-2.0", }, }, }) end let(:packages) { [package] } let(:client) { double("Artifactory::Client") } let(:artifact) { double("Artifactory::Resource::Artifact", upload: nil) } let(:build) { double("Artifactory::Resource::Build") } let(:package_properties) 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", "omnibus.license" => "Apache-2.0", "md5" => "ABCDEF123456", "sha1" => "SHA1", "sha256" => "SHA256", "sha512" => "SHA512", } end let(:metadata_json_properites) do # we don't attache checksum properties to the *.metadata.json package_properties.delete_if { |k, v| k =~ /md5|sha/ } 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(package_properties) ).once subject.publish end it "uploads the package's associated *.metadata.json" do expect(artifact).to receive(:upload).with( repository, "com/getchef/chef/11.0.6/ubuntu/14.04/chef.deb.metadata.json", hash_including(metadata_json_properites) ).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(package_properties.merge(delivery_props)) ).once subject.publish end end context "custom artifactory_publish_pattern is set" do before do Config.artifactory_publish_pattern("%{platform}/%{platform_version}/%{arch}/%{basename}") end it "uploads the package to the provided path" do expect(artifact).to receive(:upload).with( repository, "com/getchef/ubuntu/14.04/x86_64/chef.deb", hash_including(metadata_json_properites) ).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(package_properties.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(package_properties) expect(subject.send(:metadata_properties_for, package)).to_not include(build_values) end end end end end