devinstall 1.1.0 → 1.2.0
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 +7 -0
- data/.gitignore +0 -1
- data/README.md +103 -2
- data/bin/pkg-tool +0 -1
- data/devinstall.gemspec +1 -1
- data/doc/example.yml +9 -4
- data/lib/devinstall/cli.rb +5 -7
- data/lib/devinstall/package.rb +87 -0
- data/lib/devinstall/pkg/pkg_deb.rb +31 -0
- data/lib/devinstall/provider/provider_ssh.rb +49 -0
- data/lib/devinstall/provider.rb +53 -0
- data/lib/devinstall/settings.rb +60 -63
- data/lib/devinstall/version.rb +1 -1
- data/lib/devinstall.rb +2 -1
- data/spec/pkg_spec.rb +16 -0
- data/spec/provider_spec.rb +14 -0
- data/spec/settings_spec.rb +30 -25
- metadata +26 -31
- data/lib/devinstall/pkg.rb +0 -178
    
        checksums.yaml
    ADDED
    
    | @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            SHA1:
         | 
| 3 | 
            +
              metadata.gz: fbc1a0725e5afda859bd39e8b8cfe23f97e22ff0
         | 
| 4 | 
            +
              data.tar.gz: 55490a5aba501da261edf43b83c66d3d72dc70a8
         | 
| 5 | 
            +
            SHA512:
         | 
| 6 | 
            +
              metadata.gz: b1fbbc6c8ab443b9cce341905d2507f884adf05bff1f47b030f5a47ec115a9622fd4ee385da61c4fcbb4cb31333b6386a030e5fe049c5e92978eaca82c7f99a5
         | 
| 7 | 
            +
              data.tar.gz: 6a3a3bfb5fdcc517e2b976a6e80fcca4665d236f96e216260d5e7dfe511c7e4187ff5cf40d310639806c2763efbb405187845692e325e61149597875c75e9d40
         | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -1,6 +1,10 @@ | |
| 1 | 
            -
            # Devinstall
         | 
| 1 | 
            +
            # Devinstall  [![Gem Version][GV img]][Gem Version]
         | 
| 2 2 |  | 
| 3 | 
            -
             | 
| 3 | 
            +
            [Gem Version]: https://rubygems.org/gems/devinstall
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            [GV img]: https://badge.fury.io/rb/devinstall.png
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            This is a poor man automatic package builder / installer / deployer.
         | 
| 4 8 |  | 
| 5 9 | 
             
            The build happens on a remote machine (in the future on several remote machines by package type)
         | 
| 6 10 | 
             
            via external tools rsync and ssh.
         | 
| @@ -75,6 +79,103 @@ or | |
| 75 79 |  | 
| 76 80 | 
             
            This will build and upload package "devinstall" to repository for dev-rh environment as defined in config.yml
         | 
| 77 81 |  | 
| 82 | 
            +
            ## The config file
         | 
| 83 | 
            +
             | 
| 84 | 
            +
            In order to set all the variables and to define commands to do when building or installing you need a configuration file.
         | 
| 85 | 
            +
             | 
| 86 | 
            +
            The said config file have simple YAML structure and should define the folowing parameters:
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                local:    
         | 
| 89 | 
            +
                  folder:
         | 
| 90 | 
            +
                  temp:
         | 
| 91 | 
            +
             | 
| 92 | 
            +
            The folder where the source/prepackaged files are on the local (developer) machine (`:folder`) and the
         | 
| 93 | 
            +
            temporary folder where the generated packages will be downloades
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                build:
         | 
| 96 | 
            +
                  folder: 
         | 
| 97 | 
            +
                  command:
         | 
| 98 | 
            +
                  provider:
         | 
| 99 | 
            +
                  type:
         | 
| 100 | 
            +
                  arch:
         | 
| 101 | 
            +
                  target:
         | 
| 102 | 
            +
                  env:
         | 
| 103 | 
            +
             | 
| 104 | 
            +
            In order:
         | 
| 105 | 
            +
             | 
| 106 | 
            +
              - the folder where the sources should be copied (might be ignored by some provider_plugins)
         | 
| 107 | 
            +
             | 
| 108 | 
            +
              - The command used to build the package (like `make package` or `dpkg-buildpackage`)
         | 
| 109 | 
            +
             | 
