cicd-builder 0.9.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/.gitignore +35 -0
- data/ChangeLog.md +4 -0
- data/Gemfile +7 -0
- data/LICENSE +201 -0
- data/LICENSE.txt +203 -0
- data/README.md +4 -0
- data/Rakefile +30 -0
- data/cicd-builder.gemspec +33 -0
- data/features/.gitkeep +0 -0
- data/features/ci-cd-builder.feature +1 -0
- data/features/cicd-builder.feature +1 -0
- data/features/step_definitions/.gitkeep +0 -0
- data/features/step_definitions/ci-cd-builder_steps.rb +1 -0
- data/features/step_definitions/cicd-builder_steps.rb +1 -0
- data/lib/cicd/builder.rb +87 -0
- data/lib/cicd/builder/mixlib/build.rb +160 -0
- data/lib/cicd/builder/mixlib/constants.rb +18 -0
- data/lib/cicd/builder/mixlib/environment.rb +194 -0
- data/lib/cicd/builder/mixlib/errors.rb +12 -0
- data/lib/cicd/builder/mixlib/options.rb +86 -0
- data/lib/cicd/builder/mixlib/repo.rb +428 -0
- data/lib/cicd/builder/mixlib/utils.rb +27 -0
- data/lib/cicd/builder/version.rb +12 -0
- metadata +240 -0
    
        data/README.md
    ADDED
    
    
    
        data/Rakefile
    ADDED
    
    | @@ -0,0 +1,30 @@ | |
| 1 | 
            +
            # encoding: utf-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'rubygems'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            begin
         | 
| 6 | 
            +
              require 'bundler'
         | 
| 7 | 
            +
            rescue LoadError => e
         | 
| 8 | 
            +
              warn e.message
         | 
| 9 | 
            +
              warn "Run `gem install bundler` to install Bundler."
         | 
| 10 | 
            +
              exit -1
         | 
| 11 | 
            +
            end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            begin
         | 
| 14 | 
            +
              Bundler.setup(:development)
         | 
| 15 | 
            +
            rescue Bundler::BundlerError => e
         | 
| 16 | 
            +
              warn e.message
         | 
| 17 | 
            +
              warn "Run `bundle install` to install missing gems."
         | 
| 18 | 
            +
              exit e.status_code
         | 
| 19 | 
            +
            end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            require 'rake'
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            require 'rubygems/tasks'
         | 
| 24 | 
            +
            Gem::Tasks.new
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            require 'cucumber/rake/task'
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            Cucumber::Rake::Task.new do |t|
         | 
| 29 | 
            +
              t.cucumber_opts = %w[--format pretty]
         | 
| 30 | 
            +
            end
         | 
| @@ -0,0 +1,33 @@ | |
| 1 | 
            +
            # -*- encoding: utf-8 -*-
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require File.expand_path('../lib/cicd/builder/version', __FILE__)
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            Gem::Specification.new do |gem|
         | 
| 6 | 
            +
              gem.name          = 'cicd-builder'
         | 
| 7 | 
            +
              gem.version       = CiCd::Builder::VERSION
         | 
| 8 | 
            +
              gem.summary       = 'Jenkins builder task for CI/CD'
         | 
| 9 | 
            +
              gem.description   = 'Jenkins builder task for CI/CD'
         | 
| 10 | 
            +
              gem.license       = 'Apachev2'
         | 
| 11 | 
            +
              gem.authors       = ['Christo De Lange']
         | 
| 12 | 
            +
              gem.email         = 'rubygems@dldinternet.com'
         | 
| 13 | 
            +
              gem.homepage      = 'https://rubygems.org/gems/cicd-builder'
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              gem.files         = `git ls-files`.split($/)
         | 
| 16 | 
            +
              gem.executables   = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
         | 
| 17 | 
            +
              gem.test_files    = gem.files.grep(%r{^(test|spec|features)/})
         | 
| 18 | 
            +
              gem.require_paths = ['lib']
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              gem.add_dependency 'awesome_print', ">= 0.0.0"
         | 
| 21 | 
            +
              gem.add_dependency 'inifile', '>= 0.0.0'
         | 
| 22 | 
            +
              gem.add_dependency 'logging', '>= 0.0.0'
         | 
| 23 | 
            +
              gem.add_dependency 'json', '= 1.7.7'
         | 
| 24 | 
            +
              gem.add_dependency 'chef', '>= 11.8.2'
         | 
