# # Copyright:: Copyright (c) 2012-2014 Chef Software, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require 'omnibus/build_version' require 'spec_helper' describe Omnibus::BuildVersion do let(:git_describe) { '11.0.0-alpha1-207-g694b062' } let(:valid_semver_regex) { /^\d+\.\d+\.\d+(\-[\dA-Za-z\-\.]+)?(\+[\dA-Za-z\-\.]+)?$/ } let(:valid_git_describe_regex) { /^\d+\.\d+\.\d+(\-[A-Za-z0-9\-\.]+)?(\-\d+\-g[0-9a-f]+)?$/ } subject(:build_version) { Omnibus::BuildVersion.new } before :each do ENV['BUILD_ID'] = nil ENV['OMNIBUS_APPEND_TIMESTAMP'] = nil Omnibus::BuildVersion.any_instance.stub(:shellout) .and_return(double('ouput', stdout: git_describe, exitstatus: 0)) end describe 'git describe parsing' do # we prefer our git tags to be SemVer compliant # release version context '11.0.1' do let(:git_describe) { '11.0.1' } its(:version_tag) { should == '11.0.1' } its(:prerelease_tag) { should be_nil } its(:git_sha_tag) { should be_nil } its(:commits_since_tag) { should == 0 } its(:development_version?) { should be_true } its(:prerelease_version?) { should be_false } end # SemVer compliant prerelease version context '11.0.0-alpha.2' do let(:git_describe) { '11.0.0-alpha.2' } its(:version_tag) { should == '11.0.0' } its(:prerelease_tag) { should == 'alpha.2' } its(:git_sha_tag) { should be_nil } its(:commits_since_tag) { should == 0 } its(:development_version?) { should be_false } its(:prerelease_version?) { should be_true } end # full git describe string context '11.0.0-alpha.3-59-gf55b180' do let(:git_describe) { '11.0.0-alpha.3-59-gf55b180' } its(:version_tag) { should == '11.0.0' } its(:prerelease_tag) { should == 'alpha.3' } its(:git_sha_tag) { should == 'f55b180' } its(:commits_since_tag) { should == 59 } its(:development_version?) { should be_false } its(:prerelease_version?) { should be_true } end # Degenerate git tag formats # RubyGems compliant git tag context '10.16.0.rc.0' do let(:git_describe) { '10.16.0.rc.0' } its(:version_tag) { should == '10.16.0' } its(:prerelease_tag) { should == 'rc.0' } its(:git_sha_tag) { should be_nil } its(:commits_since_tag) { should == 0 } its(:development_version?) { should be_false } its(:prerelease_version?) { should be_true } end # dash seperated prerelease context '11.0.0-alpha-2' do let(:git_describe) { '11.0.0-alpha-2' } its(:version_tag) { should == '11.0.0' } its(:prerelease_tag) { should == 'alpha-2' } its(:git_sha_tag) { should be_nil } its(:commits_since_tag) { should == 0 } its(:development_version?) { should be_false } its(:prerelease_version?) { should be_true } end # dash seperated prerelease full git describe string context '11.0.0-alpha-2-59-gf55b180' do let(:git_describe) { '11.0.0-alpha-2-59-gf55b180' } its(:version_tag) { should == '11.0.0' } its(:prerelease_tag) { should == 'alpha-2' } its(:git_sha_tag) { should == 'f55b180' } its(:commits_since_tag) { should == 59 } its(:development_version?) { should be_false } its(:prerelease_version?) { should be_true } end # WTF git tag context '11.0.0-alpha2' do let(:git_describe) { '11.0.0-alpha2' } its(:version_tag) { should == '11.0.0' } its(:prerelease_tag) { should == 'alpha2' } its(:git_sha_tag) { should be_nil } its(:commits_since_tag) { should == 0 } its(:development_version?) { should be_false } its(:prerelease_version?) { should be_true } end end describe 'semver output' do let(:today_string) { Time.now.utc.strftime('%Y%m%d') } it 'generates a valid semver version' do expect(build_version.semver).to match(valid_semver_regex) end it "generates a version matching format 'MAJOR.MINOR.PATCH-PRERELEASE+TIMESTAMP.git.COMMITS_SINCE.GIT_SHA'" do expect(build_version.semver).to match(/11.0.0-alpha1\+#{today_string}[0-9]+.git.207.694b062/) end it "uses ENV['BUILD_ID'] to generate timestamp if set" do ENV['BUILD_ID'] = '2012-12-25_16-41-40' expect(build_version.semver).to eq('11.0.0-alpha1+20121225164140.git.207.694b062') end it "fails on invalid ENV['BUILD_ID'] values" do ENV['BUILD_ID'] = 'AAAA' expect { build_version.semver }.to raise_error(ArgumentError) end context 'prerelease version with dashes' do let(:git_describe) { '11.0.0-alpha-3-207-g694b062' } it 'converts all dashes to dots' do expect(build_version.semver).to match(/11.0.0-alpha.3\+#{today_string}[0-9]+.git.207.694b062/) end end context 'exact version' do let(:git_describe) { '11.0.0-alpha2' } it 'appends a timestamp with no git info' do expect(build_version.semver).to match(/11.0.0-alpha2\+#{today_string}[0-9]+/) end end describe 'appending a timestamp' do let(:git_describe) { '11.0.0-alpha-3-207-g694b062' } it 'appends a timestamp by default' do expect(build_version.semver).to match(/11.0.0-alpha.3\+#{today_string}[0-9]+.git.207.694b062/) end describe "ENV['OMNIBUS_APPEND_TIMESTAMP'] is set" do ['true', 't', 'yes', 'y', 1].each do |truthy| context "to #{truthy}" do before { ENV['OMNIBUS_APPEND_TIMESTAMP'] = truthy.to_s } it 'appends a timestamp' do expect(build_version.semver).to match(/11.0.0-alpha.3\+#{today_string}[0-9]+.git.207.694b062/) end end end ['false', 'f', 'no', 'n', 0].each do |falsey| context "to #{falsey}" do before { ENV['OMNIBUS_APPEND_TIMESTAMP'] = falsey.to_s } it 'does not append a timestamp' do expect(build_version.semver).to match(/11.0.0-alpha.3\+git.207.694b062/) end end end end describe 'Omnibus::Config.append_timestamp is set' do context 'is true' do before { Omnibus::Config.append_timestamp(true) } it 'appends a timestamp' do expect(build_version.semver).to match(/11.0.0-alpha.3\+#{today_string}[0-9]+.git.207.694b062/) end end context 'is false' do before { Omnibus::Config.append_timestamp(false) } it 'does not append a timestamp' do expect(build_version.semver).to match(/11.0.0-alpha.3\+git.207.694b062/) end end end describe 'both are set' do before do ENV['OMNIBUS_APPEND_TIMESTAMP'] = 'false' Omnibus::Config.append_timestamp(true) end it "prefers the value from ENV['OMNIBUS_APPEND_TIMESTAMP']" do expect(build_version.semver).to match(/11.0.0-alpha.3\+git.207.694b062/) end end end end describe 'git describe output' do it 'generates a valid git describe version' do expect(build_version.git_describe).to match(valid_git_describe_regex) end it "generates a version matching format 'MAJOR.MINOR.PATCH-PRELEASE.COMMITS_SINCE-gGIT_SHA'" do expect(build_version.git_describe).to eq(git_describe) end end describe 'deprecated full output' do it 'generates a valid git describe version' do expect(Omnibus::BuildVersion.full).to match(valid_git_describe_regex) end it 'outputs a deprecation message' do expect(Omnibus::BuildVersion).to receive(:puts).with(/is deprecated/) Omnibus::BuildVersion.full end end describe '`git describe` command failure' do before do stderr = <<-STDERR fatal: No tags can describe '809ea1afcce67e1148c1bf0822d40a7ef12c380e'. Try --always, or create some tags. STDERR build_version.stub(:shellout) .and_return(double('ouput', stderr: stderr, exitstatus: 128)) end it 'sets the version to 0.0.0' do expect(build_version.git_describe).to eq('0.0.0') end end describe '#initialize `path` parameter' do let(:path) { '/some/fake/path' } subject(:build_version) { Omnibus::BuildVersion.new(path) } it 'runs `git describe` at an alternate path' do expect(build_version).to receive(:shellout) .with('git describe', live_stream: nil, cwd: path) .and_return(double('ouput', stdout: git_describe, exitstatus: 0)) build_version.git_describe end end end