| 110 | 
            +
              - The provider for the build machine (like the `local` machine or another machine
         | 
| 111 | 
            +
              accessible only by SSH - `ssh` 
         | 
| 112 | 
            +
             | 
| 113 | 
            +
              - the package type ( `deb`ian, `rpm`, ...)
         | 
| 114 | 
            +
             | 
| 115 | 
            +
              - the architecture (might be ignored by some package_plugins)
         | 
| 116 | 
            +
             | 
| 117 | 
            +
              - and the folder where the package builder will put the builded packages
         | 
| 118 | 
            +
             | 
| 119 | 
            +
              - env define an environment (lyke `prod` or `QA`) for which the package will be built / installed
         | 
| 120 | 
            +
             | 
| 121 | 
            +
            Unlike the other parameters env is optional 
         | 
| 122 | 
            +
              
         | 
| 123 | 
            +
                install:
         | 
| 124 | 
            +
                  folder:
         | 
| 125 | 
            +
                  command:
         | 
| 126 | 
            +
                  provider:
         | 
| 127 | 
            +
                  type:
         | 
| 128 | 
            +
                  arch:
         | 
| 129 | 
            +
                  env:		
         | 
| 130 | 
            +
                repos:
         | 
| 131 | 
            +
                  folder:
         | 
| 132 | 
            +
                  provider:
         | 
| 133 | 
            +
                  type:
         | 
| 134 | 
            +
                  arch:
         | 
| 135 | 
            +
                  env:
         | 
| 136 | 
            +
                tests:
         | 
| 137 | 
            +
                  folder:
         | 
| 138 | 
            +
                  command:
         | 
| 139 | 
            +
                  provider
         | 
| 140 | 
            +
                  env:
         | 
| 141 | 
            +
                          
         | 
| 142 | 
            +
            The parameters have the same meaning as for `build:`
         | 
| 143 | 
            +
             `repos` reffers to the package repository
         | 
| 144 | 
            +
             `tests` is optional (DON'T do this) and no tests will be performend if it's missing
         | 
| 145 | 
            +
             | 
| 146 | 
            +
                defaults:
         | 
| 147 | 
            +
                  type:
         | 
| 148 | 
            +
                  env:
         | 
| 149 | 
            +
                          
         | 
| 150 | 
            +
            The default `type` and `env` if you don't use command-line switches
         | 
| 151 | 
            +
             | 
| 152 | 
            +
             | 
| 153 | 
            +
            The order in which the parameters will be searched is:
         | 
| 154 | 
            +
             | 
| 155 | 
            +
              - local
         | 
| 156 | 
            +
             | 
| 157 | 
            +
            Like:
         | 
| 158 | 
            +
             | 
| 159 | 
            +
                packages:
         | 
| 160 | 
            +
                  <package_name>:
         | 
| 161 | 
            +
                    <type>:
         | 
| 162 | 
            +
                      <section>:  # like build: or install:
         | 
| 163 | 
            +
                        <env>:
         | 
| 164 | 
            +
                          <parameter>: <value>
         | 
| 165 | 
            +
                        
         | 
| 166 | 
            +
                          
         | 
| 167 | 
            +
              - or global:
         | 
| 168 | 
            +
             | 
| 169 | 
            +
            Like
         | 
| 170 | 
            +
             | 
| 171 | 
            +
                  <section>:
         | 
| 172 | 
            +
                    <env>:
         | 
| 173 | 
            +
                      <parameter>: value
         | 
| 174 | 
            +
             | 
| 175 | 
            +
            The parameters speciffied per package have priority over the global ones
         | 
| 176 | 
            +
             | 
| 177 | 
            +
            In any case `env` is optional
         | 
| 178 | 
            +
             | 
| 78 179 | 
             
            ## Contributing
         | 
| 79 180 |  | 
| 80 181 | 
             
            1. Fork it
         | 
    
        data/bin/pkg-tool
    CHANGED
    
    
    
        data/devinstall.gemspec
    CHANGED
    
    | @@ -8,7 +8,7 @@ Gem::Specification.new do |spec| | |
| 8 8 | 
             
              spec.version       = Devinstall::VERSION
         | 
| 9 9 | 
             
              spec.authors       = ['Dragos Boca']
         | 
| 10 10 | 
             
              spec.email         = %w(dboca@mail.com)
         | 
| 11 | 
            -
              spec.description   = %q{ | 
| 11 | 
            +
              spec.description   = %q{OS package builder and installer}
         | 
| 12 12 | 
             
              spec.summary       = %q{Copy the source files to a build host, build the packages and install builded packages}
         | 
| 13 13 | 
             
              spec.homepage      = 'http://github.com/dboca/devinstall'
         | 
| 14 14 | 
             
              spec.license       = 'MIT'
         | 
    
        data/doc/example.yml
    CHANGED
    
    | @@ -19,6 +19,7 @@ tests: | |
| 19 19 | 
             
              dev: 
         | 
| 20 20 | 
             
                machine: dboca.dev.local
         | 
| 21 21 | 
             
                folder: rs
         | 
| 22 | 
            +
                target: rs ## this is a new addition
         | 
| 22 23 | 
             
                user: dboca
         | 
| 23 24 | 
             
                command: "cd %f && make devtest"
         | 
| 24 25 | 
             
            local:
         | 
| @@ -34,18 +35,19 @@ build: | |
| 34 35 | 
             
            # arch is the architecture for the generated package (like amd64 or i686)
         | 
| 35 36 | 
             
            # provider can be ssh or local (in the future vagrant and openstack)
         | 
| 36 37 | 
             
            # note: the ssh in provider have nothing to do with ssh command in base
         | 
| 37 | 
            -
              provider:  | 
| 38 | 
            +
              provider: local
         | 
| 38 39 | 
             
              user: dboca
         | 
| 39 40 | 
             
              host: vm-dboca.dev.local
         | 
| 40 41 | 
             
              folder: rs
         | 
| 41 42 | 
             
              target: rs
         | 
| 42 43 | 
             
              arch: all
         | 
| 44 | 
            +
              type: deb
         | 
| 43 45 | 
             
            install:
         | 
| 44 46 | 
             
            # host - dev/prod deploy and install host
         | 
| 45 47 | 
             
            # user - for scp / ssh / rsync  (defaults to base[user])
         | 
| 46 48 | 
             
            # environment - live/qa/dev/...
         | 
| 47 49 | 
             
              dev:
         | 
| 48 | 
            -
                provider: ssh  
         | 
| 50 | 
            +
                provider: ssh  ## Not implemented but compulsory for build, install, repos, tests
         | 
| 49 51 | 
             
                user: dboca
         | 
| 50 52 | 
             
                host:
         | 
| 51 53 | 
             
                  - server1.lan
         | 
| @@ -63,14 +65,17 @@ repos: | |
| 63 65 | 
             
                type: deb
         | 
| 64 66 | 
             
            packages:
         | 
| 65 67 | 
             
              devinstall:
         | 
| 66 | 
            -
            # might contain all the sections above (local, build, install, repos)
         | 
| 67 | 
            -
            # type and  | 
| 68 | 
            +
            # might contain all the sections above (local, build, install, repos, tests)
         | 
| 69 | 
            +
            # type:build:command and  type:install:command are mandatory
         | 
| 68 70 | 
             
            # in build_command the folowing expansions are made:
         | 
| 69 71 | 
             
            #  %f build[folder]
         | 
| 70 72 | 
             
            #  %t build[target]
         | 
| 71 73 | 
             
            #  %p package (current package)
         | 
| 72 74 | 
             
            #  %T type (deb, rpm, tar.gz ,...)
         | 
| 75 | 
            +
            #  %a only make sense for install and is the installed file
         | 
| 73 76 | 
             
                deb:
         | 
| 74 77 | 
             
                  build:
         | 
| 75 78 | 
             
                    command: "cd %f/%p && dpkg-buildpackage"
         | 
| 79 | 
            +
                  install:
         | 
| 80 | 
            +
                    command: "dpkg -i %a"
         | 
| 76 81 |  | 
    
        data/lib/devinstall/cli.rb
    CHANGED
    
    | @@ -1,4 +1,4 @@ | |
| 1 | 
            -
            require 'devinstall/ | 
| 1 | 
            +
            require 'devinstall/package'
         | 
| 2 2 | 
             
            require 'getopt/long'
         | 
| 3 3 | 
             
            require 'devinstall/settings'
         | 
| 4 4 | 
             
            require 'commander/import'
         | 
| @@ -37,7 +37,7 @@ module Cli | |
| 37 37 | 
             
                  env = options.env ? options.env.to_sym : config.defaults(:env)
         | 
| 38 38 |  | 
| 39 39 | 
             
                  args.each do |p|
         | 
| 40 | 
            -
                    pk=Devinstall:: | 
| 40 | 
            +
                    pk=Devinstall::Package.new(p, type, env)
         | 
| 41 41 | 
             
                    pk.build
         | 
| 42 42 | 
             
                  end
         | 
| 43 43 | 
             
                end
         | 
| @@ -51,7 +51,7 @@ module Cli | |
| 51 51 | 
             
                  env = options.env ? options.env.to_sym : config.defaults(:env)
         | 
| 52 52 |  | 
| 53 53 | 
             
                  args.each do |p|
         | 
| 54 | 
            -
                    pk=Devinstall:: | 
| 54 | 
            +
                    pk=Devinstall::Package.new(p, type, env)
         | 
| 55 55 | 
             
                    pk.build
         | 
| 56 56 | 
             
                    pk.install
         | 
| 57 57 | 
             
                  end
         | 
| @@ -66,7 +66,7 @@ module Cli | |
| 66 66 | 
             
                  env = options.env ? options.env.to_sym : config.defaults(:env)
         | 
| 67 67 |  | 
| 68 68 | 
             
                  args.each do |p|
         | 
| 69 | 
            -
                    pk=Devinstall:: | 
| 69 | 
            +
                    pk=Devinstall::Package.new(p, type, env)
         | 
| 70 70 | 
             
                    pk.run_tests
         | 
| 71 71 | 
             
                  end
         | 
| 72 72 | 
             
                end
         | 
| @@ -80,7 +80,7 @@ module Cli | |
| 80 80 | 
             
                  env = options.env ? options.env.to_sym : config.defaults(:env)
         | 
| 81 81 |  | 
| 82 82 | 
             
                  args.each do |p|
         | 
| 83 | 
            -
                    pk=Devinstall:: | 
| 83 | 
            +
                    pk=Devinstall::Package.new(p, type, env)
         | 
| 84 84 | 
             
                    pk.build
         | 
| 85 85 | 
             
                    pk.run_tests
         | 
| 86 86 | 
             
                    pk.upload
         | 
| @@ -90,5 +90,3 @@ module Cli | |
| 90 90 |  | 
| 91 91 | 
             
            end
         | 
| 92 92 |  | 
| 93 | 
            -
            __END__
         | 
| 94 | 
            -
             | 
| @@ -0,0 +1,87 @@ | |
| 1 | 
            +
            require 'devinstall/version'
         | 
| 2 | 
            +
            require 'devinstall/deep_symbolize'
         | 
| 3 | 
            +
            require 'devinstall/utils'
         | 
| 4 | 
            +
            require 'devinstall/settings'
         | 
| 5 | 
            +
            require 'devinstall/provider'
         | 
| 6 | 
            +
            require 'pp'
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            module Devinstall
         | 
| 9 | 
            +
              class UndeffError < RuntimeError;
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
             | 
| 13 | 
            +
              class Package
         | 
| 14 | 
            +
                include Utils
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                #noinspection RubyResolve
         | 
| 17 | 
            +
                def load_package_plugin(type)
         | 
| 18 | 
            +
                  require "devinstall/pkg/pkg_#{type.to_s}"
         | 
| 19 | 
            +
                  self.singleton_class.send(:include, Kernel.const_get("Pkg").const_get("#{type.to_s.capitalize}"))
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                def initialize(pkg, type, env)
         | 
| 23 | 
            +
                  @package, @type, @env = pkg, type, env
         | 
| 24 | 
            +
                  load_package_plugin(type)
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                def upload(pkg=@package, type=@type, env=@env)
         | 
| 28 | 
            +
                  uploader = Provider.new(pkg, type, env, :repos)
         | 
| 29 | 
            +
                  info = get_info(pkg, type, env)
         | 
| 30 | 
            +
                  info[:to_upload].each do |target|
         | 
| 31 | 
            +
                    puts "Uploading #{target.to_s}"
         | 
| 32 | 
            +
                    uploader.put_file(info[:files][target].to_s)
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
                rescue KeyNotDefinedError => e
         | 
| 35 | 
            +
                  puts e.message
         | 
| 36 | 
            +
                  raise "Error uploading #{pkg}"
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                def build(pkg=@package, type=@type, env=@env)
         | 
| 40 | 
            +
                  puts "Building package #{pkg} type #{type}"
         | 
| 41 | 
            +
                  info = get_info(pkg, type, env)
         | 
| 42 | 
            +
                  builder = Provider.new(pkg, type, env, :build)
         | 
| 43 | 
            +
                  builder.copy_sources
         | 
| 44 | 
            +
                  builder.do_action
         | 
| 45 | 
            +
                  info[:files].each do |target, file|
         | 
| 46 | 
            +
                    puts "Receiving target #{target.to_s} for #{file.to_s}"
         | 
| 47 | 
            +
                    builder.get_file(file)
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
                rescue KeyNotDefinedError => e
         | 
| 50 | 
            +
                  puts e.message
         | 
| 51 | 
            +
                  raise "Error uploading #{pkg}"
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                def install(pkg=@package, type=@type, env=@env)
         | 
| 55 | 
            +
                  puts "Installing #{pkg} in #{env} environment."
         | 
| 56 | 
            +
                  installer = Provider.new(pkg, type, env, :install)
         | 
| 57 | 
            +
                  info = get_info(pkg, type, env)
         | 
| 58 | 
            +
                  info[:to_install].each do |target| # upload each file to all targets
         | 
| 59 | 
            +
                    installer.put_file(info[:files][target])
         | 
| 60 | 
            +
                    installer.do_action(info[:files][target])
         | 
| 61 | 
            +
                  end
         | 
| 62 | 
            +
                rescue KeyNotDefinedError => e
         | 
| 63 | 
            +
                  puts e.message
         | 
| 64 | 
            +
                  raise "Error uploading #{pkg}"
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                def run_tests(pkg=@package, type=@type, env=@env)
         | 
| 68 | 
            +
                  config=Settings.instance
         | 
| 69 | 
            +
                  # check if we have the test section in the configuration file
         | 
| 70 | 
            +
                  unless config.respond_to? :tests
         | 
| 71 | 
            +
                    puts 'No test section in the config file.'
         | 
| 72 | 
            +
                    puts 'Skipping tests'
         | 
| 73 | 
            +
                    return
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
                  puts 'Running all tests'
         | 
| 76 | 
            +
                  puts 'This will take some time and you have no output'
         | 
| 77 | 
            +
                  tester = Provider.new(pkg, type, env, :tests)
         | 
| 78 | 
            +
                  tester.copy_sources
         | 
| 79 | 
            +
                  tester.do_action
         | 
| 80 | 
            +
                rescue KeyNotDefinedError => e
         | 
| 81 | 
            +
                  puts e.message
         | 
| 82 | 
            +
                  raise "Error uploading #{pkg}"
         | 
| 83 | 
            +
                end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
              end
         | 
| 86 | 
            +
            end
         | 
| 87 | 
            +
             | 
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            require 'devinstall/utils'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Pkg
         | 
| 4 | 
            +
              module Deb
         | 
| 5 | 
            +
            #  @type=:deb
         | 
| 6 | 
            +
                include Utils
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                def get_info(pkg, type, env)
         | 
| 9 | 
            +
                  config=Devinstall::Settings.instance
         | 
| 10 | 
            +
                  folder=config.local(:folder, pkg: pkg, type: type, env: env)
         | 
| 11 | 
            +
                  deb_changelog = File.expand_path "#{folder}/#{pkg}/debian/changelog"
         | 
| 12 | 
            +
                  unless File.exists? deb_changelog
         | 
| 13 | 
            +
                    exit! "No 'debian/changelog' found in specified :local:folder (#{folder})"
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
                  package_version = File.open(deb_changelog, 'r') { |f| f.gets.chomp.sub(/^.*\((.*)\).*$/, '\1') }
         | 
| 16 | 
            +
                  p_name = "#{pkg}_#{package_version}"
         | 
| 17 | 
            +
                  arch = config.build(pkg: pkg, type: type, env: env)[:arch]
         | 
| 18 | 
            +
                  {version: package_version,
         | 
| 19 | 
            +
                   files:
         | 
| 20 | 
            +
                       {deb: "#{p_name}_#{arch}.deb",
         | 
| 21 | 
            +
                        tgz: "#{p_name}.tar.gz",
         | 
| 22 | 
            +
                        dsc: "#{p_name}.dsc",
         | 
| 23 | 
            +
                        chg: "#{p_name}_amd64.changes"},
         | 
| 24 | 
            +
                   to_install: [:deb],
         | 
| 25 | 
            +
                   to_upload: [:deb, :tgz, :dsc, :chg]
         | 
| 26 | 
            +
                  }
         | 
| 27 | 
            +
                rescue IOError => e
         | 
| 28 | 
            +
                  exit! "IO Error while opening #{deb_changelog}\n Aborting \n #{e.message}"
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
            end
         | 
| @@ -0,0 +1,49 @@ | |
| 1 | 
            +
            require 'devinstall/utils'
         | 
| 2 | 
            +
            require 'devinstall/settings'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module Provider
         | 
| 5 | 
            +
              module Ssh
         | 
| 6 | 
            +
                include Utils
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                SETTINGS = {
         | 
| 9 | 
            +
                    build:   [:user, :host],
         | 
| 10 | 
            +
                    install: [:user, :host],
         | 
| 11 | 
            +
                    tests:   [:user, :host],
         | 
| 12 | 
            +
                    repos:   [:user, :host],
         | 
| 13 | 
            +
                    ssh:     [:ssh, :scp, :rsync, :sudo]
         | 
| 14 | 
            +
                }
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                def upload_sources(cfg, src, dst)
         | 
| 17 | 
            +
                  config =Devinstall::Settings.instance
         | 
| 18 | 
            +
                  rsync  = config.ssh(:rsync)
         | 
| 19 | 
            +
                  source = src[-1]=='/' ? src : "#{src}/"       # source folder(we add / because we are using rsync)
         | 
| 20 | 
            +
                  dest   = "#{cfg[:user]}@#{cfg[:host]}:#{dst}" # cfg should provide user and host
         | 
| 21 | 
            +
                  command("#{rsync} #{source} #{dest}")
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                def download_file(cfg, file, local)
         | 
| 25 | 
            +
                  config=Devinstall::Settings.instance
         | 
| 26 | 
            +
                  rsync = config.ssh(:rsync) # should be config.provider[:ssh][:rsync]
         | 
| 27 | 
            +
                  command("#{rsync} -az #{cfg[:user]}@#{cfg[:host]}:#{cfg[:target]}/#{file.to_s} #{local}")
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                def upload_file(cfg, file, local)
         | 
| 31 | 
            +
                  config=Devinstall::Settings.instance
         | 
| 32 | 
            +
                  scp   = config.ssh(:scp) # should be config.provider[:ssh][:scp]
         | 
| 33 | 
            +
                  hosts = Array === cfg[:host] ? cfg[:host] : [cfg[:host]]
         | 
| 34 | 
            +
                  hosts.each do |host|
         | 
| 35 | 
            +
                    command("#{scp} #{local}/#{file} #{cfg[:user]}@#{host}:#{cfg[:folder]}")
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                def exec_command(cfg, command)
         | 
| 40 | 
            +
                  config=Devinstall::Settings.instance
         | 
| 41 | 
            +
                  ssh   = config.ssh(:ssh) # should be config.provider[:ssh][:scp]
         | 
| 42 | 
            +
                  hosts = Array === cfg[:host] ? cfg[:host] : [cfg[:host]]
         | 
| 43 | 
            +
                  hosts.each do |host|
         | 
| 44 | 
            +
                    command("#{ssh} #{cfg[:user]}@#{host} \"#{command}\"")
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
            end
         | 
| @@ -0,0 +1,53 @@ | |
| 1 | 
            +
            module Devinstall
         | 
| 2 | 
            +
              class Provider
         | 
| 3 | 
            +
             | 
| 4 | 
            +
                #noinspection RubyResolve
         | 
| 5 | 
            +
                def initialize(pkg, type, env, action=nil)
         | 
| 6 | 
            +
                  providers={build: :build, install: :install, upload: :repos, run_tests: :tests}
         | 
| 7 | 
            +
                  @pkg, @type, @env = (pkg.to_sym rescue pkg), (type.to_sym rescue type), (env.to_sym rescue env)
         | 
| 8 | 
            +
                  @action           = action || providers[caller_locations(1, 1)[0].label.to_sym] # that's realy stupid!
         | 
| 9 | 
            +
                  provider          = Settings.instance.send(action, :provider, pkg: pkg, type: type, env: env)
         | 
| 10 | 
            +
                  require "devinstall/provider/provider_#{provider}"
         | 
| 11 | 
            +
                  self.singleton_class.send(:include, Kernel.const_get('Provider').const_get("#{provider.capitalize}"))
         | 
| 12 | 
            +
                  provider_settings=Kernel.const_get('Provider').const_get("#{provider.capitalize}")::SETTINGS
         | 
| 13 | 
            +
                  Settings.instance.register_provider(provider.to_sym, provider_settings)
         | 
| 14 | 
            +
                  ObjectSpace.define_finalizer(self, Proc.new{Settings.instance.unregister_provider(provider)})
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                def copy_sources # that's upload sources
         | 
| 18 | 
            +
                  config = Settings.instance
         | 
| 19 | 
            +
                  remote = config.send(@action, :folder, pkg: @pkg, type: @type, env: @env)
         | 
| 20 | 
            +
                  local  = File.expand_path config.local(:folder, pkg: @pkg, type: @type, env: @env)
         | 
| 21 | 
            +
                  cfg    = config.send(@action, pkg: @pkg, type: @type, env: @env)
         | 
| 22 | 
            +
                  upload_sources(cfg, local, remote)
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                def get_file(file)
         | 
| 26 | 
            +
                  config = Settings.instance
         | 
| 27 | 
            +
                  local  = File.expand_path config.local(:temp, pkg: @pkg, type: @type, env: @env)
         | 
| 28 | 
            +
                  cfg    = config.send(@action, pkg: @pkg, type: @type, env: @env)
         | 
| 29 | 
            +
                  download_file(cfg, file, local)
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                def put_file(file)
         | 
| 33 | 
            +
                  config = Settings.instance
         | 
| 34 | 
            +
                  local  = File.expand_path config.local(:temp, pkg: @pkg, type: @type, env: @env)
         | 
| 35 | 
            +
                  cfg    = config.send(@action, pkg: @pkg, type: @type, env: @env)
         | 
| 36 | 
            +
                  upload_file(cfg, file, local)
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                def do_action(to=nil)
         | 
| 40 | 
            +
                  config  = Settings.instance
         | 
| 41 | 
            +
                  cfg     =config.send(@action, pkg: @pkg, type: @type, env: @env)
         | 
| 42 | 
            +
                  command = cfg[:command].
         | 
| 43 | 
            +
                      gsub('%f', cfg[:folder]).
         | 
| 44 | 
            +
                      gsub('%p', @pkg.to_s).
         | 
| 45 | 
            +
                      gsub('%T', @type.to_s)
         | 
| 46 | 
            +
                  command = command.gsub('%t', cfg[:target]) if cfg.has_key? :target
         | 
| 47 | 
            +
                  command = command.gsub('%a', to) unless to.nil?
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  exec_command(cfg, command)
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
              end
         | 
| 53 | 
            +
            end
         | 
    
        data/lib/devinstall/settings.rb
    CHANGED
    
    | @@ -8,65 +8,55 @@ class Hash | |
| 8 8 | 
             
            end
         | 
| 9 9 |  | 
| 10 10 |  | 
| 11 | 
            -
             | 
| 12 11 | 
             
            module Devinstall
         | 
| 13 12 |  | 
| 14 | 
            -
            class KeyNotDefinedError < RuntimeError | 
| 15 | 
            -
             | 
| 13 | 
            +
              class KeyNotDefinedError < RuntimeError
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
              class UnknownKeyError < RuntimeError
         | 
| 16 | 
            +
              end
         | 
| 16 17 |  | 
| 17 18 | 
             
              class Settings
         | 
| 18 19 | 
             
                include Singleton
         | 
| 19 20 |  | 
| 20 | 
            -
                FILES | 
| 21 | 
            -
                SETTINGS | 
| 22 | 
            -
                MDEFS={
         | 
| 23 | 
            -
                    local: | 
| 24 | 
            -
                    build: | 
| 25 | 
            -
                    install: | 
| 26 | 
            -
                    tests: | 
| 27 | 
            -
                    repos: | 
| 21 | 
            +
                FILES     = []
         | 
| 22 | 
            +
                SETTINGS  = {}
         | 
| 23 | 
            +
                MDEFS     = {
         | 
| 24 | 
            +
                    local:    [:folder, :temp],
         | 
| 25 | 
            +
                    build:    [:folder, :command, :provider, :type, :arch, :target],
         | 
| 26 | 
            +
                    install:  [:folder, :command, :provider, :type, :arch],
         | 
| 27 | 
            +
                    tests:    [:folder, :command, :provider],
         | 
| 28 | 
            +
                    repos:    [:folder, :provider, :type, :arch],
         | 
| 29 | 
            +
                    defaults: [:type, :env]
         | 
| 28 30 | 
             
                }
         | 
| 29 | 
            -
             | 
| 31 | 
            +
                PROVIDERS = {}
         | 
| 30 32 | 
             
                class Action
         | 
| 31 33 | 
             
                  include Enumerable
         | 
| 32 34 |  | 
| 33 | 
            -
                  def initialize( | 
| 34 | 
            -
                    @ | 
| 35 | 
            -
                    @sect=sect
         | 
| 36 | 
            -
                    @pkg=pkg
         | 
| 37 | 
            -
                    @type=type
         | 
| 38 | 
            -
                    @env=env
         | 
| 35 | 
            +
                  def initialize(m, pkg, type, env)
         | 
| 36 | 
            +
                    @method, @pkg, @type, @env = (m.to_sym rescue m), (pkg.to_sym rescue pkg), (type.to_sym rescue type), (env.to_sym rescue env)
         | 
| 39 37 | 
             
                  end
         | 
| 40 38 |  | 
| 41 | 
            -
                  def  | 
| 42 | 
            -
                     | 
| 43 | 
            -
                    return false unless Settings::MDEFS.has_key? @sect
         | 
| 44 | 
            -
                    Settings::MDEFS[@sect].inject (true) do |res, k|
         | 
| 45 | 
            -
                      res and config.respond_to? @sect and config.send(@sect, k, pkg: @pkg, type: @type, env: @env)
         | 
| 46 | 
            -
                    end
         | 
| 47 | 
            -
                  rescue KeyNotDefinedError => e
         | 
| 48 | 
            -
                    puts e.message
         | 
| 49 | 
            -
                    puts e.backtrace if $verbose
         | 
| 50 | 
            -
                    return false
         | 
| 39 | 
            +
                  def has_key?(key)
         | 
| 40 | 
            +
                    Settings.instance.send(@method, key, pkg: @pkg, type: @type, env: @env) rescue false
         | 
| 51 41 | 
             
                  end
         | 
| 52 42 |  | 
| 53 43 | 
             
                  def [](key)
         | 
| 54 | 
            -
                    Settings.instance.send(@ | 
| 44 | 
            +
                    Settings.instance.send(@method, key, pkg: @pkg, type: @type, env: @env)
         | 
| 55 45 | 
             
                  end
         | 
| 56 46 |  | 
| 57 47 | 
             
                  def each
         | 
| 58 48 | 
             
                    config=Settings.instance
         | 
| 59 | 
            -
                    Settings::MDEFS[@ | 
| 60 | 
            -
                      yield(key, config.send(@ | 
| 49 | 
            +
                    Settings::MDEFS[@method].each do |key|
         | 
| 50 | 
            +
                      yield(key, config.send(@method, key, pkg: @pkg, type: @type, env: @env)) if block_given?
         | 
| 61 51 | 
             
                    end
         | 
| 62 52 | 
             
                  end
         | 
| 63 | 
            -
                end | 
| 53 | 
            +
                end ## Class Action
         | 
| 64 54 |  | 
| 65 55 | 
             
                def load! (filename)
         | 
| 66 56 | 
             
                  if File.exist?(File.expand_path(filename))
         | 
| 67 57 | 
             
                    unless FILES.include? filename
         | 
| 68 58 | 
             
                      FILES << filename
         | 
| 69 | 
            -
                      data | 
| 59 | 
            +
                      data   = YAML::load_file(filename).deep_symbolize
         | 
| 70 60 | 
             
                      merger = proc do |_, v1, v2|
         | 
| 71 61 | 
             
                        Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2
         | 
| 72 62 | 
             
                      end
         | 
| @@ -75,40 +65,33 @@ class UnknownKeyError < RuntimeError;end | |
| 75 65 | 
             
                  end
         | 
| 76 66 | 
             
                end
         | 
| 77 67 |  | 
| 78 | 
            -
                def  | 
| 79 | 
            -
                   | 
| 80 | 
            -
                   | 
| 81 | 
            -
                   | 
| 82 | 
            -
                   | 
| 68 | 
            +
                def method_missing (method, *args)
         | 
| 69 | 
            +
                  raise UnknownKeyError, "Undefined section '#{method}'" unless method_defined? method
         | 
| 70 | 
            +
                  key  = (args.shift or {})
         | 
| 71 | 
            +
                  rest = (Hash === key) ? key : (args.shift or {})
         | 
| 72 | 
            +
                  pkg = rest[:pkg]
         | 
| 73 | 
            +
                  if pkg.nil?
         | 
| 74 | 
            +
                   raise UnknownKeyError, "Unknown key #{key}" unless key_defined? method,key
         | 
| 75 | 
            +
                   return SETTINGS[method][key] rescue raise "#{method}: Package must be defined"
         | 
| 76 | 
            +
                  end
         | 
| 77 | 
            +
                  type = rest[:type] || defaults(:type)
         | 
| 78 | 
            +
                  env  = rest[:env] || defaults(:env)
         | 
| 79 | 
            +
                  return Action.new(method, pkg, type, env) if Hash === key
         | 
| 80 | 
            +
                  raise UnknownKeyError, "Unknown key #{key}" unless key_defined? method,key
         | 
| 81 | 
            +
                  global_or_local(method, key, pkg, type, env) or
         | 
| 82 | 
            +
                      raise KeyNotDefinedError, "Undefined key '#{method}:#{key}' or alternate for ['#{pkg}' '#{type}' '#{env}']"
         | 
| 83 83 | 
             
                end
         | 
| 84 84 |  | 
| 85 | 
            -
                def  | 
| 86 | 
            -
                   | 
| 87 | 
            -
                  raise UnknownKeyError, "Unknown key: '#{key}'" unless [:rsync, :ssh, :sudo, :scp].include? key
         | 
| 88 | 
            -
                  return nil unless key_chain(:base, key)
         | 
| 89 | 
            -
                  SETTINGS[:base][key] or raise KeyNotDefinedError, "Undefined key :base:#{key.to_s}"
         | 
| 85 | 
            +
                def respond_to_missing?(method, _)
         | 
| 86 | 
            +
                  method_defined? method
         | 
| 90 87 | 
             
                end
         | 
| 91 88 |  | 
| 92 | 
            -
                def  | 
| 93 | 
            -
                   | 
| 94 | 
            -
                  key=(args.shift or {})
         | 
| 95 | 
            -
                  if Hash === key
         | 
| 96 | 
            -
                    pkg = key[:pkg] or raise 'package must be defined'
         | 
| 97 | 
            -
                    type = (key[:type] or defaults(:type))
         | 
| 98 | 
            -
                    env = (key[:env] or defaults(:env))
         | 
| 99 | 
            -
                    return Action.new(SETTINGS, m, pkg, type, env)
         | 
| 100 | 
            -
                  end
         | 
| 101 | 
            -
                  rest=(args.shift or {})
         | 
| 102 | 
            -
                  (pkg = rest[:pkg]) or raise 'package must be defined'
         | 
| 103 | 
            -
                  type = (rest[:type] or defaults(:type))
         | 
| 104 | 
            -
                  env = (rest[:env] or defaults(:env))
         | 
| 105 | 
            -
                  pkg=pkg.to_sym
         | 
| 106 | 
            -
                  raise UnknownKeyError, "Unknown key #{key}" unless MDEFS[m].include? key
         | 
| 107 | 
            -
                  global_or_local(m, key, pkg, type, env) or raise KeyNotDefinedError, "Undefined key '#{m}:#{key}' or alternate for ['#{pkg}' '#{type}' '#{env}']"
         | 
| 89 | 
            +
                def register_provider(provider, methods)
         | 
| 90 | 
            +
                  PROVIDERS[provider]=methods
         | 
| 108 91 | 
             
                end
         | 
| 109 92 |  | 
| 110 | 
            -
                def  | 
| 111 | 
            -
                   | 
| 93 | 
            +
                def unregister_provider(provider)
         | 
| 94 | 
            +
                  PROVIDERS.delete(provider)
         | 
| 112 95 | 
             
                end
         | 
| 113 96 |  | 
| 114 97 | 
             
                private
         | 
| @@ -117,8 +100,8 @@ class UnknownKeyError < RuntimeError;end | |
| 117 100 | 
             
                  res=SETTINGS
         | 
| 118 101 | 
             
                  keys.each do |key|
         | 
| 119 102 | 
             
                    next if key.nil?
         | 
| 120 | 
            -
                    return nil unless res.has_key? key
         | 
| 121 | 
            -
                    res=res[key]
         | 
| 103 | 
            +
                    return nil unless res.has_key? key.to_sym
         | 
| 104 | 
            +
                    res=res[key.to_sym]
         | 
| 122 105 | 
             
                  end
         | 
| 123 106 | 
             
                  res
         | 
| 124 107 | 
             
                end
         | 
| @@ -130,6 +113,20 @@ class UnknownKeyError < RuntimeError;end | |
| 130 113 | 
             
                      key_chain(section, key)
         | 
| 131 114 | 
             
                end
         | 
| 132 115 |  | 
| 116 | 
            +
                def key_defined?(method, key)
         | 
| 117 | 
            +
                  method, key = (method.to_sym rescue method), (key.to_sym rescue key)
         | 
| 118 | 
            +
                  method_defined? method and
         | 
| 119 | 
            +
                  (MDEFS[method].include? key rescue false) or
         | 
| 120 | 
            +
                      PROVIDERS.inject(false){|res,(_,v)| res or (v[method].include? key rescue false)}
         | 
| 121 | 
            +
                end
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                def method_defined?(method)
         | 
| 124 | 
            +
                  method = (method.to_sym rescue method)
         | 
| 125 | 
            +
                  (MDEFS.has_key?(method) or
         | 
| 126 | 
            +
                      PROVIDERS.inject(false){|res,(k,_)| res or PROVIDERS[k].has_key? method}) and
         | 
| 127 | 
            +
                      SETTINGS.has_key? method
         | 
| 128 | 
            +
                end
         | 
| 129 | 
            +
             | 
| 133 130 | 
             
              end
         | 
| 134 131 | 
             
            end
         | 
| 135 132 |  | 
    
        data/lib/devinstall/version.rb
    CHANGED
    
    
    
        data/lib/devinstall.rb
    CHANGED
    
    
    
        data/spec/pkg_spec.rb
    ADDED
    
    | @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            require 'rspec'
         | 
| 2 | 
            +
            require 'devinstall'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            describe 'Packages' do
         | 
| 5 | 
            +
              config=Devinstall::Settings.instance
         | 
| 6 | 
            +
              config.load! './doc/example.yml' ## use defaults for type and env
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              package=:devinstall
         | 
| 9 | 
            +
              type=:deb
         | 
| 10 | 
            +
              env=nil
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              it 'should include the correct file' do
         | 
| 13 | 
            +
                pk=Devinstall::Package.new(package, type, env)
         | 
| 14 | 
            +
                expect(pk.singleton_class.include?(Pkg::Deb)).to be_true
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
            end
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            require 'rspec'
         | 
| 2 | 
            +
            require 'devinstall'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            describe 'Provider' do
         | 
| 5 | 
            +
              before do
         | 
| 6 | 
            +
              @package, @type, @env, @action = :devinstall, :deb, :dev, :install
         | 
| 7 | 
            +
            #  config=Devinstall::Settings.instance
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              it 'should load the correct (Provider::Ssh) plugin' do
         | 
| 11 | 
            +
                provider = Devinstall::Provider.new(@package, @type, @env, @action)
         | 
| 12 | 
            +
                expect(provider.singleton_class.include? Provider::Ssh).to be_true
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
            end
         | 
    
        data/spec/settings_spec.rb
    CHANGED
    
    | @@ -10,6 +10,8 @@ describe 'Settings' do | |
| 10 10 | 
             
              type=:deb
         | 
| 11 11 | 
             
              env=nil
         | 
| 12 12 |  | 
| 13 | 
            +
              $verbose=true
         | 
| 14 | 
            +
             | 
| 13 15 | 
             
              it 'should load an existig file' do
         | 
| 14 16 | 
             
                expect(config.load!('doc/example.yml')).to be_true
         | 
| 15 17 | 
             
              end
         | 
| @@ -20,56 +22,59 @@ describe 'Settings' do | |
| 20 22 |  | 
| 21 23 | 
             
              it 'should load at init' do
         | 
| 22 24 | 
             
                expect(config).to be_an_instance_of(Devinstall::Settings)
         | 
| 23 | 
            -
                [:defaults, : | 
| 25 | 
            +
                [:defaults, :local, :build, :install, :tests, :repos].each do |p|
         | 
| 24 26 | 
             
                  expect(config.respond_to? p).to be_true
         | 
| 25 27 | 
             
                end # all sections loaded!
         | 
| 26 28 | 
             
              end
         | 
| 27 29 |  | 
| 28 | 
            -
              it 'should have defaults' do
         | 
| 29 | 
            -
                expect(config.defaults).to be_true
         | 
| 30 | 
            -
              end
         | 
| 31 | 
            -
             | 
| 32 | 
            -
              it 'should produce validators when hashes are given' do
         | 
| 33 | 
            -
                expect(config.build(type:'deb', env:'dev', pkg:package)).to be_an_instance_of(Devinstall::Settings::Action)
         | 
| 30 | 
            +
              it 'should have a method defaults' do
         | 
| 31 | 
            +
                expect(config.respond_to? :defaults).to be_true
         | 
| 34 32 | 
             
              end
         | 
| 35 33 |  | 
| 36 | 
            -
              it ' | 
| 37 | 
            -
                expect(config. | 
| 34 | 
            +
              it 'the method "defaults" should have only one argument' do
         | 
| 35 | 
            +
                expect(config.defaults(:type)).to eq "deb"
         | 
| 38 36 | 
             
              end
         | 
| 39 37 |  | 
| 40 | 
            -
              it 'should  | 
| 41 | 
            -
                expect( | 
| 42 | 
            -
                expect(rr.valid?).to be_true
         | 
| 38 | 
            +
              it 'should instantiate a new "Action" when hashes are given' do
         | 
| 39 | 
            +
                expect(config.build(type:'deb', env:'dev', pkg:package)).to be_an_instance_of(Devinstall::Settings::Action)
         | 
| 43 40 | 
             
              end
         | 
| 44 41 |  | 
| 45 | 
            -
              it 'should  | 
| 46 | 
            -
                expect( | 
| 47 | 
            -
                expect(rr.valid?).to be_false
         | 
| 42 | 
            +
              it 'should instantiata a new "Action" when partial hashes are given' do
         | 
| 43 | 
            +
                expect(config.build(pkg:package)).to be_an_instance_of(Devinstall::Settings::Action)
         | 
| 48 44 | 
             
              end
         | 
| 49 45 |  | 
| 50 | 
            -
              it 'should raise errors for unknown keys' do
         | 
| 46 | 
            +
              it 'should raise "UnknownKeys" errors for unknown keys' do
         | 
| 51 47 | 
             
                expect{config.defaults :none}.to raise_error(Devinstall::UnknownKeyError)
         | 
| 52 48 | 
             
              end
         | 
| 53 49 |  | 
| 54 | 
            -
              it 'should raise errors for undefined keys' do
         | 
| 50 | 
            +
              it 'should raise "KeyNotDefinedError" errors for undefined keys' do
         | 
| 55 51 | 
             
                expect{config.tests(:provider, pkg:package)}.to raise_error(Devinstall::KeyNotDefinedError)
         | 
| 56 52 | 
             
              end
         | 
| 57 53 |  | 
| 58 | 
            -
              it 'should produce a value if  | 
| 59 | 
            -
                expect(config.build(: | 
| 54 | 
            +
              it 'should produce a value if all arguments are valid' do
         | 
| 55 | 
            +
                expect(config.build(:command, pkg:package)).to eq('cd %f/%p && dpkg-buildpackage')
         | 
| 60 56 | 
             
              end
         | 
| 57 | 
            +
            end
         | 
| 58 | 
            +
            describe "Action" do
         | 
| 59 | 
            +
              config=Devinstall::Settings.instance
         | 
| 60 | 
            +
              config.load! './doc/example.yml' ## use defaults for type and env
         | 
| 61 | 
            +
             | 
| 62 | 
            +
              package=:devinstall
         | 
| 63 | 
            +
              type=:deb
         | 
| 64 | 
            +
              env=nil
         | 
| 61 65 |  | 
| 62 | 
            -
               | 
| 66 | 
            +
              $verbose=true
         | 
| 67 | 
            +
             | 
| 68 | 
            +
              it 'should have a [] method' do
         | 
| 63 69 | 
             
                rr=config.build(pkg:package, type:type, env:env)
         | 
| 64 | 
            -
                expect(rr[: | 
| 70 | 
            +
                expect(rr[:target]).to eq('rs')
         | 
| 65 71 | 
             
              end
         | 
| 66 72 |  | 
| 67 73 | 
             
              it 'should enumerate all defined values' do
         | 
| 68 74 | 
             
                ar=[]
         | 
| 69 | 
            -
                config.build(pkg:package, type:type, env:env).each do |k, | 
| 70 | 
            -
             | 
| 75 | 
            +
                config.build(pkg:package, type:type, env:env).each do |k,_|
         | 
| 76 | 
            +
                  ar << k
         | 
| 71 77 | 
             
                end
         | 
| 72 | 
            -
                expect(ar | 
| 78 | 
            +
                expect(ar.sort == [:folder, :command, :provider, :type, :arch, :target].sort ).to be_true
         | 
| 73 79 | 
             
              end
         | 
| 74 | 
            -
             | 
| 75 80 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,97 +1,86 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: devinstall
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1. | 
| 5 | 
            -
              prerelease: 
         | 
| 4 | 
            +
              version: 1.2.0
         | 
| 6 5 | 
             
            platform: ruby
         | 
| 7 6 | 
             
            authors:
         | 
| 8 7 | 
             
            - Dragos Boca
         | 
| 9 8 | 
             
            autorequire: 
         | 
| 10 9 | 
             
            bindir: bin
         | 
| 11 10 | 
             
            cert_chain: []
         | 
| 12 | 
            -
            date: 2013-05- | 
| 11 | 
            +
            date: 2013-05-05 00:00:00.000000000 Z
         | 
| 13 12 | 
             
            dependencies:
         | 
| 14 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 14 | 
             
              name: bundler
         | 
| 16 15 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 17 | 
            -
                none: false
         | 
| 18 16 | 
             
                requirements:
         | 
| 19 | 
            -
                - -  | 
| 17 | 
            +
                - - '>='
         | 
| 20 18 | 
             
                  - !ruby/object:Gem::Version
         | 
| 21 19 | 
             
                    version: '0'
         | 
| 22 20 | 
             
              type: :development
         | 
| 23 21 | 
             
              prerelease: false
         | 
| 24 22 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 25 | 
            -
                none: false
         | 
| 26 23 | 
             
                requirements:
         | 
| 27 | 
            -
                - -  | 
| 24 | 
            +
                - - '>='
         | 
| 28 25 | 
             
                  - !ruby/object:Gem::Version
         | 
| 29 26 | 
             
                    version: '0'
         | 
| 30 27 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 31 28 | 
             
              name: rake
         | 
| 32 29 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 33 | 
            -
                none: false
         | 
| 34 30 | 
             
                requirements:
         | 
| 35 | 
            -
                - -  | 
| 31 | 
            +
                - - '>='
         | 
| 36 32 | 
             
                  - !ruby/object:Gem::Version
         | 
| 37 33 | 
             
                    version: '0'
         | 
| 38 34 | 
             
              type: :development
         | 
| 39 35 | 
             
              prerelease: false
         | 
| 40 36 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 41 | 
            -
                none: false
         | 
| 42 37 | 
             
                requirements:
         | 
| 43 | 
            -
                - -  | 
| 38 | 
            +
                - - '>='
         | 
| 44 39 | 
             
                  - !ruby/object:Gem::Version
         | 
| 45 40 | 
             
                    version: '0'
         | 
| 46 41 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 47 42 | 
             
              name: getopt
         | 
| 48 43 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 49 | 
            -
                none: false
         | 
| 50 44 | 
             
                requirements:
         | 
| 51 | 
            -
                - -  | 
| 45 | 
            +
                - - '>='
         | 
| 52 46 | 
             
                  - !ruby/object:Gem::Version
         | 
| 53 47 | 
             
                    version: '0'
         | 
| 54 48 | 
             
              type: :development
         | 
| 55 49 | 
             
              prerelease: false
         | 
| 56 50 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 57 | 
            -
                none: false
         | 
| 58 51 | 
             
                requirements:
         | 
| 59 | 
            -
                - -  | 
| 52 | 
            +
                - - '>='
         | 
| 60 53 | 
             
                  - !ruby/object:Gem::Version
         | 
| 61 54 | 
             
                    version: '0'
         | 
| 62 55 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 63 56 | 
             
              name: rspec
         | 
| 64 57 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 65 | 
            -
                none: false
         | 
| 66 58 | 
             
                requirements:
         | 
| 67 | 
            -
                - -  | 
| 59 | 
            +
                - - '>='
         | 
| 68 60 | 
             
                  - !ruby/object:Gem::Version
         | 
| 69 61 | 
             
                    version: '0'
         | 
| 70 62 | 
             
              type: :development
         | 
| 71 63 | 
             
              prerelease: false
         | 
| 72 64 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 73 | 
            -
                none: false
         | 
| 74 65 | 
             
                requirements:
         | 
| 75 | 
            -
                - -  | 
| 66 | 
            +
                - - '>='
         | 
| 76 67 | 
             
                  - !ruby/object:Gem::Version
         | 
| 77 68 | 
             
                    version: '0'
         | 
| 78 69 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 79 70 | 
             
              name: commander
         | 
| 80 71 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 81 | 
            -
                none: false
         | 
| 82 72 | 
             
                requirements:
         | 
| 83 | 
            -
                - -  | 
| 73 | 
            +
                - - '>='
         | 
| 84 74 | 
             
                  - !ruby/object:Gem::Version
         | 
| 85 75 | 
             
                    version: '0'
         | 
| 86 76 | 
             
              type: :development
         | 
| 87 77 | 
             
              prerelease: false
         | 
| 88 78 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 89 | 
            -
                none: false
         | 
| 90 79 | 
             
                requirements:
         | 
| 91 | 
            -
                - -  | 
| 80 | 
            +
                - - '>='
         | 
| 92 81 | 
             
                  - !ruby/object:Gem::Version
         | 
| 93 82 | 
             
                    version: '0'
         | 
| 94 | 
            -
            description:  | 
| 83 | 
            +
            description: OS package builder and installer
         | 
| 95 84 | 
             
            email:
         | 
| 96 85 | 
             
            - dboca@mail.com
         | 
| 97 86 | 
             
            executables:
         | 
| @@ -111,36 +100,42 @@ files: | |
| 111 100 | 
             
            - lib/devinstall.rb
         | 
| 112 101 | 
             
            - lib/devinstall/cli.rb
         | 
| 113 102 | 
             
            - lib/devinstall/deep_symbolize.rb
         | 
| 114 | 
            -
            - lib/devinstall/ | 
| 103 | 
            +
            - lib/devinstall/package.rb
         | 
| 104 | 
            +
            - lib/devinstall/pkg/pkg_deb.rb
         | 
| 105 | 
            +
            - lib/devinstall/provider.rb
         | 
| 106 | 
            +
            - lib/devinstall/provider/provider_ssh.rb
         | 
| 115 107 | 
             
            - lib/devinstall/settings.rb
         | 
| 116 108 | 
             
            - lib/devinstall/utils.rb
         | 
| 117 109 | 
             
            - lib/devinstall/version.rb
         | 
| 110 | 
            +
            - spec/pkg_spec.rb
         | 
| 111 | 
            +
            - spec/provider_spec.rb
         | 
| 118 112 | 
             
            - spec/settings_spec.rb
         | 
| 119 113 | 
             
            homepage: http://github.com/dboca/devinstall
         | 
| 120 114 | 
             
            licenses:
         | 
| 121 115 | 
             
            - MIT
         | 
| 116 | 
            +
            metadata: {}
         | 
| 122 117 | 
             
            post_install_message: 
         | 
| 123 118 | 
             
            rdoc_options: []
         | 
| 124 119 | 
             
            require_paths:
         | 
| 125 120 | 
             
            - lib
         | 
| 126 121 | 
             
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 127 | 
            -
              none: false
         | 
| 128 122 | 
             
              requirements:
         | 
| 129 | 
            -
              - -  | 
| 123 | 
            +
              - - '>='
         | 
| 130 124 | 
             
                - !ruby/object:Gem::Version
         | 
| 131 125 | 
             
                  version: '0'
         | 
| 132 126 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 133 | 
            -
              none: false
         | 
| 134 127 | 
             
              requirements:
         | 
| 135 | 
            -
              - -  | 
| 128 | 
            +
              - - '>='
         | 
| 136 129 | 
             
                - !ruby/object:Gem::Version
         | 
| 137 130 | 
             
                  version: '0'
         | 
| 138 131 | 
             
            requirements: []
         | 
| 139 132 | 
             
            rubyforge_project: 
         | 
| 140 | 
            -
            rubygems_version:  | 
| 133 | 
            +
            rubygems_version: 2.0.3
         | 
| 141 134 | 
             
            signing_key: 
         | 
| 142 | 
            -
            specification_version:  | 
| 135 | 
            +
            specification_version: 4
         | 
| 143 136 | 
             
            summary: Copy the source files to a build host, build the packages and install builded
         | 
| 144 137 | 
             
              packages
         | 
| 145 138 | 
             
            test_files:
         | 
| 139 | 
            +
            - spec/pkg_spec.rb
         | 
| 140 | 
            +
            - spec/provider_spec.rb
         | 
| 146 141 | 
             
            - spec/settings_spec.rb
         | 
    
        data/lib/devinstall/pkg.rb
    DELETED
    
    | @@ -1,178 +0,0 @@ | |
| 1 | 
            -
            require 'devinstall/version'
         | 
| 2 | 
            -
            require 'devinstall/deep_symbolize'
         | 
| 3 | 
            -
            require 'devinstall/utils'
         | 
| 4 | 
            -
            require 'devinstall/settings'
         | 
| 5 | 
            -
            require 'pp'
         | 
| 6 | 
            -
             | 
| 7 | 
            -
            module Devinstall
         | 
| 8 | 
            -
              class UndeffError < RuntimeError; end
         | 
| 9 | 
            -
             | 
| 10 | 
            -
              class Pkg
         | 
| 11 | 
            -
                include Utils
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                def get_version(pkg, type, env)
         | 
| 14 | 
            -
                  config=Settings.instance
         | 
| 15 | 
            -
                  folder=config.local(:folder, pkg:pkg, type:type, env:env)
         | 
| 16 | 
            -
                  case type
         | 
| 17 | 
            -
                    when :deb
         | 
| 18 | 
            -
                      begin
         | 
| 19 | 
            -
                        deb_changelog = File.expand_path "#{folder}/#{pkg}/debian/changelog"
         | 
| 20 | 
            -
                        unless File.exists? deb_changelog
         | 
| 21 | 
            -
                          exit! <<-eos
         | 
| 22 | 
            -
                            No 'debian/changelog' found in specified :local:folder (#{folder})
         | 
| 23 | 
            -
                            Please check your config file
         | 
| 24 | 
            -
                          eos
         | 
| 25 | 
            -
                        end
         | 
| 26 | 
            -
                        @_package_version[:deb] = File.open(deb_changelog, 'r') { |f| f.gets.chomp.sub(/^.*\((.*)\).*$/, '\1') }
         | 
| 27 | 
            -
                      rescue IOError => e
         | 
| 28 | 
            -
                        exit! <<-eos
         | 
| 29 | 
            -
                          IO Error while opening #{deb_changelog}
         | 
| 30 | 
            -
                          Aborting \n #{e}
         | 
| 31 | 
            -
                        eos
         | 
| 32 | 
            -
                      end
         | 
| 33 | 
            -
                    else
         | 
| 34 | 
            -
                      raise UndeffError, "TODO package type #{type}"
         | 
| 35 | 
            -
                  end
         | 
| 36 | 
            -
                end
         | 
| 37 | 
            -
             | 
| 38 | 
            -
                # @param [String] package
         | 
| 39 | 
            -
                def initialize(package, type, env)
         | 
| 40 | 
            -
                  config=Settings.instance #class variable,first thing!
         | 
| 41 | 
            -
                  @type=type
         | 
| 42 | 
            -
                  @env=env
         | 
| 43 | 
            -
                  @package = package 
         | 
| 44 | 
            -
                  @_package_version = {} # versions for types:
         | 
| 45 | 
            -
                  @package_files = {}
         | 
| 46 | 
            -
                  arch = config.build(pkg:package, type:type, env:env)[:arch]
         | 
| 47 | 
            -
                  p_name = "#{@package}_#{get_version(package, type, env)}"
         | 
| 48 | 
            -
                  @package_files[:deb] = {deb: "#{p_name}_#{arch}.deb",
         | 
| 49 | 
            -
                                          tgz: "#{p_name}.tar.gz",
         | 
| 50 | 
            -
                                          dsc: "#{p_name}.dsc",
         | 
| 51 | 
            -
                                          chg: "#{p_name}_amd64.changes"}
         | 
| 52 | 
            -
                end
         | 
| 53 | 
            -
             | 
| 54 | 
            -
                def upload(pkg=@package, type=@type, env=@env)
         | 
| 55 | 
            -
                  config = Settings.instance
         | 
| 56 | 
            -
                  scp = config.base(:scp)
         | 
| 57 | 
            -
                  repo = config.repos(pkg:pkg, type:type, env:env)
         | 
| 58 | 
            -
                  local = config.local(pkg:pkg, type:type, env:env)
         | 
| 59 | 
            -
             | 
| 60 | 
            -
                  @package_files[type].each do |p, f|
         | 
| 61 | 
            -
                    puts "Uploading #{f}\t\t[#{p}] to #{repo[:host]}"
         | 
| 62 | 
            -
                    command("#{scp} #{local[:temp]}/#{f} #{repo[:user]}@#{repo[:host]}:#{repo[:folder]}")
         | 
| 63 | 
            -
                  end
         | 
| 64 | 
            -
                rescue CommandError => e
         | 
| 65 | 
            -
                  puts e.verbose_message
         | 
| 66 | 
            -
                  exit! ''
         | 
| 67 | 
            -
                rescue KeyNotDefinedError => e
         | 
| 68 | 
            -
                  puts e.message
         | 
| 69 | 
            -
                  exit! ''
         | 
| 70 | 
            -
                end
         | 
| 71 | 
            -
             | 
| 72 | 
            -
                def build(pkg=@package, type=@type, env=@env)
         | 
| 73 | 
            -
                  config = Settings.instance
         | 
| 74 | 
            -
                  puts "Building package #{pkg} type #{type}"
         | 
| 75 | 
            -
                  build = config.build(pkg:pkg, type:type, env:env)
         | 
| 76 | 
            -
                  local = config.local(pkg:pkg, type:type, env:env)
         | 
| 77 | 
            -
                  raise 'Invaild build configuration' unless build.valid?
         | 
| 78 | 
            -
             | 
| 79 | 
            -
                  ssh   = config.base(:ssh)
         | 
| 80 | 
            -
                  rsync = config.base(:rsync)
         | 
| 81 | 
            -
                  local_folder = File.expand_path local[:folder]
         | 
| 82 | 
            -
                  local_temp   = File.expand_path local[:temp]
         | 
| 83 | 
            -
             | 
| 84 | 
            -
                  build_command = build[:command].gsub('%f', build[:folder]).
         | 
| 85 | 
            -
                      gsub('%t', build[:target]).
         | 
| 86 | 
            -
                      gsub('%p', pkg.to_s).
         | 
| 87 | 
            -
                      gsub('%T', type.to_s)
         | 
| 88 | 
            -
             | 
| 89 | 
            -
                  upload_sources("#{local_folder}/", "#{build[:user]}@#{build[:host]}:#{build[:folder]}")
         | 
| 90 | 
            -
                  command("#{ssh} #{build[:user]}@#{build[:host]} \"#{build_command}\"")
         | 
| 91 | 
            -
                  @package_files[type].each do |p, t|
         | 
| 92 | 
            -
                    puts "Receiving target #{p.to_s} for #{t.to_s}"
         | 
| 93 | 
            -
                    command("#{rsync} -az #{build[:user]}@#{build[:host]}:#{build[:target]}/#{t} #{local_temp}")
         | 
| 94 | 
            -
                  end
         | 
| 95 | 
            -
                rescue CommandError => e
         | 
| 96 | 
            -
                  puts e.verbose_message
         | 
| 97 | 
            -
                  exit! ''
         | 
| 98 | 
            -
                rescue KeyNotDefinedError => e
         | 
| 99 | 
            -
                  puts e.message
         | 
| 100 | 
            -
                  exit! ''
         | 
| 101 | 
            -
                end
         | 
| 102 | 
            -
             | 
| 103 | 
            -
                def install(pkg=@package, type=@type, env=@env)
         | 
| 104 | 
            -
                  config=Settings.instance
         | 
| 105 | 
            -
                  puts "Installing #{pkg} in #{env} environment."
         | 
| 106 | 
            -
                  install=config.install(pkg:pkg, type:type, env:env)
         | 
| 107 | 
            -
                  temp  =config.local(pkg:pkg, type:type, env:env)[:temp]
         | 
| 108 | 
            -
             | 
| 109 | 
            -
                  sudo = config.base(:sudo)
         | 
| 110 | 
            -
                  scp  = config.base(:scp)
         | 
| 111 | 
            -
             | 
| 112 | 
            -
                  install[:host] = [install[:host]] unless Array === install[:host]
         | 
| 113 | 
            -
                  case type
         | 
| 114 | 
            -
                    when :deb
         | 
| 115 | 
            -
                      install[:host].each do |host|
         | 
| 116 | 
            -
                        command("#{scp} #{temp}/#{@package_files[type][:deb]} #{install[:user]}@#{host}:#{install[:folder]}")
         | 
| 117 | 
            -
                        command("#{sudo} #{install[:user]}@#{host} /usr/bin/dpkg -i #{install[:folder]}/#{@package_files[type][:deb]}")
         | 
| 118 | 
            -
                      end
         | 
| 119 | 
            -
                    else
         | 
| 120 | 
            -
                      exit! "unknown package type '#{type.to_s}'"
         | 
| 121 | 
            -
                  end
         | 
| 122 | 
            -
                rescue CommandError => e
         | 
| 123 | 
            -
                  puts e.verbose_message
         | 
| 124 | 
            -
                  exit! ''
         | 
| 125 | 
            -
                rescue KeyNotDefinedError => e
         | 
| 126 | 
            -
                  puts e.message
         | 
| 127 | 
            -
                  exit! ''
         | 
| 128 | 
            -
                end
         | 
| 129 | 
            -
             | 
| 130 | 
            -
                def run_tests(pkg=@package, type=@type, env=@env)
         | 
| 131 | 
            -
                  config=Settings.instance
         | 
| 132 | 
            -
                  # check if we have the test section in the configuration file
         | 
| 133 | 
            -
                  unless config.respond_to? :tests
         | 
| 134 | 
            -
                    puts 'No test section in the config file.'
         | 
| 135 | 
            -
                    puts 'Skipping tests'
         | 
| 136 | 
            -
                    return
         | 
| 137 | 
            -
                  end
         | 
| 138 | 
            -
                  # for tests we will use almost the same setup as for build
         | 
| 139 | 
            -
                  test  = config.tests(pkg:pkg, type:type, env:env)
         | 
| 140 | 
            -
                  local = config.local(pkg:pkg, type:type, env:env)
         | 
| 141 | 
            -
                  build = config.build(pkg:pkg, type:type, env:env)
         | 
| 142 | 
            -
             | 
| 143 | 
            -
                  ssh = config.base(:ssh)
         | 
| 144 | 
            -
                  # replace "variables" in commands
         | 
| 145 | 
            -
                  command = test[:command].
         | 
| 146 | 
            -
                      gsub('%f', test[:folder]).# %f is the folder where the sources are rsync-ed
         | 
| 147 | 
            -
                      gsub('%t', build[:target]).# %t is the folder where the build places the result
         | 
| 148 | 
            -
                      gsub('%p', pkg.to_s) # %p is the package name
         | 
| 149 | 
            -
                  # take the sources from the local folder
         | 
| 150 | 
            -
                  local_folder = File.expand_path local[:folder]
         | 
| 151 | 
            -
                  # upload them to the test machine
         | 
| 152 | 
            -
                  upload_sources("#{local_folder}/", "#{test[:user]}@#{test[:machine]}:#{test[:folder]}")
         | 
| 153 | 
            -
                  puts 'Running all tests'
         | 
| 154 | 
            -
                  puts 'This will take some time and you have no output'
         | 
| 155 | 
            -
                  command("#{ssh} #{test[:user]}@#{test[:machine]} \"#{command}\"")
         | 
| 156 | 
            -
                rescue CommandError => e
         | 
| 157 | 
            -
                  puts e.verbose_message
         | 
| 158 | 
            -
                  exit! ''
         | 
| 159 | 
            -
                rescue KeyNotDefinedError => e
         | 
| 160 | 
            -
                  puts e.message
         | 
| 161 | 
            -
                  exit! ''
         | 
| 162 | 
            -
                end
         | 
| 163 | 
            -
             | 
| 164 | 
            -
                def upload_sources (source, dest)
         | 
| 165 | 
            -
                  config=Settings.instance
         | 
| 166 | 
            -
                  rsync = config.base(:rsync)
         | 
| 167 | 
            -
                  command("#{rsync} -az #{source} #{dest}")
         | 
| 168 | 
            -
                end
         | 
| 169 | 
            -
              rescue CommandError => e
         | 
| 170 | 
            -
                puts e.verbose_message
         | 
| 171 | 
            -
                exit! ''
         | 
| 172 | 
            -
              rescue KeyNotDefinedError => e
         | 
| 173 | 
            -
                puts e.message
         | 
| 174 | 
            -
                exit! ''
         | 
| 175 | 
            -
              end
         | 
| 176 | 
            -
             | 
| 177 | 
            -
            end
         | 
| 178 | 
            -
             |