| 25 | 
            +
              gem.add_dependency 'aws-sdk', '>= 0.0.0'
         | 
| 26 | 
            +
              gem.add_dependency 'yajl-ruby', '>= 0.0.0'
         | 
| 27 | 
            +
              gem.add_dependency 'git', '>= 1.2.7'
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              gem.add_development_dependency 'bundler', '~> 1.0'
         | 
| 30 | 
            +
              gem.add_development_dependency 'rake', '~> 10.3'
         | 
| 31 | 
            +
              gem.add_development_dependency 'rubygems-tasks', '~> 0.2'
         | 
| 32 | 
            +
              gem.add_development_dependency 'cucumber'
         | 
| 33 | 
            +
            end
         | 
    
        data/features/.gitkeep
    ADDED
    
    | 
            File without changes
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            Feature: Blah blah blah
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            Feature: Blah blah blah
         | 
| 
            File without changes
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            @wip
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            @wip
         | 
    
        data/lib/cicd/builder.rb
    ADDED
    
    | @@ -0,0 +1,87 @@ | |
| 1 | 
            +
            require 'cicd/builder/version'
         | 
| 2 | 
            +
            module CiCd
         | 
| 3 | 
            +
            	module Builder
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            		require 'awesome_print'
         | 
| 6 | 
            +
            		require 'optparse'
         | 
| 7 | 
            +
            		require 'inifile'
         | 
| 8 | 
            +
            		require 'logging'
         | 
| 9 | 
            +
            		require 'net/http'
         | 
| 10 | 
            +
            		require 'uri'
         | 
| 11 | 
            +
            		require 'fileutils'
         | 
| 12 | 
            +
            		require 'digest'
         | 
| 13 | 
            +
            		require 'yajl/json_gem'
         | 
| 14 | 
            +
            		require 'aws-sdk'
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            		_lib=File.dirname(__FILE__)
         | 
| 17 | 
            +
            		$:.unshift(_lib) unless $:.include?(_lib)
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            		require 'cicd/builder/version'
         | 
| 20 | 
            +
            		require 'cicd/builder/mixlib/constants'
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            		#noinspection ALL
         | 
| 23 | 
            +
            		class BuilderBase
         | 
| 24 | 
            +
            			attr_accessor :default_options
         | 
| 25 | 
            +
            			attr_accessor :options
         | 
| 26 | 
            +
            			attr_accessor :logger
         | 
| 27 | 
            +
            			attr_accessor :vars
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            			def initialize()
         | 
| 30 | 
            +
                    @vars = {
         | 
| 31 | 
            +
                        return_code: -1
         | 
| 32 | 
            +
                    }
         | 
| 33 | 
            +
            				@default_options = {
         | 
| 34 | 
            +
            						builder:        ::CiCd::Builder::VERSION,
         | 
| 35 | 
            +
            						env_keys:       %w(JENKINS_HOME BUILD_NUMBER JOB_NAME)
         | 
| 36 | 
            +
            				}
         | 
| 37 | 
            +
            			end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
            			require 'cicd/builder/mixlib/errors'
         | 
| 40 | 
            +
            			require 'cicd/builder/mixlib/utils'
         | 
| 41 | 
            +
            			require 'cicd/builder/mixlib/options'
         | 
| 42 | 
            +
            			require 'cicd/builder/mixlib/environment'
         | 
| 43 | 
            +
            			require 'cicd/builder/mixlib/repo'
         | 
| 44 | 
            +
            			require 'cicd/builder/mixlib/build'
         | 
| 45 | 
            +
             | 
| 46 | 
            +
            			# ---------------------------------------------------------------------------------------------------------------
         | 
| 47 | 
            +
                  def getBuilderVersion
         | 
| 48 | 
            +
                    {
         | 
| 49 | 
            +
                        version:  VERSION,
         | 
| 50 | 
            +
                        major:    MAJOR,
         | 
| 51 | 
            +
                        minor:    MINOR,
         | 
| 52 | 
            +
                        patch:    PATCH,
         | 
| 53 | 
            +
                    }
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            			# ---------------------------------------------------------------------------------------------------------------
         | 
| 57 | 
            +
            			def run()
         | 
| 58 | 
            +
            				$stdout.write("CiCd::Builder v#{@VERSION}\n")
         | 
| 59 | 
            +
            				parseOptions()
         | 
| 60 | 
            +
             | 
| 61 | 
            +
            				ret = checkEnvironment()
         | 
| 62 | 
            +
            				if 0 == ret
         | 
