physique 0.2.2

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.
@@ -0,0 +1,113 @@
1
+ require 'xsemver'
2
+ require 'albacore/logging'
3
+
4
+ module Physique
5
+ module Tasks
6
+ # Versionizer does versioning ITS OWN WAY!
7
+ #
8
+ # Defines ENV vars:
9
+ # * BUILD_VERSION
10
+ # * NUGET_VERSION
11
+ # * FORMAL_VERSION
12
+ #
13
+ # Publishes symbol :build_version
14
+ module Versionizer
15
+ # adds a new task with the given symbol to the Rake/Albacore application
16
+ # You can use this like any other albacore method, such as build,
17
+ # in order to give it parameters or dependencies, but there is no
18
+ # configuration object that you can configure. Copy-n-paste this
19
+ # code if you want something of your own.
20
+ #
21
+ def self.new(*sym)
22
+ version = gitflow_version(XSemVer::SemVer.find)
23
+ version_data = define_versions(version)
24
+
25
+ Albacore.subscribe :build_version do |data|
26
+ ENV['BUILD_VERSION'] = data.build_version
27
+ ENV['NUGET_VERSION'] = data.nuget_version
28
+ ENV['FORMAL_VERSION'] = data.formal_version
29
+ ENV['LONG_VERSION'] = data.long_version
30
+ end
31
+
32
+ Albacore.define_task(*sym) do
33
+ Albacore.publish :build_version, OpenStruct.new(version_data)
34
+ end
35
+
36
+ Albacore.define_task :version do
37
+ puts version_data.inspect
38
+ end
39
+ end
40
+
41
+ def self.define_versions(semver)
42
+ build = build_number
43
+
44
+ {
45
+ # just a monotonic inc
46
+ :semver => semver,
47
+ :build_number => build,
48
+ :current_branch => current_branch,
49
+
50
+ # purely M.m.p format
51
+ :formal_version => "#{semver.format('%M.%m.%p')}",
52
+
53
+ # four-numbers version, useful if you're dealing with COM/Windows
54
+ :long_version => "#{semver.format('%M.%m.%p')}.#{build}",
55
+
56
+ # extensible number w/ git hash
57
+ :build_version => "#{semver.format('%M.%m.%p%s')}.#{last_commit[0]}",
58
+
59
+ # nuget (not full semver 2.0.0-rc.1 support) see http://nuget.codeplex.com/workitem/1796
60
+ :nuget_version => semver.format('%M.%m.%p%s')
61
+ }
62
+ end
63
+
64
+ # load the commit data
65
+ # returns: [short-commit :: String]
66
+ #
67
+ def self.last_commit
68
+ begin
69
+ `git rev-parse --short HEAD`.chomp[0,6]
70
+ rescue
71
+ (ENV['BUILD_VCS_NUMBER'] || '000000')[0,6]
72
+ end
73
+ end
74
+
75
+ # Determine the current branch
76
+ # returns: branch name
77
+ #
78
+ def self.current_branch
79
+ begin
80
+ `git rev-parse --abbrev-ref HEAD`.chomp
81
+ rescue
82
+ 'master'
83
+ end
84
+ end
85
+
86
+ def self.gitflow_version(version)
87
+ return unless ENV.include?('BUILD_NUMBER')
88
+ version.special = gitflow_special
89
+ version
90
+ end
91
+
92
+ def self.build_number
93
+ ENV['BUILD_NUMBER'] || '0'
94
+ end
95
+
96
+ def self.gitflow_special
97
+ prefix = special_prefix
98
+ return version.special if prefix == 'master'
99
+
100
+ "#{prefix}#{build_number}"
101
+ end
102
+
103
+ def self.special_prefix
104
+ # TODO: There is a better way to do this.
105
+ branch_name = current_branch
106
+ return 'release' if branch_name.start_with? 'release/'
107
+ return 'hotfix' if branch_name.start_with? 'hotfix/'
108
+ return 'feature' if branch_name.start_with? 'feature/'
109
+ branch_name
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,58 @@
1
+ require 'physique/dsl'
2
+ require 'physique/tool_locator'
3
+
4
+ module Physique
5
+ class TasksBuilder
6
+ include Albacore::DSL
7
+ include Albacore::Logging
8
+ include Physique::ToolLocator
9
+
10
+ @subclasses = []
11
+
12
+ class << self
13
+ attr_reader :subclasses
14
+ end
15
+
16
+ def self.inherited(subclass)
17
+ TasksBuilder.subclasses << subclass
18
+ end
19
+
20
+ attr_reader :solution
21
+
22
+ def self.build_tasks_for(solution)
23
+ TasksBuilder.subclasses.each do |builder_class|
24
+ builder_class.new.build_tasks_for solution
25
+ end
26
+ end
27
+
28
+ def build_tasks_for(solution)
29
+ @solution = solution
30
+ build_tasks
31
+ end
32
+
33
+ def build_tasks
34
+ raise 'This method must be implemented in your subclass'
35
+ end
36
+
37
+ def ensure_output_location(path)
38
+ # Ensure output directory exists
39
+ FileUtils.mkdir_p path
40
+ end
41
+
42
+ def namespace(name, &block)
43
+ name = to_string_or_symbol(name)
44
+ Rake.application.in_namespace(name, &block)
45
+ end
46
+
47
+ def to_string_or_symbol(name)
48
+ name = name.to_s if name.kind_of?(Symbol)
49
+ name = name.to_str if name.respond_to?(:to_str)
50
+ unless name.kind_of?(String) || name.nil?
51
+ raise ArgumentError, 'Expected a String or Symbol for a namespace name'
52
+ end
53
+ name
54
+ end
55
+ end
56
+ end
57
+
58
+ Gem.find_files('physique/task_builders/*.rb').each { |path| require path }
@@ -0,0 +1,42 @@
1
+ require 'map'
2
+ require 'albacore'
3
+
4
+ module Physique
5
+ module ToolLocator
6
+ include Albacore::Logging
7
+
8
+ # Allows you to locate a tool on disk given a file specification. For example...
9
+ #
10
+ # locate_tool 'C:/Program Files/Microsoft SQL Server/**/Tools/Binn/SQLCMD.EXE'
11
+ #
12
+ # The tool sorts any matching executables in descending order to that the most recent version is returned. To
13
+ # change this behavior call the method with the reverse option.
14
+ #
15
+ # locate_tool 'C:/path/to/**/tool.exe', reverse: false
16
+ #
17
+ # Throws a ToolNotFoundError if no tool could be found.
18
+ def locate_tool(paths, options = {})
19
+ # FileList only correctly handles forward-slashes, even on Windows
20
+ paths = paths.gsub('\\', '/')
21
+
22
+ info { "Extracting paths from the following pattern #{paths}" }
23
+ paths = FileList[paths] unless paths.respond_to?(:each)
24
+
25
+ info { "Attempting to locate tool in the following paths #{paths}" }
26
+ opts = Map.options(options)
27
+ opts = opts.apply :reverse => true
28
+ paths = paths.collect { |p| which(p) }.compact.sort
29
+ paths = paths.reverse if opts[:reverse]
30
+ tool = paths.first
31
+
32
+ raise ToolNotFoundError, "Could not find tool in the following paths: \n #{paths}" if tool.nil?
33
+ tool
34
+ end
35
+
36
+ def which(exe)
37
+ Albacore::CrossPlatformCmd.which(exe) ? exe : nil;
38
+ end
39
+
40
+ class ToolNotFoundError < Exception; end
41
+ end
42
+ end
@@ -0,0 +1,3 @@
1
+ module Physique
2
+ VERSION = '0.2.2'
3
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'physique/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'physique'
8
+ spec.version = Physique::VERSION
9
+ spec.authors = ['Robert Scaduto']
10
+ spec.email = ['rscaduto@thirdwave.it']
11
+ spec.description = %q{Beautiful builds for .NET projects}
12
+ spec.summary = %q{A conventional build framework supporting NUnit, FluentMigrator and Octopus Deploy}
13
+ spec.homepage = 'http://github.com/scardetto/physique'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'bundler'
22
+ spec.add_development_dependency 'rspec', '2.14.1'
23
+ spec.add_dependency 'activesupport', '~> 4.1'
24
+ spec.add_dependency 'map', '~> 6.5'
25
+ spec.add_dependency 'albacore', '2.0.0.rc.12'
26
+ end
@@ -0,0 +1,22 @@
1
+ require 'physique'
2
+
3
+ describe Physique::FluentMigratorConfig do
4
+ it 'should find full project path when specifying the name and language' do
5
+ project_name = 'Test.Database'
6
+ opts = Physique::FluentMigratorConfig.new.tap { |c|
7
+ c.project = project_name
8
+ c.lang = :vb
9
+ }.opts
10
+
11
+ expect(opts.project_file).to eq("src/#{project_name}/#{project_name}.vbproj")
12
+ end
13
+
14
+ it 'should default to the cs programming language' do
15
+ project_name = 'Test.Database'
16
+ opts = Physique::FluentMigratorConfig.new.tap { |c|
17
+ c.project = project_name
18
+ }.opts
19
+
20
+ expect(opts.project_file).to eq("src/#{project_name}/#{project_name}.csproj")
21
+ end
22
+ end
@@ -0,0 +1,26 @@
1
+ require 'physique/project'
2
+
3
+ describe Physique::Project do
4
+ it 'should echo the path when full project file name is provided' do
5
+ project_name = 'test.csproj'
6
+ expect(get_path(project_name)).to eq(project_name)
7
+ end
8
+
9
+ it 'should return the full path when partial project file name is provided' do
10
+ project_name = 'TestProject.Domain'
11
+ expect(get_path(project_name)).to eq("src/#{project_name}/#{project_name}.csproj")
12
+ end
13
+
14
+ it 'should handle multiple languages' do
15
+ project_name = 'TestProject.Domain'
16
+ language = 'vb'
17
+ expect(get_path(project_name, language)).to eq("src/#{project_name}/#{project_name}.vbproj")
18
+
19
+ language = 'fs'
20
+ expect(get_path(project_name, language)).to eq("src/#{project_name}/#{project_name}.fsproj")
21
+ end
22
+
23
+ def get_path(name, ext = 'cs')
24
+ ::Physique::Project.get_path(name, ext)
25
+ end
26
+ end
@@ -0,0 +1,12 @@
1
+ require 'physique'
2
+
3
+ describe Physique::CompileConfig do
4
+
5
+ describe 'By default' do
6
+ before(:all) { @config = Physique::CompileConfig.new }
7
+
8
+ it 'should set the build configuration to Release' do
9
+ expect(@config.opts.configuration).to eq('Release')
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,146 @@
1
+ require 'physique'
2
+ require 'physique/tasks/sqlcmd'
3
+
4
+ describe Physique::SqlCmd::Config do
5
+ if ::Rake::Win32.windows?
6
+ describe 'When initialized with the minimum required values' do
7
+ before(:all) do
8
+ @opts = Physique::SqlCmd::Config.new.tap { |c|
9
+ c.server_name = 'server'
10
+ c.command = 'command'
11
+ }.opts
12
+ end
13
+
14
+ it 'should find sqlcmd tool' do
15
+ expect(@opts[:exe]).to match(/sqlcmd/i)
16
+ end
17
+
18
+ it 'should break on errors' do
19
+ expect(@opts[:continue_on_errors]).to be_false
20
+ end
21
+
22
+ it 'should set the server name' do
23
+ expect(@opts[:server_name]).to eq('server')
24
+ end
25
+ end
26
+
27
+ describe 'When initialized with a command' do
28
+ before(:all) do
29
+ @opts = Physique::SqlCmd::Config.new.tap { |c|
30
+ c.server_name = 'server'
31
+ c.command = 'command'
32
+ }.opts
33
+ end
34
+
35
+ it 'should set the command' do
36
+ expect(@opts[:command]).to eq('command')
37
+ end
38
+
39
+ it 'should set the source to :command' do
40
+ expect(@opts[:source]).to eq(:command)
41
+ end
42
+ end
43
+
44
+ describe 'When initialized with a file' do
45
+ before(:all) do
46
+ @opts = Physique::SqlCmd::Config.new.tap { |c|
47
+ c.server_name = 'server'
48
+ c.file = 'test.sql'
49
+ }.opts
50
+ end
51
+
52
+ it 'should set the file' do
53
+ expect(@opts[:file]).to eq('test.sql')
54
+ end
55
+
56
+ it 'should set the source to :file' do
57
+ expect(@opts[:source]).to eq(:file)
58
+ end
59
+ end
60
+
61
+ describe 'When initialized with both a file and a command' do
62
+ before(:all) do
63
+ @opts = Physique::SqlCmd::Config.new.tap { |c|
64
+ c.server_name = 'server'
65
+ c.command = 'command'
66
+ c.file = 'file'
67
+ }.opts
68
+ end
69
+
70
+ it 'should give precedence to the command' do
71
+ expect(@opts[:source]).to eq(:command)
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ describe Physique::SqlCmd::Cmd do
78
+ describe 'When configured with a file' do
79
+ before(:all) do
80
+ opts = Physique::SqlCmd::Config.new.tap { |c|
81
+ c.server_name = 'server'
82
+ c.database_name = 'database'
83
+ c.file = 'test.sql'
84
+ }.opts
85
+
86
+ @cmd = Physique::SqlCmd::Cmd.new opts
87
+ end
88
+
89
+ it 'should break on errors' do
90
+ expect(@cmd.parameters).to include('-b')
91
+ end
92
+
93
+ it 'should include the server name' do
94
+ expect(@cmd.parameters).to include('-S server')
95
+ end
96
+
97
+ it 'should include the database name' do
98
+ expect(@cmd.parameters).to include('-d database')
99
+ end
100
+
101
+ it 'should include the file name' do
102
+ expect(@cmd.parameters).to include('-i test.sql')
103
+ end
104
+ end
105
+
106
+ describe 'When configured with a command' do
107
+ before(:all) do
108
+ opts = Physique::SqlCmd::Config.new.tap { |c|
109
+ c.server_name = 'server'
110
+ c.command = 'command'
111
+ }.opts
112
+
113
+ @cmd = Physique::SqlCmd::Cmd.new opts
114
+ end
115
+
116
+ it 'should break on errors' do
117
+ expect(@cmd.parameters).to include('-b')
118
+ end
119
+
120
+ it 'should include the server name' do
121
+ expect(@cmd.parameters).to include('-S server')
122
+ end
123
+
124
+ it 'should include the command in single quotes' do
125
+ expect(@cmd.parameters).to include("-Q 'command'")
126
+ end
127
+ end
128
+
129
+ describe 'When setting variables' do
130
+ before(:all) do
131
+ opts = Physique::SqlCmd::Config.new.tap { |c|
132
+ c.server_name = 'server'
133
+ c.command = 'command'
134
+ c.set_variable 'test_variable1', 'test_value1'
135
+ c.set_variable 'test_variable2', 'test_value2'
136
+ }.opts
137
+
138
+ @cmd = Physique::SqlCmd::Cmd.new opts
139
+ end
140
+
141
+ it 'should add multiple variables to the command line' do
142
+ expect(@cmd.parameters).to include("-v test_variable1=test_value1")
143
+ expect(@cmd.parameters).to include("-v test_variable2=test_value2")
144
+ end
145
+ end
146
+ end