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.
- checksums.yaml +15 -0
- data/.gitignore +36 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +60 -0
- data/README.md +41 -0
- data/Rakefile +6 -0
- data/lib/physique.rb +22 -0
- data/lib/physique/config.rb +24 -0
- data/lib/physique/dsl.rb +76 -0
- data/lib/physique/project.rb +34 -0
- data/lib/physique/solution.rb +69 -0
- data/lib/physique/task_builders/build.rb +62 -0
- data/lib/physique/task_builders/default.rb +9 -0
- data/lib/physique/task_builders/fluent_migrator.rb +227 -0
- data/lib/physique/task_builders/nuget.rb +45 -0
- data/lib/physique/task_builders/octopus.rb +147 -0
- data/lib/physique/task_builders/publish_nugets.rb +133 -0
- data/lib/physique/task_builders/test.rb +44 -0
- data/lib/physique/tasks/fluent_migrator.rb +159 -0
- data/lib/physique/tasks/nugets_pack.rb +12 -0
- data/lib/physique/tasks/octopus_pack.rb +141 -0
- data/lib/physique/tasks/sqlcmd.rb +110 -0
- data/lib/physique/tasks/versionizer.rb +113 -0
- data/lib/physique/tasks_builder.rb +58 -0
- data/lib/physique/tool_locator.rb +42 -0
- data/lib/physique/version.rb +3 -0
- data/physique.gemspec +26 -0
- data/spec/config_spec.rb +22 -0
- data/spec/project_spec.rb +26 -0
- data/spec/solution_spec.rb +12 -0
- data/spec/sqlcmd_spec.rb +146 -0
- data/spec/tool_locator_spec.rb +22 -0
- metadata +151 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
module Physique
|
2
|
+
class TestConfig
|
3
|
+
self.extend Albacore::ConfigDSL
|
4
|
+
|
5
|
+
# Path to test runner executable
|
6
|
+
attr_path :exe
|
7
|
+
|
8
|
+
# Path to test runner executable
|
9
|
+
attr_writer :files
|
10
|
+
|
11
|
+
def opts
|
12
|
+
Map.new({
|
13
|
+
exe: @exe,
|
14
|
+
files: @files
|
15
|
+
})
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class TestsTasksBuilder < TasksBuilder
|
20
|
+
def build_tasks
|
21
|
+
add_test_tasks
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_test_tasks
|
25
|
+
configuration = solution.compile.configuration
|
26
|
+
package_dir = solution.nuget.restore_location
|
27
|
+
|
28
|
+
task = test_runner_task :test => test_dependencies do |tests|
|
29
|
+
tests.files = FileList["**/*.Tests/bin/#{configuration}/*.Tests.dll"]
|
30
|
+
tests.exe = locate_tool("#{package_dir}/NUnit.Runners.*/tools/nunit-console.exe")
|
31
|
+
tests.parameters.add('/labels')
|
32
|
+
tests.parameters.add('/trace=Verbose')
|
33
|
+
tests.parameters.add('/exclude=PersistenceTest')
|
34
|
+
end
|
35
|
+
task.add_description 'Run unit tests'
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_dependencies
|
39
|
+
dependencies = [ :compile ]
|
40
|
+
dependencies << 'db:rebuild' unless solution.migrator.nil?
|
41
|
+
dependencies
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'active_support/core_ext/string'
|
2
|
+
require 'map'
|
3
|
+
|
4
|
+
module Physique
|
5
|
+
module FluentMigrator
|
6
|
+
class Cmd
|
7
|
+
include Albacore::CrossPlatformCmd
|
8
|
+
|
9
|
+
attr_reader :parameters
|
10
|
+
|
11
|
+
def initialize(opts)
|
12
|
+
@work_dir = opts[:work_dir]
|
13
|
+
@executable = opts[:exe]
|
14
|
+
set_parameters opts
|
15
|
+
end
|
16
|
+
|
17
|
+
def execute
|
18
|
+
sh "#{@executable} #{@parameters.join(' ')}"
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def set_parameters(opts)
|
24
|
+
@parameters = @parameters || []
|
25
|
+
@parameters << "--target #{opts.dll}"
|
26
|
+
@parameters << "--provider #{opts.dialect}"
|
27
|
+
@parameters << %Q{--connectionString "#{opts.connection_string}"}
|
28
|
+
@parameters << "--task #{opts.task}"
|
29
|
+
@parameters << "--namespace #{opts.namespace}" unless opts.namespace.blank?
|
30
|
+
@parameters << "--nested #{opts.nested}" unless opts.namespace.blank? # Modifies the namespace option
|
31
|
+
@parameters << "--output --outputFileName #{opts.output_file}" unless opts.output_file.blank?
|
32
|
+
@parameters << '--preview true' if opts.preview
|
33
|
+
@parameters << "--steps #{opts.steps}" if opts.task =~ /rollback/
|
34
|
+
@parameters << "--version #{opts.version}" if opts.task =~ /^migrate($|:up)|^rollback:toversion$/
|
35
|
+
@parameters << '--transaction-per-session' if opts.tps
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Config
|
40
|
+
include Albacore::CmdConfig
|
41
|
+
include Physique::ToolLocator
|
42
|
+
self.extend Albacore::ConfigDSL
|
43
|
+
|
44
|
+
# SQL Server instance
|
45
|
+
attr_path :instance
|
46
|
+
|
47
|
+
# SQL Server database
|
48
|
+
attr_writer :database
|
49
|
+
|
50
|
+
# SQL dialect
|
51
|
+
attr_writer :dialect
|
52
|
+
|
53
|
+
# Dll containing the migrations
|
54
|
+
attr_path :dll
|
55
|
+
|
56
|
+
# Namespace of migration to run
|
57
|
+
def namespace=(val)
|
58
|
+
@namespace = val
|
59
|
+
@nested = true
|
60
|
+
end
|
61
|
+
|
62
|
+
def shallow
|
63
|
+
@nested = false
|
64
|
+
end
|
65
|
+
|
66
|
+
def deep
|
67
|
+
@nested = true
|
68
|
+
end
|
69
|
+
|
70
|
+
# Migration task
|
71
|
+
attr_writer :task
|
72
|
+
|
73
|
+
# Version number to migrate to
|
74
|
+
attr_writer :version
|
75
|
+
|
76
|
+
# Number of steps to rollback
|
77
|
+
attr_writer :steps
|
78
|
+
|
79
|
+
# Verbosity
|
80
|
+
attr_writer :verbose
|
81
|
+
|
82
|
+
# Timeout
|
83
|
+
attr_writer :timeout
|
84
|
+
|
85
|
+
# Output file
|
86
|
+
attr_path :output_file
|
87
|
+
|
88
|
+
def output_to_file
|
89
|
+
# Set a default output file
|
90
|
+
@output_file = "#{@database}-output.sql"
|
91
|
+
end
|
92
|
+
|
93
|
+
def transaction_per_session
|
94
|
+
@tps = true
|
95
|
+
end
|
96
|
+
|
97
|
+
def preview
|
98
|
+
@preview = true
|
99
|
+
end
|
100
|
+
|
101
|
+
# Path Migrator executable
|
102
|
+
attr_path :exe
|
103
|
+
|
104
|
+
# Bin folder to look find the Migrate tool if :exe is not set
|
105
|
+
attr_path :bin_dir
|
106
|
+
|
107
|
+
def opts
|
108
|
+
raise ArgumentError, 'You must specify a server name' if @instance.blank?
|
109
|
+
raise ArgumentError, 'You must specify a database name' if @database.blank?
|
110
|
+
raise ArgumentError, 'You must specify the path to the migrator executable' if @exe.blank?
|
111
|
+
raise ArgumentError, 'You must specify a migration dll' if @dll.blank?
|
112
|
+
raise ArgumentError, 'You must specify a valid task' unless valid_tasks.include? @task
|
113
|
+
|
114
|
+
Map.new({
|
115
|
+
connection_string: connection_string,
|
116
|
+
dialect: @dialect,
|
117
|
+
dll: @dll,
|
118
|
+
namespace: @namespace,
|
119
|
+
nested: @nested,
|
120
|
+
task: @task,
|
121
|
+
version: @version,
|
122
|
+
steps: @steps,
|
123
|
+
verbose: @verbose,
|
124
|
+
output_file: @output_file,
|
125
|
+
exe: @exe,
|
126
|
+
tps: @tps,
|
127
|
+
preview: @preview,
|
128
|
+
timeout: @timeout,
|
129
|
+
}).apply(
|
130
|
+
dialect: 'SqlServer2008',
|
131
|
+
verbose: true,
|
132
|
+
version: 0,
|
133
|
+
steps: 1,
|
134
|
+
timeout: 30 # seconds
|
135
|
+
)
|
136
|
+
end
|
137
|
+
|
138
|
+
private
|
139
|
+
|
140
|
+
def connection_string
|
141
|
+
"Data Source=#{@instance};Initial Catalog=#{@database};Integrated Security=True;"
|
142
|
+
end
|
143
|
+
|
144
|
+
def valid_tasks
|
145
|
+
%w{migrate:up migrate migrate:down rollback rollback:toversion rollback:all validateversionorder listmigrations}
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
class Task
|
150
|
+
def initialize(opts)
|
151
|
+
@cmd = Physique::FluentMigrator::Cmd.new opts
|
152
|
+
end
|
153
|
+
|
154
|
+
def execute
|
155
|
+
@cmd.execute
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'albacore/logging'
|
2
|
+
require 'physique/tasks/nugets_pack'
|
3
|
+
|
4
|
+
module Physique
|
5
|
+
module OctopusPack
|
6
|
+
class Config
|
7
|
+
attr_writer :project_file
|
8
|
+
attr_writer :type
|
9
|
+
attr_writer :configuration
|
10
|
+
attr_writer :exe
|
11
|
+
attr_writer :out
|
12
|
+
attr_writer :original_path
|
13
|
+
attr_writer :metadata
|
14
|
+
|
15
|
+
def opts
|
16
|
+
raise ArgumentError, 'You must specify a project file' if @project_file.blank?
|
17
|
+
raise ArgumentError, 'You must specify a version' if @metadata.version.blank?
|
18
|
+
raise ArgumentError, 'You must specify the NuGet executable' if @exe.blank?
|
19
|
+
raise ArgumentError, 'You must specify an output folder' if @out.blank?
|
20
|
+
|
21
|
+
Map.new({
|
22
|
+
project_file: @project_file,
|
23
|
+
type: @type,
|
24
|
+
configuration: @configuration,
|
25
|
+
exe: @exe,
|
26
|
+
out: @out,
|
27
|
+
original_path: @original_path,
|
28
|
+
metadata: @metadata,
|
29
|
+
}).apply({
|
30
|
+
type: :console,
|
31
|
+
configuration: 'Release',
|
32
|
+
original_path: FileUtils.pwd,
|
33
|
+
verify_files: true,
|
34
|
+
})
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class Task
|
39
|
+
include Albacore::Logging
|
40
|
+
|
41
|
+
def initialize(opts)
|
42
|
+
@opts = opts
|
43
|
+
@project = Albacore::Project.new opts.project_file
|
44
|
+
|
45
|
+
opts.metadata.id = @project.name if @project.name
|
46
|
+
@package = Albacore::NugetModel::Package.new opts.metadata
|
47
|
+
end
|
48
|
+
|
49
|
+
def execute
|
50
|
+
if @opts.type == :website
|
51
|
+
add_content_files
|
52
|
+
add_binary_files target: 'bin'
|
53
|
+
else
|
54
|
+
add_content_files
|
55
|
+
add_binary_files
|
56
|
+
end
|
57
|
+
|
58
|
+
nuspec_path = write_nuspec!
|
59
|
+
create_nuget! @project.proj_path_base, nuspec_path
|
60
|
+
ensure
|
61
|
+
cleanup_nuspec nuspec_path
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def write_nuspec!
|
67
|
+
raise ArgumentError, "no nuspec metadata id, project at path: #{@project.proj_path_base}, nuspec: #{@package.inspect}" unless @package.metadata.id
|
68
|
+
|
69
|
+
path = File.join(@project.proj_path_base, @package.metadata.id + '.nuspec')
|
70
|
+
File.write(path, @package.to_xml)
|
71
|
+
path
|
72
|
+
end
|
73
|
+
|
74
|
+
def create_nuget!(cwd, nuspec_file)
|
75
|
+
# create the command
|
76
|
+
exe = path_to(@opts.exe, cwd)
|
77
|
+
out = path_to(@opts.out, cwd)
|
78
|
+
nuspec = path_to(nuspec_file, cwd)
|
79
|
+
cmd = Albacore::NugetsPack::Cmd.new exe,
|
80
|
+
work_dir: cwd,
|
81
|
+
out: out
|
82
|
+
|
83
|
+
# Octopus packages don't confirm to NuGet standards so
|
84
|
+
# disable package analysis to prevent unnecessary warnings.
|
85
|
+
cmd.disable_package_analysis
|
86
|
+
|
87
|
+
# run the command for the file
|
88
|
+
pkg, _ = cmd.execute nuspec
|
89
|
+
|
90
|
+
publish_artifact nuspec, pkg
|
91
|
+
end
|
92
|
+
|
93
|
+
def cleanup_nuspec nuspec
|
94
|
+
return if nuspec.nil? or not File.exists? nuspec
|
95
|
+
return if @opts.get :leave_nuspec, false
|
96
|
+
File.delete nuspec
|
97
|
+
end
|
98
|
+
|
99
|
+
def path_to(relative_file_path, cwd)
|
100
|
+
File.expand_path(File.join(@opts.get(:original_path), relative_file_path), cwd)
|
101
|
+
end
|
102
|
+
|
103
|
+
def publish_artifact(nuspec, nuget)
|
104
|
+
Albacore.publish :artifact, OpenStruct.new(
|
105
|
+
nuspec: nuspec,
|
106
|
+
nupkg: nuget,
|
107
|
+
location: nuget
|
108
|
+
)
|
109
|
+
end
|
110
|
+
|
111
|
+
def add_content_files
|
112
|
+
@project.
|
113
|
+
included_files.
|
114
|
+
keep_if { |f| f.item_name == 'content' && f.item_name != 'packages.config' }.
|
115
|
+
each { |f| @package.add_file f.include, f.include}
|
116
|
+
end
|
117
|
+
|
118
|
+
def add_binary_files(options = {})
|
119
|
+
target = options[:target] || ''
|
120
|
+
|
121
|
+
output_path = get_output_path
|
122
|
+
Dir.new(get_absolute_output_path).entries.
|
123
|
+
keep_if { |f| f =~ /^.*\.(dll|exe|pdb|config)$/i}.
|
124
|
+
each { |f| @package.add_file bin_target(output_path, f), bin_target(target, f) }
|
125
|
+
end
|
126
|
+
|
127
|
+
def bin_target(target, file_name)
|
128
|
+
return file_name if target.blank?
|
129
|
+
File.join(target, file_name)
|
130
|
+
end
|
131
|
+
|
132
|
+
def get_absolute_output_path
|
133
|
+
File.expand_path get_output_path, @project.proj_path_base
|
134
|
+
end
|
135
|
+
|
136
|
+
def get_output_path
|
137
|
+
Albacore::NugetModel::Package.get_output_path(@project, Map.new(configuration: @opts.configuration))
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'active_support/core_ext/string'
|
2
|
+
require 'albacore'
|
3
|
+
require 'albacore/cmd_config'
|
4
|
+
require 'physique/tool_locator'
|
5
|
+
|
6
|
+
module Physique
|
7
|
+
module SqlCmd
|
8
|
+
class Cmd
|
9
|
+
include Albacore::CrossPlatformCmd
|
10
|
+
|
11
|
+
attr_reader :parameters
|
12
|
+
|
13
|
+
def initialize(opts)
|
14
|
+
@executable = opts[:exe]
|
15
|
+
set_parameters opts
|
16
|
+
end
|
17
|
+
|
18
|
+
def execute
|
19
|
+
sh "#{@executable} #{@parameters.join(' ')}"
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def set_parameters(opts)
|
25
|
+
@parameters = @parameters || []
|
26
|
+
@parameters << "-S #{opts[:server_name]}"
|
27
|
+
@parameters << "-d #{opts[:database_name]}" unless opts.blank? :database_name
|
28
|
+
@parameters << "-i #{opts[:file]}" if opts[:source] == :file
|
29
|
+
@parameters << "-Q '#{opts[:command]}'" if opts[:source] == :command
|
30
|
+
@parameters << '-b' unless opts[:continue_on_error]
|
31
|
+
|
32
|
+
opts[:variables].each do |k, v|
|
33
|
+
@parameters << "-v #{k}=#{v}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class Config
|
39
|
+
include Albacore::CmdConfig
|
40
|
+
include Physique::ToolLocator
|
41
|
+
self.extend Albacore::ConfigDSL
|
42
|
+
|
43
|
+
# The database server
|
44
|
+
attr_path :server_name
|
45
|
+
|
46
|
+
# The database name
|
47
|
+
attr_writer :database_name
|
48
|
+
|
49
|
+
# The sql script to execute
|
50
|
+
attr_path :file
|
51
|
+
|
52
|
+
# The sql command to execute
|
53
|
+
attr_writer :command
|
54
|
+
|
55
|
+
def initialize
|
56
|
+
@variables = Hash.new
|
57
|
+
@continue_on_error = false
|
58
|
+
|
59
|
+
@exe = which('sqlcmd') ||
|
60
|
+
locate_tool('C:/Program Files/Microsoft SQL Server/**/Tools/Binn/SQLCMD.EXE')
|
61
|
+
end
|
62
|
+
|
63
|
+
def set_variable(k, v)
|
64
|
+
@variables[k] = v
|
65
|
+
end
|
66
|
+
|
67
|
+
def continue_on_error
|
68
|
+
@continue_on_error = true
|
69
|
+
end
|
70
|
+
|
71
|
+
def opts
|
72
|
+
raise ArgumentError, 'You must specify a server name' if @server_name.blank?
|
73
|
+
raise ArgumentError, 'You must specify a command or a file to execute' unless can_execute?
|
74
|
+
|
75
|
+
Map.new({
|
76
|
+
exe: @exe,
|
77
|
+
server_name: @server_name,
|
78
|
+
database_name: @database_name,
|
79
|
+
file: @file,
|
80
|
+
command: @command,
|
81
|
+
source: execute_source,
|
82
|
+
continue_on_error: @continue_on_error,
|
83
|
+
variables: @variables
|
84
|
+
})
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def can_execute?
|
90
|
+
!(@file.blank? && @command.blank?)
|
91
|
+
end
|
92
|
+
|
93
|
+
def execute_source
|
94
|
+
# Command takes precedence over a file
|
95
|
+
return :command unless @command.blank?
|
96
|
+
:file
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class Task
|
101
|
+
def initialize(opts)
|
102
|
+
@cmd = Physique::SqlCmd::Cmd.new opts
|
103
|
+
end
|
104
|
+
|
105
|
+
def execute
|
106
|
+
@cmd.execute
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|