| 63 | 
            +
            					ret = getVars()
         | 
| 64 | 
            +
                      if 0 == ret
         | 
| 65 | 
            +
                        ret = prepareBuild()
         | 
| 66 | 
            +
                        if 0 == ret
         | 
| 67 | 
            +
                          ret = makeBuild()
         | 
| 68 | 
            +
                          if 0 == ret
         | 
| 69 | 
            +
                            ret = saveBuild()
         | 
| 70 | 
            +
                            if 0 == ret
         | 
| 71 | 
            +
                              ret = uploadBuildArtifacts()
         | 
| 72 | 
            +
                              if 0 == ret
         | 
| 73 | 
            +
                                # noop
         | 
| 74 | 
            +
                              end
         | 
| 75 | 
            +
                            end
         | 
| 76 | 
            +
                          end
         | 
| 77 | 
            +
                        end
         | 
| 78 | 
            +
                      end
         | 
| 79 | 
            +
                    end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
            				@vars[:return_code]
         | 
| 82 | 
            +
            			end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
            		end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
            	end
         | 
| 87 | 
            +
            end
         | 
| @@ -0,0 +1,160 @@ | |
| 1 | 
            +
            require 'json'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module CiCd
         | 
| 4 | 
            +
            	module Builder
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            		# ---------------------------------------------------------------------------------------------------------------
         | 
| 7 | 
            +
            		def cleanupBuild()
         | 
| 8 | 
            +
                  [ :build_pkg, :build_chk, :build_mdf, :build_mff ].each do |fil|
         | 
| 9 | 
            +
                    if File.exists?(@vars[fil])
         | 
| 10 | 
            +
                      begin
         | 
| 11 | 
            +
                        FileUtils.rm_f(@vars[fil])
         | 
| 12 | 
            +
                      rescue => e
         | 
| 13 | 
            +
                        @logger.error e.to_s
         | 
| 14 | 
            +
                        #raise e
         | 
| 15 | 
            +
                        return -96
         | 
| 16 | 
            +
                      end
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
            			if Dir.exists?(@vars[:build_dir])
         | 
| 20 | 
            +
            				begin
         | 
| 21 | 
            +
            					FileUtils.rm_r(@vars[:build_dir])
         | 
| 22 | 
            +
            				rescue => e
         | 
| 23 | 
            +
            					@logger.error e.to_s
         | 
| 24 | 
            +
            					#raise e
         | 
| 25 | 
            +
            					return -95
         | 
| 26 | 
            +
            				end
         | 
| 27 | 
            +
            			end
         | 
| 28 | 
            +
            			0
         | 
| 29 | 
            +
            		end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                # ---------------------------------------------------------------------------------------------------------------
         | 
| 32 | 
            +
                def prepareBuild()
         | 
| 33 | 
            +
                  meta = {}
         | 
| 34 | 
            +
                  %w[ WORKSPACE PROJECT_NAME VERSION RELEASE ].each do |e|
         | 
| 35 | 
            +
                    unless ENV.has_key?(e)
         | 
| 36 | 
            +
                      raise "#{e} environment variable is required"
         | 
| 37 | 
            +
                    end
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
                  meta[:Version] = ENV['VERSION']
         | 
| 40 | 
            +
                  meta[:Release] = ENV['RELEASE']
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  place = ''
         | 
| 43 | 
            +
                  begin
         | 
| 44 | 
            +
                    place = 'require "git"'
         | 
| 45 | 
            +
                    eval place
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                    # Assuming we are in the workspace ...
         | 
| 48 | 
            +
                    place = "Git.open('#{ENV['WORKSPACE']}')"
         | 
| 49 | 
            +
                    git = Git.open(ENV['WORKSPACE'], :log => @logger)
         | 
| 50 | 
            +
                    place = 'git.log'
         | 
| 51 | 
            +
                    meta[:Commit] = git.log[0].sha
         | 
| 52 | 
            +
                    place = 'git.current_branch'
         | 
| 53 | 
            +
                    meta[:Branch] = git.current_branch
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                    @vars[:build_bra] = meta[:Branch].gsub(%r([/|]),'.')
         | 
| 56 | 
            +
                    @vars[:build_ver] = "#{meta[:Version]}"
         | 
| 57 | 
            +
                    @vars[:build_vrb] = "#{@vars[:build_ver]}-release-#{meta[:Release]}-#{@vars[:build_bra]}-#{@vars[:variant]}" #
         | 
