bozo-scripts 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,34 @@
1
+ module Bozo::Preparers
2
+
3
+ class CommonAssemblyInfo
4
+
5
+ def company_name(name)
6
+ @company_name = name
7
+ end
8
+
9
+ def execute
10
+ log_info 'Generating common assembly info'
11
+
12
+ git_hash = env['GIT_HASH_FULL']
13
+ computer_name = env['COMPUTERNAME']
14
+ trademark = computer_name ? "#{computer_name} #{git_hash}" : git_hash
15
+ path = File.expand_path(File.join('build', 'CommonAssemblyInfo.cs'))
16
+
17
+ log_debug "Version: #{version}"
18
+ log_debug "Commit hash: #{git_hash}"
19
+ log_debug "Computer name: #{computer_name}" if computer_name
20
+ log_debug "Path: #{path}"
21
+
22
+ File.open(path, 'w+') do |f|
23
+ f << "using System.Reflection;\n"
24
+ f << "\n"
25
+ f << "[assembly: AssemblyCompany(\"#{@company_name}\")]\n"
26
+ f << "[assembly: AssemblyVersion(\"#{version}\")]\n"
27
+ f << "[assembly: AssemblyFileVersion(\"#{version}\")]\n"
28
+ f << "[assembly: AssemblyTrademark(\"#{trademark}\")]"
29
+ end
30
+ end
31
+
32
+ end
33
+
34
+ end
@@ -0,0 +1,152 @@
1
+ module Bozo::Preparers
2
+
3
+ # Preparer for creating files based upon configuration files and ERB-style
4
+ # templates before any compilation occurs.
5
+ #
6
+ # == Overview
7
+ #
8
+ # This preparer is primarily intended for generating config files with shared
9
+ # values but it is capable of generating whatever files you want. Each
10
+ # instance of the preparer is isolated from the anothers so you could specify
11
+ # multiple preparers to work with different configurations and templates if
12
+ # you wished.
13
+ #
14
+ # By default the preparer will load <tt>default.rb</tt> followed by
15
+ # <tt>[environment].rb</tt> followed by <tt>[machine_name].rb</tt> from the
16
+ # configured config_path if the file exists. It will then load any files
17
+ # explicitly required through the config_file method.
18
+ #
19
+ # == Hook configuration
20
+ #
21
+ # prepare :file_templating do |t|
22
+ # t.config_path 'somewhere' # defaults to 'config' if not specified
23
+ # t.config_file 'my/specific/file.rb' # must be a specific file
24
+ # t.template_files 'src/**/*.config.template' # can use glob format
25
+ # end
26
+ #
27
+ # Source files are expected to have an additional extension compared to the
28
+ # target file. For example, a source file of
29
+ # <tt>src/csharp/Project/Project.config.template</tt> will generate the file
30
+ # <tt>src/csharp/Project/Project.config</tt>.
31
+ #
32
+ # == Configuration files
33
+ #
34
+ # Configuration files specify a hash of hashes in a more readable format.
35
+ # For example:
36
+ #
37
+ # group :example do
38
+ # set :one, 'foo'
39
+ # set :two, 'bar'
40
+ # end
41
+ #
42
+ # Internally creates a hash like:
43
+ #
44
+ # {:example => {:one => 'foo', :two => 'bar'}}
45
+ #
46
+ # A configuration file can overwrite the values specified by a preceding one
47
+ # without error. Groups can be opened and closed as desired and nesting
48
+ # groups is possible.
49
+ #
50
+ # == Template files
51
+ #
52
+ # To use a value within an ERB template you specify the hash hierarchy as if
53
+ # they were method names rather than having to use the full hash syntax.
54
+ #
55
+ # Therefore, this is valid:
56
+ #
57
+ # Foo is <%= example.one %>
58
+ #
59
+ # Whilst this is *not* valid:
60
+ #
61
+ # Foo is <%= self[:example][:one] %>
62
+ #
63
+ # If a template uses a value that is not specified within the configuration
64
+ # then the preparer will raise an error and halt the build.
65
+ class FileTemplating
66
+
67
+ # Creates a new instance.
68
+ def initialize
69
+ @config_path = 'config'
70
+ @template_globs = []
71
+ @config_files = []
72
+ end
73
+
74
+ # Sets the path of the directory within which the preparer should look for
75
+ # the default configuration files.
76
+ #
77
+ # @param [String] path
78
+ # The path to the directory containing the default configuration files.
79
+ def config_path(path)
80
+ @config_path = path
81
+ end
82
+
83
+ # Adds a specific file to load configuration from.
84
+ #
85
+ # @param [String] path
86
+ # The path to a configuration file.
87
+ def config_file(path)
88
+ @config_files << path
89
+ end
90
+
91
+ # Adds a set of templates files from which to generate files.
92
+ #
93
+ # @param [String] glob
94
+ # A glob that points to a set of files that should pass through the
95
+ # templating engine.
96
+ def template_files(glob)
97
+ @template_globs << glob
98
+ end
99
+
100
+ # Generate all the files matching the configuration.
101
+ def execute
102
+ log_info '' # formatting
103
+ log_info 'Generating files'
104
+
105
+ get_coordinator.generate_files do |template, target|
106
+ log_debug "Generating #{target} from #{template}"
107
+ end
108
+ end
109
+
110
+ private
111
+
112
+ # Creates a new templating coordinator based upon the current
113
+ # configuration.
114
+ def get_coordinator
115
+ coordinator = Bozo::ErubisTemplatingCoordinator.new
116
+
117
+ add_config coordinator
118
+ add_templates coordinator
119
+
120
+ coordinator
121
+ end
122
+
123
+ # Adds the configuration to the templating coordinator.
124
+ def add_config(coordinator)
125
+ add_default_config_files coordinator
126
+ @config_files.each {|f| coordinator.required_config_file f}
127
+ end
128
+
129
+ # Adds the default configuration from the configuration directory to the
130
+ # templating coordinator.
131
+ #
132
+ # @param [ErubisTemplatingCoordinator] coordinator
133
+ # The template coordinator to add the configuration to.
134
+ def add_default_config_files(coordinator)
135
+ default_files = ['default.rb', "#{environment}.rb"]
136
+ default_files << "#{env['MACHINENAME']}.rb" if env['MACHINENAME']
137
+
138
+ default_files.each do |file|
139
+ coordinator.config_file File.join(@config_path, file)
140
+ end
141
+ end
142
+
143
+ # Adds the templates to the templating coordinator.
144
+ def add_templates(coordinator)
145
+ @template_globs.each do |glob|
146
+ coordinator.template_files glob
147
+ end
148
+ end
149
+
150
+ end
151
+
152
+ end
@@ -0,0 +1,83 @@
1
+ require 'fileutils'
2
+
3
+ module Bozo::Publishers
4
+
5
+ # Publisher that copies files from one location to another.
6
+ class FileCopy
7
+
8
+ # Creates a new instance.
9
+ def initialize
10
+ @directories = []
11
+ end
12
+
13
+ # Adds a source directory of files copy.
14
+ #
15
+ # Must be relative to the project root. All files within the directory and
16
+ # its subdirectories will be copied to the destination directory,
17
+ # maintaining the file structure.
18
+ #
19
+ # @params [Array] args
20
+ # Path to a directory relative to the project root.
21
+ def directory(*args)
22
+ @directories << args
23
+ end
24
+
25
+ # Set the destination directory of the file copy.
26
+ #
27
+ # Must be an absolute path.
28
+ #
29
+ # @params [String] destination
30
+ # The absolution path the source files should be copied to.
31
+ def destination(destination)
32
+ @destination = destination
33
+ end
34
+
35
+ def execute
36
+ if @directories.empty? or @destination.nil?
37
+ raise Bozo::ConfigurationError.new 'You must specify at least one source file or directory AND a destination directory'
38
+ end
39
+
40
+ ensure_no_clashing_files
41
+
42
+ copy_pairs do |source, target|
43
+ FileUtils.mkdir_p File.dirname(target)
44
+ log_debug "Publishing \"#{File.basename(source)}\" to \"#{target}\""
45
+ FileUtils.cp source, target
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ # Checks the destination does not contain files that will be overwritten by
52
+ # the source files.
53
+ def ensure_no_clashing_files
54
+ existing_files = []
55
+
56
+ copy_pairs do |source, target|
57
+ existing_files << target if File.exist? target
58
+ end
59
+
60
+ raise Bozo::ConfigurationError.new "Target files already exist - #{existing_files}" unless existing_files.empty?
61
+ end
62
+
63
+ # Returns the source-destination file pairs specified by the source
64
+ # directories and destination directory.
65
+ def copy_pairs # :yields: source_path, destination_path
66
+ destination = File.join @destination
67
+
68
+ @directories.each do |dir|
69
+ relative_source_dir = File.join(dir)
70
+ source_dir = File.expand_path relative_source_dir
71
+ source_dir_path = Pathname.new source_dir
72
+
73
+ Dir[File.join(source_dir, '**', '*')].each do |source_file|
74
+ rel_path = Pathname.new(source_file).relative_path_from(source_dir_path).to_s
75
+ target_file = File.join(destination, rel_path)
76
+ yield source_file, target_file
77
+ end
78
+ end
79
+ end
80
+
81
+ end
82
+
83
+ end
@@ -0,0 +1,18 @@
1
+ module Bozo::Publishers
2
+
3
+ # Publisher that publishes gem files to rubygems.org
4
+ class Rubygems
5
+
6
+ def execute
7
+ Dir['dist/gem/*.gem'].each { |gem| push gem }
8
+ end
9
+
10
+ private
11
+
12
+ def push(gem)
13
+ execute_command :rubygems, ['gem', 'push', gem]
14
+ end
15
+
16
+ end
17
+
18
+ end
@@ -0,0 +1,158 @@
1
+ require 'nokogiri'
2
+
3
+ module Bozo::TestRunners
4
+
5
+ # Adds a code coverage test runner using dotCover
6
+ #
7
+ # The default configuration looks for dotCover in the ProgramFiles(x86) path
8
+ #
9
+ # Test runners can be defined for dotCover to run against. Each runner
10
+ # produces a separate dotcover output
11
+ class DotCover
12
+ def self.default_path
13
+ if ENV['teamcity.dotCover.home'].nil?
14
+ if ENV['ProgramFiles(x86)'].nil?
15
+ program_files_path = ENV['ProgramFiles']
16
+ else
17
+ program_files_path = ENV['ProgramFiles(x86)']
18
+ end
19
+
20
+ File.join(program_files_path, 'JetBrains', 'dotCover', 'v1.2', 'Bin', 'dotcover.exe')
21
+ else
22
+ File.join(ENV['teamcity.dotCover.home'], 'dotcover.exe')
23
+ end
24
+ end
25
+
26
+ def initialize
27
+ @@defaults = {
28
+ :path => DotCover.default_path,
29
+ :required => true
30
+ }
31
+
32
+ @config = {}
33
+ @runners = []
34
+ end
35
+
36
+ # Returns whether dotcover is installed at the configured path
37
+ def dotcover_installed?
38
+ path = configuration[:path]
39
+
40
+ return false if path.nil?
41
+
42
+ File.exist? path
43
+ end
44
+
45
+ # Adds a test runner
46
+ #
47
+ # @param [Symbol] runner
48
+ # A test runner to wrap with dotcover
49
+ def runner(runner, &block)
50
+ add_instance runner, block
51
+ end
52
+
53
+ # Specifies whether covering with dotcover is required
54
+ #
55
+ # If it is not required, and dotcover cannot be found, then test runners
56
+ # are executed without coverage. If dotcover is required but cannot be
57
+ # found then an error will occur.
58
+ #
59
+ # @param [boolean] required
60
+ # Whether dotCover coverage is required
61
+ def required?(required = nil)
62
+ @config[:required] = required unless required.nil?
63
+
64
+ @config[:required]
65
+ end
66
+
67
+ def execute
68
+ if required? or dotcover_installed?
69
+ @runners.each {|runner| execute_with_coverage runner}
70
+ else
71
+ @runners.each {|runner| execute_without_coverage(runner)}
72
+ end
73
+ end
74
+
75
+ private
76
+
77
+ # Resolves the named class within the given namespace and then created an
78
+ # instance of the class before adding it to the given collection and
79
+ # yielding it to the configuration block when one is provided.
80
+ #
81
+ # @param [Symbol] type
82
+ # The name of the step executor.
83
+ # @param [Proc] block
84
+ # Optional block to refine the configuration of the step executor.
85
+ def add_instance(type, block)
86
+ instance = Bozo::TestRunners.const_get(to_class_name(type)).new
87
+ instance.extend Bozo::Runner
88
+ @runners << instance
89
+ block.call instance if block
90
+ end
91
+
92
+ # Converts a symbol into a Pascal Case class name.
93
+ #
94
+ # eg. `:single` => `"Single"`, `:two_words` => `"TwoWords"`.
95
+ #
96
+ # @param [Symbol] type
97
+ # The name of a step executor.
98
+ def to_class_name(type)
99
+ type.to_s.split('_').map{|word| word.capitalize}.join
100
+ end
101
+
102
+ def execute_without_coverage(runner)
103
+ log_debug 'Running ' + runner.class.to_s + ' without coverage'
104
+ runner.execute
105
+ end
106
+
107
+ def execute_with_coverage(runner)
108
+ if required? & !dotcover_installed?
109
+ log_fatal "Attempting to run with coverage but dotcover could not be found at #{configuration[:path]}"
110
+ end
111
+
112
+ log_debug "Running #{runner.class} with coverage"
113
+
114
+ config = configuration
115
+ dotcover_path = config[:path]
116
+ coverage_path = generate_coverage_file runner
117
+
118
+ args = []
119
+ args << '"' + dotcover_path + '"'
120
+ args << "analyse #{coverage_path}"
121
+
122
+ log_debug 'Running dotcover from "' + dotcover_path + '"'
123
+ execute_command :dot_cover, args
124
+ end
125
+
126
+ def generate_coverage_file(runner)
127
+ output_file = File.expand_path(File.join('temp', 'dotcover', "#{Time.now.to_i}-dotcover-report.xml"))
128
+
129
+ runner_args = runner.runner_args
130
+ runner_args.flatten!
131
+
132
+ builder = Nokogiri::XML::Builder.new do |doc|
133
+ doc.AnalyseParams do
134
+ doc.Executable runner.runner_path.gsub(/\//, '\\')
135
+ doc.Arguments runner_args.join(' ')
136
+ doc.WorkingDir File.expand_path(File.join('temp', 'dotcover'))
137
+ doc.Output output_file
138
+ end
139
+ end
140
+
141
+ coverage_path = File.expand_path(File.join('temp', 'dotcover', "coverage.xml"))
142
+ FileUtils.mkdir_p File.dirname(coverage_path)
143
+ File.open(coverage_path, 'w+') {|f| f.write(builder.to_xml)}
144
+
145
+ coverage_path
146
+ end
147
+
148
+ def configuration
149
+ config_with_defaults
150
+ end
151
+
152
+ def config_with_defaults
153
+ @@defaults.merge @config
154
+ end
155
+
156
+ end
157
+
158
+ end
@@ -0,0 +1,131 @@
1
+ module Bozo::TestRunners
2
+
3
+ # A TestRunner for NUnit
4
+ # By default the x64 runner is used. If you want to use a different
5
+ # platform runner then set the platform, e.g. 'x86'.
6
+ #
7
+ # == Dotcover integration
8
+ # To enable integration with the dotcover test runner the following
9
+ # interface needs to be used
10
+ #
11
+ # runner_path # should return the path to the runners executable
12
+ # runner_args # should return the arguments to be passed to use
13
+ class Nunit
14
+
15
+ def initialize
16
+ @projects = []
17
+ @include = []
18
+ @exclude = []
19
+ end
20
+
21
+ def destination(destination)
22
+ @destination = destination
23
+ end
24
+
25
+ def platform(platform)
26
+ @platform = platform
27
+ end
28
+
29
+ def project(path)
30
+ @projects << path
31
+ end
32
+
33
+ def report_path(path)
34
+ @report_path = path
35
+ end
36
+
37
+ def coverage(coverage)
38
+ @coverage = coverage
39
+ end
40
+
41
+ def include(include)
42
+ cannot_define_both_include_and_exclude_categories if @exclude.any?
43
+ @include << include
44
+ end
45
+
46
+ def exclude(exclude)
47
+ cannot_define_both_include_and_exclude_categories if @include.any?
48
+ @exclude << exclude
49
+ end
50
+
51
+ def to_s
52
+ "Run tests with nunit against projects #{@projects}"
53
+ end
54
+
55
+ # Returns the path to the runner's executable.
56
+ #
57
+ # @returns [String]
58
+ def runner_path
59
+ exe_name = "nunit-console.exe"
60
+
61
+ if defined? @platform
62
+ log_debug "Looking for runner with #@platform platform"
63
+ exe_name = "nunit-console-#@platform.exe"
64
+ end
65
+
66
+ nunit_runners = expand_and_glob('packages', 'NUnit*', 'tools', exe_name)
67
+ raise nunit_runner_not_found if nunit_runners.empty?
68
+ raise multiple_runners_found if nunit_runners.size > 1
69
+
70
+ nunit_runner = nunit_runners.first
71
+
72
+ log_debug "Found runner at #{nunit_runner}"
73
+
74
+ nunit_runner
75
+ end
76
+
77
+ # Returns the arguments required for the runner's executable.
78
+ #
79
+ # @returns [Array]
80
+ def runner_args
81
+ args = []
82
+
83
+ @projects.each do |project|
84
+ expand_and_glob('temp', 'msbuild', project, '**', "#{project}.dll").each do |test_dll|
85
+ args << "\"#{test_dll}\""
86
+ end
87
+ end
88
+ args << '/nologo'
89
+
90
+ report_path = @report_path
91
+ report_path = expand_path('temp', 'nunit', "#{Time.now.to_i}-nunit-report.xml") unless report_path
92
+
93
+ # Ensure the directory is there because NUnit won't make it
94
+ FileUtils.mkdir_p File.dirname(report_path)
95
+
96
+ args << "/xml:\"#{report_path}\""
97
+ args << "/include:#{@include.join(',')}" if @include.any?
98
+ args << "/exclude:#{@exclude.join(',')}" if @exclude.any?
99
+
100
+ args
101
+ end
102
+
103
+ def execute
104
+ execute_command :nunit, [runner_path] << runner_args
105
+ end
106
+
107
+ private
108
+
109
+ def nunit_runner_not_found
110
+ Bozo::ConfigurationError.new 'No NUnit runners found. You must install one via nuget.'
111
+ end
112
+
113
+ def multiple_runners_found
114
+ Bozo::ConfigurationError.new 'Multiple NUnit runners found. There should only be one.'
115
+ end
116
+
117
+ def expand_path(*args)
118
+ File.expand_path(File.join(args))
119
+ end
120
+
121
+ def expand_and_glob(*args)
122
+ Dir[expand_path(*args)]
123
+ end
124
+
125
+ def cannot_define_both_include_and_exclude_categories
126
+ raise Bozo::ConfigurationError.new 'Both include and exclude categories defined. You cannot specify both for nunit.'
127
+ end
128
+
129
+ end
130
+
131
+ end
@@ -0,0 +1,35 @@
1
+ module Bozo::TestRunners
2
+
3
+ class Runit
4
+
5
+ def initialize
6
+ @paths = []
7
+ end
8
+
9
+ def path(path)
10
+ @paths << path
11
+ end
12
+
13
+ def execute
14
+ require 'test/unit'
15
+
16
+ test_files = []
17
+
18
+ @paths.each do |p|
19
+ Dir[p].select {|f| (File.extname f) == '.rb'}.each {|f| test_files << f}
20
+ end
21
+
22
+ # raise an error if no test files were found. This may indicate a configuration issue
23
+ raise Bozo::ConfigurationError.new "No tests found" unless test_files.any?
24
+ raise Bozo::ExecutionError.new(:runit, test_files, -1) unless execute_tests test_files
25
+ end
26
+
27
+ private
28
+
29
+ def execute_tests(test_files)
30
+ Test::Unit::AutoRunner.run(true, nil, test_files)
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,5 @@
1
+ module BozoScripts
2
+
3
+ VERSION = File.read(File.expand_path(File.dirname(File.realpath(__FILE__)) + '/../../VERSION')).strip
4
+
5
+ end
@@ -0,0 +1,26 @@
1
+ $:.push File.expand_path(File.dirname(__FILE__))
2
+
3
+ require 'fileutils'
4
+ require 'rainbow'
5
+ require 'bozo'
6
+
7
+ require 'bozo/compilers/msbuild'
8
+ require 'bozo/dependency_resolvers/bundler'
9
+ require 'bozo/dependency_resolvers/nuget'
10
+ require 'bozo/hooks/fxcop'
11
+ require 'bozo/hooks/git_commit_hashes'
12
+ require 'bozo/hooks/git_tag_release'
13
+ require 'bozo/hooks/teamcity'
14
+ require 'bozo/hooks/timing'
15
+ require 'bozo/packagers/rubygems'
16
+ require 'bozo/packagers/nuget'
17
+ require 'bozo/preparers/common_assembly_info'
18
+ require 'bozo/preparers/file_templating'
19
+ require 'bozo/publishers/file_copy'
20
+ require 'bozo/publishers/rubygems'
21
+ require 'bozo/test_runners/dotcover'
22
+ require 'bozo/test_runners/nunit'
23
+ require 'bozo/test_runners/runit'
24
+ require 'bozo/configuration'
25
+ require 'bozo/erubis_templating_coordinator'
26
+ require 'bozo/version'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bozo-scripts
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Garry Shutler
@@ -88,7 +88,30 @@ email:
88
88
  executables: []
89
89
  extensions: []
90
90
  extra_rdoc_files: []
91
- files: []
91
+ files:
92
+ - lib/bozo/compilers/msbuild.rb
93
+ - lib/bozo/configuration.rb
94
+ - lib/bozo/dependency_resolvers/bundler.rb
95
+ - lib/bozo/dependency_resolvers/nuget.rb
96
+ - lib/bozo/erubis_templating_coordinator.rb
97
+ - lib/bozo/hooks/fxcop.rb
98
+ - lib/bozo/hooks/git_commit_hashes.rb
99
+ - lib/bozo/hooks/git_tag_release.rb
100
+ - lib/bozo/hooks/teamcity.rb
101
+ - lib/bozo/hooks/timing.rb
102
+ - lib/bozo/packagers/nuget.rb
103
+ - lib/bozo/packagers/rubygems.rb
104
+ - lib/bozo/preparers/common_assembly_info.rb
105
+ - lib/bozo/preparers/file_templating.rb
106
+ - lib/bozo/publishers/file_copy.rb
107
+ - lib/bozo/publishers/rubygems.rb
108
+ - lib/bozo/test_runners/dotcover.rb
109
+ - lib/bozo/test_runners/nunit.rb
110
+ - lib/bozo/test_runners/runit.rb
111
+ - lib/bozo/version.rb
112
+ - lib/bozo_scripts.rb
113
+ - VERSION
114
+ - LICENSE
92
115
  homepage: https://github.com/zopaUK/bozo-scripts
93
116
  licenses: []
94
117
  metadata: {}