| 58 | 
            +
                    @vars[:build_nam] = "#{@vars[:project_name]}-#{@vars[:build_vrb]}"
         | 
| 59 | 
            +
                    @vars[:build_rel] = "#{@vars[:build_nam]}-build-#{@vars[:build_num]}"
         | 
| 60 | 
            +
                    @vars[:build_dir] = "#{ENV['WORKSPACE']}/#{@vars[:build_rel]}"
         | 
| 61 | 
            +
                    @vars[:latest_pkg]= "#{@vars[:build_store]}/#{@vars[:build_rel]}.tar.gz"
         | 
| 62 | 
            +
                    @vars[:build_pkg] = "#{@vars[:build_rel]}.tar.gz"
         | 
| 63 | 
            +
                    @vars[:build_chk] = "#{@vars[:build_rel]}.checksum"
         | 
| 64 | 
            +
                    @vars[:build_mff] = "#{@vars[:build_rel]}.manifest"
         | 
| 65 | 
            +
                    @vars[:build_mdf] = "#{@vars[:build_rel]}.meta"
         | 
| 66 | 
            +
                    @vars[:build_mdd] = meta.dup
         | 
| 67 | 
            +
                    #noinspection RubyArgCount
         | 
| 68 | 
            +
                    @vars[:build_mds] = Digest::SHA256.hexdigest(meta.to_s)
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                    @vars[:return_code] = 0
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                  rescue Exception => e
         | 
| 73 | 
            +
                    @logger.error "#{e.class}:: '#{place}' - #{e.message}"
         | 
| 74 | 
            +
                    @vars[:return_code] = -98
         | 
| 75 | 
            +
                  end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                  @vars[:return_code]
         | 
| 78 | 
            +
                end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                # ---------------------------------------------------------------------------------------------------------------
         | 
| 81 | 
            +
                def makeBuild()
         | 
| 82 | 
            +
                  if @vars.has_key?(:build_dir) and @vars.has_key?(:build_pkg)
         | 
| 83 | 
            +
                    begin
         | 
| 84 | 
            +
                      do_build = false
         | 
| 85 | 
            +
                      if File.exists?(@vars[:build_chk])
         | 
| 86 | 
            +
                        @vars[:build_sha] = IO.readlines(@vars[:build_chk])
         | 
| 87 | 
            +
                        unless @vars[:build_sha].is_a?(Array)
         | 
| 88 | 
            +
                          @logger.error "Unable to parse build checksum from #{@vars[:build_chk]}"
         | 
| 89 | 
            +
                          return -97
         | 
| 90 | 
            +
                        end
         | 
| 91 | 
            +
                        @vars[:build_sha] = @vars[:build_sha][0].chomp()
         | 
| 92 | 
            +
                      else
         | 
| 93 | 
            +
                        @vars[:build_sha] = ''
         | 
| 94 | 
            +
                        do_build = true
         | 
| 95 | 
            +
                      end
         | 
| 96 | 
            +
                      unless File.exists?(@vars[:build_pkg])
         | 
| 97 | 
            +
                        do_build = true
         | 
| 98 | 
            +
                      end
         | 
| 99 | 
            +
                      if do_build
         | 
| 100 | 
            +
                        @vars[:return_code] = cleanupBuild()
         | 
| 101 | 
            +
                        return @vars[:return_code] unless @vars[:return_code] == 0
         | 
| 102 | 
            +
                        @vars[:build_dte] = DateTime.now.strftime("%F %T%:z")
         | 
| 103 | 
            +
                        createMetaData()
         | 
| 104 | 
            +
                        @vars[:return_code] = packageBuild()
         | 
| 105 | 
            +
                        if 0 == @vars[:return_code]
         | 
| 106 | 
            +
                          @vars[:check_sha] = @vars[:build_sha]
         | 
| 107 | 
            +
                          @vars[:build_sha] = Digest::SHA256.file(@vars[:build_pkg]).hexdigest()
         | 
| 108 | 
            +
                          IO.write(@vars[:build_chk], @vars[:build_sha])
         | 
| 109 | 
            +
                        end
         | 
| 110 | 
            +
                        reportStatus()
         | 
| 111 | 
            +
                        reportResult()
         | 
| 112 | 
            +
                      else
         | 
| 113 | 
            +
                        reportStatus()
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                        # No need to build again :)
         | 
| 116 | 
            +
                        @logger.info "NO_CHANGE: #{ENV['JOB_NAME']} #{ENV['BUILD_NUMBER']} #{@vars[:build_nam]} #{@vars[:build_pkg]} #{@vars[:build_chk]} [#{@vars[:build_sha]}]"
         | 
| 117 | 
            +
                        @vars[:return_code] = 0
         | 
| 118 | 
            +
                        return 1
         | 
| 119 | 
            +
                      end
         | 
| 120 | 
            +
                    rescue => e
         | 
| 121 | 
            +
                      @logger.error "#{e.class.name} #{e.message}"
         | 
| 122 | 
            +
                      @vars[:return_code] = -99
         | 
| 123 | 
            +
                    end
         | 
| 124 | 
            +
                  else
         | 
| 125 | 
            +
                    @logger.error ":build_dir or :build_pkg is unknown"
         | 
| 126 | 
            +
                    @vars[:return_code] = 2
         | 
| 127 | 
            +
                  end
         | 
| 128 | 
            +
                  @vars[:return_code]
         | 
| 129 | 
            +
                end
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                # ---------------------------------------------------------------------------------------------------------------
         | 
| 132 | 
            +
            		def packageBuild()
         | 
| 133 | 
            +
            			excludes=%w(*.iml *.txt *.sh *.md .gitignore .editorconfig .jshintrc *.deprecated adminer doc)
         | 
| 134 | 
            +
            			excludes = excludes.map{ |e| "--exclude=#{@vars[:build_nam]}/#{e}" }.join(' ')
         | 
| 135 | 
            +
            			cmd = %(cd #{ENV['WORKSPACE']}; tar zcvf #{@vars[:build_pkg]} #{excludes} #{@vars[:build_nam]} 1>#{@vars[:build_pkg]}.manifest)
         | 
| 136 | 
            +
            			@logger.info cmd
         | 
| 137 | 
            +
            			logger_info = %x(#{cmd})
         | 
| 138 | 
            +
            			ret = $?.exitstatus
         | 
| 139 | 
            +
            			@logger.info logger_info
         | 
| 140 | 
            +
            			FileUtils.rmtree(@vars[:build_dir])
         | 
| 141 | 
            +
            			ret
         | 
| 142 | 
            +
            		end
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                # ---------------------------------------------------------------------------------------------------------------
         | 
| 145 | 
            +
                def createMetaData()
         | 
| 146 | 
            +
                  @vars[:build_mdd].merge!({
         | 
| 147 | 
            +
                                            :Generation => @options[:gen],
         | 
| 148 | 
            +
                                            :Project => @vars[:project_name],
         | 
| 149 | 
            +
                                            :Variant => @vars[:variant],
         | 
| 150 | 
            +
                                            :Build => @vars[:build_num],
         | 
| 151 | 
            +
                                            :Date => @vars[:build_dte],
         | 
| 152 | 
            +
                                            :Builder => VERSION,
         | 
| 153 | 
            +
             | 
| 154 | 
            +
                                                  })
         | 
| 155 | 
            +
                  json = JSON.pretty_generate( @vars[:build_mdd], { indent: "\t", space: ' '})
         | 
| 156 | 
            +
                  IO.write(@vars[:build_mdf], json)
         | 
| 157 | 
            +
                end
         | 
| 158 | 
            +
             | 
| 159 | 
            +
              end
         | 
| 160 | 
            +
            end
         | 
| @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            module CiCd
         | 
| 2 | 
            +
            	module Builder
         | 
| 3 | 
            +
            		#noinspection RubyStringKeysInHashInspection
         | 
| 4 | 
            +
            		LOGLEVELS = {
         | 
| 5 | 
            +
            			'crit'     => :fatal,
         | 
| 6 | 
            +
            			'critical' => :fatal,
         | 
| 7 | 
            +
            			'err'      => :error,
         | 
| 8 | 
            +
            			'error'    => :error,
         | 
| 9 | 
            +
            			'warn'     => :warn,
         | 
| 10 | 
            +
            			'warning'  => :warn,
         | 
| 11 | 
            +
            			'info'     => :info,
         | 
| 12 | 
            +
            			'debug'    => :debug,
         | 
| 13 | 
            +
            		}
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            		MYNAME       = File.basename(__FILE__)
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            	end
         | 
| 18 | 
            +
            end
         | 
| @@ -0,0 +1,194 @@ | |
| 1 | 
            +
            module CiCd
         | 
| 2 | 
            +
            	module Builder
         | 
| 3 | 
            +
                require 'awesome_print'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            		# ---------------------------------------------------------------------------------------------------------------
         | 
| 6 | 
            +
            		def checkEnvironment()
         | 
| 7 | 
            +
            			# [2013-12-30 Christo] Detect CI ...
         | 
| 8 | 
            +
            			unless ENV.has_key?('JENKINS_HOME')
         | 
| 9 | 
            +
            				puts 'Sorry, your CI environment is not supported at this time (2013-12-30) ... Christo De Lange'
         | 
| 10 | 
            +
            				puts 'This script is developed for Jenkins so either you are not using Jenkins or you ran me outside of the CI ecosystem ...'
         | 
| 11 | 
            +
            				return 99
         | 
| 12 | 
            +
            			end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            			# Check for the necessary environment variables
         | 
| 15 | 
            +
            			map_keys = {}
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            			@options[:env_keys].each { |k|
         | 
| 18 | 
            +
            				map_keys[k]= (not ENV.has_key?(k))
         | 
| 19 | 
            +
            			}
         | 
| 20 | 
            +
            			missing = map_keys.keys.select{ |k| map_keys[k] }
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            			if missing.count() > 0
         | 
| 23 | 
            +
            				ap missing
         | 
| 24 | 
            +
            				raise Exception.new("Need environment variables: #{missing}")
         | 
| 25 | 
            +
            			end
         | 
| 26 | 
            +
            			0
         | 
| 27 | 
            +
            		end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            		# ---------------------------------------------------------------------------------------------------------------
         | 
| 30 | 
            +
            		def getVars()
         | 
| 31 | 
            +
            			@vars               ||= {}
         | 
| 32 | 
            +
            			@vars[:release]     = 'latest'
         | 
| 33 | 
            +
            			@vars[:build_store] = '/tmp'
         | 
| 34 | 
            +
            			@vars[:variant]     = 'SNAPSHOT'
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            			if ENV.has_key?('PROJECT_NAME')
         | 
| 37 | 
            +
            				@vars[:project_name] = ENV['PROJECT_NAME']
         | 
| 38 | 
            +
            			end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
            			if ENV.has_key?('RELEASE')
         | 
| 41 | 
            +
            				@vars[:release] = ENV['RELEASE']
         | 
| 42 | 
            +
            			end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            			if ENV.has_key?('BUILD_STORE')
         | 
| 45 | 
            +
            				@vars[:build_store] = "#{ENV['BUILD_STORE']}"
         | 
| 46 | 
            +
            			end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
            			if ENV.has_key?('VARIANT')
         | 
| 49 | 
            +
            				@vars[:variant] = "#{ENV['VARIANT']}"
         | 
| 50 | 
            +
            			end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
            			if ENV.has_key?('BUILD_NUMBER')
         | 
| 53 | 
            +
            				@vars[:build_num] = "#{ENV['BUILD_NUMBER']}"
         | 
| 54 | 
            +
            			end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            			@vars[:return_code] = getLatest()
         | 
| 57 | 
            +
            		end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                def getLatest
         | 
| 60 | 
            +
                  ret = 0
         | 
| 61 | 
            +
                  @vars[:vars_fil] = "#{@vars[:build_store]}/#{ENV['JOB_NAME']}-#{@vars[:variant]}.env"
         | 
| 62 | 
            +
                  @vars[:latest_fil] = "#{@vars[:build_store]}/#{ENV['JOB_NAME']}-#{@vars[:variant]}.latest"
         | 
| 63 | 
            +
                  @vars[:latest_ver] = ''
         | 
| 64 | 
            +
                  @vars[:latest_sha] = ''
         | 
| 65 | 
            +
                  @vars[:latest_pkg] = ''
         | 
| 66 | 
            +
                  if @vars[:build_nam]
         | 
| 67 | 
            +
                    @vars[:latest_pkg]= "#{@vars[:build_store]}/#{@vars[:build_nam]}.tar.gz"
         | 
| 68 | 
            +
                  end
         | 
| 69 | 
            +
                  if File.exists?(@vars[:latest_fil])
         | 
| 70 | 
            +
                    @vars[:latest_ver] = IO.readlines(@vars[:latest_fil])
         | 
| 71 | 
            +
                    unless @vars[:latest_ver].is_a?(Array)
         | 
| 72 | 
            +
                      @logger.error "Unable to parse latest version from #{@vars[:latest_fil]}"
         | 
| 73 | 
            +
                      ret = -97
         | 
| 74 | 
            +
                    end
         | 
| 75 | 
            +
                    @vars[:latest_sha] = @vars[:latest_ver][1].chomp() if (@vars[:latest_ver].length > 1)
         | 
| 76 | 
            +
                    @vars[:latest_ver] = @vars[:latest_ver][0].chomp()
         | 
| 77 | 
            +
                  end
         | 
| 78 | 
            +
                  ret
         | 
| 79 | 
            +
                end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                # ---------------------------------------------------------------------------------------------------------------
         | 
| 82 | 
            +
            		def saveEnvironment(ignored=[])
         | 
| 83 | 
            +
            			@logger.info "Save environment to #{@vars[:vars_fil]}"
         | 
| 84 | 
            +
            			vstr = ['[global]']
         | 
| 85 | 
            +
            			ENV.to_hash.sort.each{|k,v|
         | 
| 86 | 
            +
            				vstr << %(#{k}="#{v}") unless ignored.include?(k)
         | 
| 87 | 
            +
            			}
         | 
| 88 | 
            +
             | 
| 89 | 
            +
            			IO.write(@vars[:vars_fil], vstr.join("\n"))
         | 
| 90 | 
            +
            		end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                # ---------------------------------------------------------------------------------------------------------------
         | 
| 93 | 
            +
                def saveBuild()
         | 
| 94 | 
            +
                  begin
         | 
| 95 | 
            +
                    raise 'ERROR: Checksum not read'       unless @vars.has_key?(:latest_sha)
         | 
| 96 | 
            +
                    raise 'ERROR: Checksum not calculated' unless @vars.has_key?(:build_sha)
         | 
| 97 | 
            +
                    change = false
         | 
| 98 | 
            +
                    if @vars[:latest_sha] != @vars[:build_sha]
         | 
| 99 | 
            +
                      change = true
         | 
| 100 | 
            +
                      @logger.info "CHANGE: Checksum [#{@vars[:latest_sha]}] => [#{@vars[:build_sha]}]"
         | 
| 101 | 
            +
                    end
         | 
| 102 | 
            +
                    if @vars[:latest_ver] != @vars[:build_ver]
         | 
| 103 | 
            +
                      change = true
         | 
| 104 | 
            +
                      @logger.info "CHANGE: Release [#{@vars[:latest_ver]}] => [#{@vars[:build_ver]}]"
         | 
| 105 | 
            +
                    end
         | 
| 106 | 
            +
                    unless File.file?(@vars[:build_pkg])
         | 
| 107 | 
            +
                      change = true
         | 
| 108 | 
            +
                      @logger.info "CHANGE: No #{@vars[:build_pkg]}"
         | 
| 109 | 
            +
                    end
         | 
| 110 | 
            +
                    unless File.symlink?(@vars[:latest_pkg])
         | 
| 111 | 
            +
                      change = true
         | 
| 112 | 
            +
                      @logger.info "CHANGE: No #{@vars[:latest_pkg]}"
         | 
| 113 | 
            +
                    end
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                    if change
         | 
| 116 | 
            +
                      if @vars[:latest_pkg] != @vars[:build_pkg]
         | 
| 117 | 
            +
                        @logger.info "Link #{@vars[:latest_pkg]} to #{@vars[:build_pkg]}"
         | 
| 118 | 
            +
                        begin
         | 
| 119 | 
            +
                          File.unlink(@vars[:latest_pkg])
         | 
| 120 | 
            +
                        rescue
         | 
| 121 | 
            +
                          # noop
         | 
| 122 | 
            +
                        end
         | 
| 123 | 
            +
                        File.symlink(@vars[:build_pkg], @vars[:latest_pkg])
         | 
| 124 | 
            +
                      end
         | 
| 125 | 
            +
                      @logger.info "Save latest build info to #{@vars[:latest_fil]}"
         | 
| 126 | 
            +
                      IO.write(@vars[:latest_fil], "#{@vars[:build_ver]}\n#{@vars[:build_sha]}")
         | 
| 127 | 
            +
                      saveEnvironment(['LS_COLORS','AWS_ACCESS_KEY_ID','AWS_SECRET_ACCESS_KEY'])
         | 
| 128 | 
            +
                      # NOTE the '.note'!
         | 
| 129 | 
            +
                      @logger.note "CHANGE: #{ENV['JOB_NAME']} (#{@vars[:build_ver]}[#{@vars[:build_sha]}])"
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                    else
         | 
| 132 | 
            +
                      @logger.info "Artifact #{@vars[:latest_pkg]} unchanged (#{@vars[:latest_ver]} [#{@vars[:latest_sha]}])"
         | 
| 133 | 
            +
                      @logger.info "NO_CHANGE: #{ENV['JOB_NAME']} #{@vars[:latest_ver]}"
         | 
| 134 | 
            +
                    end
         | 
| 135 | 
            +
                    @vars[:return_code] = 0
         | 
| 136 | 
            +
                  rescue => e
         | 
| 137 | 
            +
                    @logger.error "#{e.backtrace[0]}: #{e.class.name} #{e.message}"
         | 
| 138 | 
            +
                    @vars[:return_code] = 2
         | 
| 139 | 
            +
                  end
         | 
| 140 | 
            +
                  @vars[:return_code]
         | 
| 141 | 
            +
                end
         | 
| 142 | 
            +
             | 
| 143 | 
            +
                def reportResult()
         | 
| 144 | 
            +
                  if 0 == @vars[:return_code]
         | 
| 145 | 
            +
                    # NOTE the '.note'!
         | 
| 146 | 
            +
                    @logger.note  "CHANGE:  #{ENV['JOB_NAME']} #{ENV['BUILD_NUMBER']} #{@vars[:build_nam]} (#{@vars[:build_pkg]}) [#{@vars[:check_sha]}] => [#{@vars[:build_sha]}]"
         | 
| 147 | 
            +
                  else
         | 
| 148 | 
            +
                    @logger.error "FAILURE: #{ENV['JOB_NAME']} #{ENV['BUILD_NUMBER']} #{@vars[:build_pkg]} #{@vars[:return_code]}"
         | 
| 149 | 
            +
                  end
         | 
| 150 | 
            +
                end
         | 
| 151 | 
            +
             | 
| 152 | 
            +
            		# ---------------------------------------------------------------------------------------------------------------
         | 
| 153 | 
            +
            		def reportStatus(ignored=[])
         | 
| 154 | 
            +
                  # [2013-12-30 Christo] Report status,environment, etc.
         | 
| 155 | 
            +
             | 
| 156 | 
            +
            			if @logger.level < ::Logging::LEVELS['warn']
         | 
| 157 | 
            +
            				@logger.info '='*100
         | 
| 158 | 
            +
            				@logger.info Dir.getwd()
         | 
| 159 | 
            +
            				@logger.info '='*100
         | 
| 160 | 
            +
             | 
| 161 | 
            +
            				@logger.info "Config:"
         | 
| 162 | 
            +
            				@options.each{|k,v|
         | 
| 163 | 
            +
            					unless ignored.include?(k)
         | 
| 164 | 
            +
            						@logger.info sprintf("%25s: %s", "#{k.to_s}",  "#{v.to_s}")
         | 
| 165 | 
            +
            					end
         | 
| 166 | 
            +
            				}
         | 
| 167 | 
            +
             | 
| 168 | 
            +
            				@logger.info '='*100
         | 
| 169 | 
            +
             | 
| 170 | 
            +
            				@logger.info "Parameters:"
         | 
| 171 | 
            +
            				@vars.sort.each{|k,v|
         | 
| 172 | 
            +
            					unless ignored.include?(k)
         | 
| 173 | 
            +
            						@logger.info sprintf("%25s: %s", "#{k.to_s}",  "#{v.to_s}")
         | 
| 174 | 
            +
            					end
         | 
| 175 | 
            +
            				}
         | 
| 176 | 
            +
             | 
| 177 | 
            +
            				@logger.info '='*100
         | 
| 178 | 
            +
            			end
         | 
| 179 | 
            +
             | 
| 180 | 
            +
            			if @logger.level < ::Logging::LEVELS['info']
         | 
| 181 | 
            +
            				@logger.debug '='*100
         | 
| 182 | 
            +
            				@logger.debug "Environment:"
         | 
| 183 | 
            +
            				ENV.sort.each{|k,v|
         | 
| 184 | 
            +
            					unless ignored.include?(k)
         | 
| 185 | 
            +
            						@logger.debug sprintf("%25s: %s", "#{k.to_s}",  "#{v.to_s}")
         | 
| 186 | 
            +
            					end
         | 
| 187 | 
            +
            				}
         | 
| 188 | 
            +
             | 
| 189 | 
            +
            				@logger.debug '='*100
         | 
| 190 | 
            +
            			end
         | 
| 191 | 
            +
            		end
         | 
| 192 | 
            +
             | 
| 193 | 
            +
            	end
         | 
| 194 | 
            +
            end
         |