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,9 @@
1
+ module Physique
2
+ class DefaultTasksBuilder < TasksBuilder
3
+ def build_tasks
4
+ Rake::Task.define_task :default => [ :test ]
5
+ Rake::Task.define_task :ci => [ :versionizer, :test ]
6
+ end
7
+ end
8
+ end
9
+
@@ -0,0 +1,227 @@
1
+ require 'physique/project'
2
+
3
+ module Physique
4
+ class FluentMigratorConfig
5
+ self.extend Albacore::ConfigDSL
6
+ include Albacore::Logging
7
+
8
+ # Project name or path
9
+ attr_path :project
10
+
11
+ attr_writer :lang, # Programming language of the db project
12
+ :instance, # Server instance name
13
+ :name, # Database name
14
+ :scripts_dir, # Scripts folder to examine to create tasks
15
+ :dialect # Dialect to use for generating SQL
16
+
17
+ def initialize
18
+ @lang = :cs
19
+ @scripts_dir = '_Scripts'
20
+ end
21
+
22
+ def opts
23
+ Map.new({
24
+ exe: @exe,
25
+ instance: @instance,
26
+ name: @name,
27
+ project: @project,
28
+ project_file: Physique::Project.get_path(@project, @lang),
29
+ lang: @lang,
30
+ }).apply(
31
+ lang: :cs,
32
+ project_dir: "src/#{@project}",
33
+ scripts_dir: "src/#{@project}/#{@scripts_dir}"
34
+ )
35
+ end
36
+ end
37
+
38
+ class FluentMigratorTasksBuilder < TasksBuilder
39
+ def build_tasks
40
+ @options = solution.migrator
41
+ return if @options.nil?
42
+
43
+ add_script_tasks
44
+ add_default_db_tasks
45
+ add_migrator_tasks
46
+ add_workflow_tasks
47
+ add_new_migration_task
48
+ end
49
+
50
+ private
51
+
52
+ def add_script_tasks
53
+ FileList["#{@options.scripts_dir}/*.sql"].each do |f|
54
+ namespace :db do
55
+ task_name = File.basename(f, '.*')
56
+ task = sqlcmd_task task_name do |s|
57
+ s.file = f
58
+ s.server_name = @options.instance
59
+ s.set_variable 'DATABASE_NAME', @options.name
60
+ end
61
+ task.add_description get_script_task_description(task_name, @options.scripts_dir)
62
+ end
63
+ end
64
+ end
65
+
66
+ def add_default_db_tasks
67
+ default_tasks(@options.name).each do |task_name,sql|
68
+ unless Rake::Task.task_defined? "db:#{task_name.to_s}"
69
+ namespace :db do
70
+ task = sqlcmd_task task_name do |s|
71
+ s.command = sql
72
+ s.server_name = @options.instance
73
+ s.set_variable 'DATABASE_NAME', @options.name
74
+ end
75
+ task.add_description get_script_task_description(task_name, @options.scripts_dir)
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ def default_tasks(database)
82
+ { create: "CREATE DATABASE #{database}",
83
+ drop: "DROP DATABASE #{database}",
84
+ seed: 'SELECT 1' } # This is a no-op
85
+ end
86
+
87
+ def get_script_task_description(task, dir)
88
+ well_known_scripts[task.to_sym] || "Executes #{task}.sql in the #{dir} folder."
89
+ end
90
+
91
+ # TODO: Refactor this to combine this with default_tasks
92
+ def well_known_scripts
93
+ { create: 'Creates the database',
94
+ drop: 'Drops the database',
95
+ seed: 'Seeds the database with test data' }
96
+ end
97
+
98
+ def add_migrator_tasks
99
+ require 'physique/tasks/fluent_migrator'
100
+
101
+ namespace :db do
102
+ build_task :compile_db do |b|
103
+ b.target = [ 'Build' ]
104
+ b.file = solution.migrator.project_file
105
+ b.prop 'Configuration', solution.compile.configuration
106
+ b.logging = solution.compile.logging
107
+ end
108
+
109
+ block = lambda &method(:configure_migration)
110
+
111
+ # Migrate up
112
+ task = fluent_migrator_task :migrate => [ :compile_db ], &block.curry.('migrate:up')
113
+ task.add_description 'Migrate database to the latest version'
114
+
115
+ # Migrate down
116
+ task = fluent_migrator_task :rollback => [ :compile_db ], &block.curry.('rollback')
117
+ task.add_description 'Rollback the database to the previous version'
118
+ end
119
+ end
120
+
121
+ def configure_migration(task, config)
122
+ config.instance = solution.migrator.instance
123
+ config.database = solution.migrator.name
124
+ config.task = task
125
+ config.dll = migration_dll
126
+ config.exe = locate_tool(tool_in_output_folder || tool_in_nuget_package)
127
+ config.output_to_file
128
+ end
129
+
130
+ def add_workflow_tasks
131
+ namespace :db do
132
+ # Try the migration
133
+ task = Rake::Task.define_task :try => [ :migrate, :rollback ]
134
+ task.add_description 'Migrate and then immediately rollback'
135
+
136
+ # Setup the database from nothing
137
+ task = Rake::Task.define_task :setup => [ :create, :migrate, :seed ]
138
+ task.add_description 'Create the database and run all migrations'
139
+
140
+ # Setup the database from nothing
141
+ task = Rake::Task.define_task :rebuild => [ :drop, :setup ]
142
+ task.add_description 'Drop and recreate the database'
143
+ end
144
+ end
145
+
146
+ def migration_dll
147
+ "#{solution.migrator.project_dir}/bin/#{solution.compile.configuration}/#{solution.migrator.project}.dll"
148
+ end
149
+
150
+ def tool_in_output_folder
151
+ existing_path "#{solution.migrator.project_dir}/bin/#{solution.compile.configuration}/Migrate.exe"
152
+ end
153
+
154
+ def tool_in_nuget_package
155
+ existing_path "#{solution.nuget.restore_location}/FluentMigrator.*/tools/Migrate.exe"
156
+ end
157
+
158
+ def existing_path(path)
159
+ return path if FileList[path].any? { |p| File.exists? p }
160
+ nil
161
+ end
162
+
163
+ def add_new_migration_task
164
+ namespace :db do
165
+ task = Rake::Task.define_task :new_migration, :name, :description do |t, args|
166
+ name, description = args[:name], args[:description]
167
+
168
+ unless name
169
+ abort [
170
+ %Q{Usage: rake "#{t.name}[name[,description]]"},
171
+ desc,
172
+ ].join "\n\n"
173
+ end
174
+
175
+ project, project_dir, project_file = solution.migrator.project, solution.migrator.project_dir, solution.migrator.project_file
176
+ version = migration_version
177
+ migration_file_name = "#{version}_#{name}.cs"
178
+ migration_content = migration_template(version, name, description, project)
179
+
180
+ # Save the new migration file
181
+ save_file migration_content, "#{project_dir}/Migrations/#{migration_file_name}"
182
+
183
+ # Add the new migration file to the project
184
+ Albacore::Project.new(project_file).tap do |p|
185
+ p.add_compile_node :Migrations, migration_file_name
186
+ p.save
187
+ end
188
+ end
189
+ task.add_description 'Creates a new migration file with the specified name'
190
+ end
191
+ end
192
+
193
+ def migration_version
194
+ Time.now.utc.strftime('%Y%m%d%H%M%S')
195
+ end
196
+
197
+ def migration_template(version, name, description, project_name)
198
+ description = ", \"#{description}\"" unless description.nil?
199
+ return <<TEMPLATE
200
+ using FluentMigrator;
201
+ using FluentMigrator.Runner;
202
+
203
+ namespace #{project_name}.Migrations
204
+ {
205
+ [Migration(#{version}#{description})]
206
+ public class #{name} : Migration
207
+ {
208
+ public override void Up()
209
+ {
210
+ // Add migration code here
211
+ }
212
+
213
+ public override void Down()
214
+ {
215
+ // Add migration rollback code here
216
+ }
217
+ }
218
+ }
219
+ TEMPLATE
220
+ end
221
+
222
+ def save_file(content, file_path)
223
+ raise "#{file_path} already exists, cancelling" if File.exists? file_path
224
+ File.open(file_path, 'w') { |f| f.write(content) }
225
+ end
226
+ end
227
+ end
@@ -0,0 +1,45 @@
1
+ module Physique
2
+ class NugetConfig
3
+ self.extend Albacore::ConfigDSL
4
+
5
+ attr_path :exe, # Path to nuget executable
6
+ :restore_location, # Path where nuget packages will be downloaded
7
+ :build_location # Path where nuget packages will be built
8
+
9
+ # Disable metadata analysis (sets -NoPackageAnalysis flag)
10
+ def disable_package_analysis
11
+ @disable_package_analysis = true
12
+ end
13
+
14
+ def initialize
15
+ @exe = 'src/.nuget/NuGet.exe'
16
+ @restore_location = 'src/packages'
17
+ @build_location = 'build/packages'
18
+ end
19
+
20
+ def opts
21
+ Map.new({
22
+ exe: @exe,
23
+ restore_location: @restore_location,
24
+ build_location: @build_location,
25
+ disable_package_analysis: !!@disable_package_analysis
26
+ })
27
+ end
28
+ end
29
+
30
+ class NugetTasksBuilder < TasksBuilder
31
+ def build_tasks
32
+ add_restore
33
+ end
34
+
35
+ private
36
+
37
+ def add_restore
38
+ task = nugets_restore_task :restore do |r|
39
+ r.out = solution.nuget.restore_location
40
+ r.exe = solution.nuget.exe
41
+ end
42
+ task.add_description 'Restores all nugets as per the packages.config files'
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,147 @@
1
+ require 'albacore'
2
+ require 'albacore/nuget_model'
3
+ require 'physique/config'
4
+
5
+ module Physique
6
+ class OctopusDeployConfig
7
+ attr_writer :server, # The server name of the deployment server
8
+ :api_key # The API key of the deployment server
9
+
10
+ def initialize
11
+ @apps = []
12
+ @alias_tasks = true
13
+ end
14
+
15
+ # Do not alias the tasks without the 'octo' prefix.
16
+ def no_alias_tasks
17
+ @alias_tasks = false
18
+ end
19
+
20
+ def deploy_app
21
+ config = OctopusDeployAppConfig.new
22
+ yield config
23
+ @apps << config
24
+ end
25
+
26
+ def opts
27
+ raise ArgumentError, 'You must specify a server to deploy to' if @server.blank?
28
+ raise ArgumentError, 'You must specify at least one application to deploy' if @apps.blank?
29
+
30
+ Map.new({
31
+ server: @server,
32
+ api_key: @api_key,
33
+ alias_tasks: @alias_tasks,
34
+ apps: @apps.map { |a| a.opts }
35
+ })
36
+ end
37
+ end
38
+
39
+ class OctopusDeployAppConfig < MetadataConfig
40
+ attr_writer :name, # The name for the build task
41
+ :project, # The project to deploy
42
+ :type, # The type of app to deploy
43
+ :lang # The programming language of the project to deploy
44
+
45
+ def initialize
46
+ super
47
+ @type = :console
48
+ @lang = :cs
49
+ end
50
+
51
+ def opts
52
+ raise ArgumentError, 'You must specify a :project to deploy' if @project.blank?
53
+ raise ArgumentError, 'You must specify the :type of project to deploy' if @type.blank?
54
+ raise ArgumentError, "Project :type #{@type} is not supported." unless supported_types.include? @type
55
+
56
+ project_file_path = Physique::Project.get_path(@project, @lang)
57
+ _, project_file = File.split project_file_path
58
+ project_name = File.basename(project_file, '.*')
59
+
60
+ Map.new({
61
+ type: @type,
62
+ name: @name || @project,
63
+ project: project_name,
64
+ project_file: project_file_path,
65
+ metadata: @metadata
66
+ })
67
+ end
68
+
69
+ private
70
+
71
+ def supported_types
72
+ [ :console, :service, :website ]
73
+ end
74
+ end
75
+
76
+ class OctopusTasksBuilder < TasksBuilder
77
+ def build_tasks
78
+ @options = solution.octopus
79
+ return if @options.nil?
80
+ return if @options.apps.blank?
81
+
82
+ add_octopus_package_tasks
83
+ add_octopus_publish_tasks
84
+
85
+ if @options.alias_tasks
86
+ add_task_aliases
87
+ end
88
+ end
89
+
90
+ private
91
+
92
+ def add_octopus_package_tasks
93
+ @options.apps.each do |a|
94
+ namespace :octo do
95
+ namespace :package do
96
+ task = octopus_pack_task a.name => [:versionizer, :test] do |o|
97
+ ensure_output_location solution.nuget.build_location
98
+
99
+ o.project_file = a.project_file
100
+ o.type = a.type
101
+ o.configuration = solution.compile.configuration
102
+ o.exe = solution.nuget.exe
103
+ o.out = solution.nuget.build_location
104
+ o.metadata = a.metadata
105
+ end
106
+ task.add_description "Package #{a.project} for Octopus deployment"
107
+ end
108
+
109
+ task = Rake::Task.define_task :package => all_octopus_app_tasks('package')
110
+ task.add_description 'Package all applications'
111
+ end
112
+ end
113
+ end
114
+
115
+ def add_octopus_publish_tasks
116
+ nuget = solution.nuget
117
+
118
+ @options.apps.each do |a|
119
+ namespace :octo do
120
+ namespace :publish do
121
+ task = Rake::Task.define_task a.name => [ "package:#{a.name}" ] do
122
+ package_location = Albacore::Paths.normalise_slashes "#{nuget.build_location}/#{a.project}.#{a.metadata.version}.nupkg"
123
+ sh "#{nuget.exe} push #{package_location} -ApiKey #{@options.api_key} -Source #{@options.server}"
124
+ end
125
+ task.add_description "Publish #{a.project} app to Octopus Server"
126
+ end
127
+
128
+ task = Rake::Task.define_task :publish => all_octopus_app_tasks('publish')
129
+ task.add_description 'Publish all apps to Octopus Server'
130
+ end
131
+ end
132
+ end
133
+
134
+ def all_octopus_app_tasks(task)
135
+ # It is assumed that this is called within the octo namespace
136
+ @options.apps.map { |a| "#{task}:#{a.name}" }
137
+ end
138
+
139
+ def add_task_aliases
140
+ task = Rake::Task.define_task :package => [ 'octo:package' ]
141
+ task.add_description 'Package all applications'
142
+
143
+ task = Rake::Task.define_task :publish => [ 'octo:publish' ]
144
+ task.add_description 'Publish apps to Octopus Server'
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,133 @@
1
+ require 'physique/config'
2
+
3
+ module Physique
4
+ class PublishNugetsConfig < MetadataConfig
5
+ attr_writer :project_files, # Project files to include
6
+ :exclude, # Project files to exclude
7
+ :local_path, # Path to publish locally
8
+ :feed_url, # Nuget feed to publish packages
9
+ :api_key # Nuget API key
10
+
11
+ def initialize
12
+ super
13
+ @alias_tasks = true
14
+ end
15
+
16
+ # Do not alias the tasks without the 'nuget' prefix.
17
+ def no_alias_tasks
18
+ @alias_tasks = false
19
+ end
20
+
21
+ def symbols_feed_url=(value)
22
+ @gen_symbols = true
23
+ @symbols_feed_url = value
24
+ end
25
+
26
+ def opts
27
+ Map.new(
28
+ project_files: FileList[project_files_or_default].exclude(exclude_or_default),
29
+ metadata: @metadata,
30
+ local_path: @local_path,
31
+ feed_url: @feed_url,
32
+ gen_symbols: @gen_symbols,
33
+ symbols_feed_url: @symbols_feed_url,
34
+ api_key: @api_key,
35
+ alias_tasks: @alias_tasks
36
+ ).apply(
37
+ local_path: 'C:/Nuget.Local'
38
+ )
39
+ end
40
+
41
+ def project_files_or_default
42
+ @project_files || 'src/**/*.{csproj,fsproj,nuspec}'
43
+ end
44
+
45
+ def exclude_or_default
46
+ @exclude || /Tests/
47
+ end
48
+ end
49
+
50
+ class PublishNugetsTasksBuilder < TasksBuilder
51
+ def build_tasks
52
+ @options = solution.publish_nugets
53
+ return if @options.nil?
54
+
55
+ add_package_nugets_task
56
+ add_publish_nugets_task
57
+ add_publish_nugets_local_task
58
+
59
+ if @options.alias_tasks
60
+ add_task_aliases
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ def add_package_nugets_task
67
+ namespace :nuget do
68
+ task = nugets_pack_task :package => [ :versionizer, :test ] do |p|
69
+ ensure_output_location solution.nuget.build_location
70
+
71
+ p.configuration = solution.compile.configuration
72
+ p.out = solution.nuget.build_location
73
+ p.exe = solution.nuget.exe
74
+ p.files = @options.project_files
75
+ p.gen_symbols if @options.gen_symbols
76
+ p.with_metadata do |m|
77
+ @options.metadata.set_fields.each do |attr|
78
+ eval "m.#{attr}= @options.metadata.#{attr}"
79
+ end
80
+ end
81
+ end
82
+ task.add_description 'Package all nugets'
83
+ end
84
+ end
85
+
86
+ def add_publish_nugets_task
87
+ namespace :nuget do
88
+ task = Rake::Task.define_task :publish => [ 'nuget:package' ] do
89
+ raise ArgumentError, 'You must specify an :api_key to connect to the server' if @options.api_key.blank?
90
+
91
+ nuget_project_names.each do |p|
92
+ sh nuget_publish_command(p, 'nupkg', @options.feed_url)
93
+
94
+ if @options.gen_symbols
95
+ sh nuget_publish_command(p, 'symbols.nupkg', @options.symbols_feed_url)
96
+ end
97
+ end
98
+ end
99
+ task.add_description 'Publish nuget packages to feed'
100
+ end
101
+ end
102
+
103
+ def nuget_publish_command(name, extension, feed)
104
+ "#{solution.nuget.exe} push #{solution.nuget.build_location}/#{name}.#{@options.metadata.version}.#{extension} #{@options.api_key} -Source #{feed}"
105
+ end
106
+
107
+ def add_publish_nugets_local_task
108
+ local_path = @options.local_path
109
+
110
+ namespace :nuget do
111
+ namespace :publish do
112
+ task = Rake::Task.define_task :local => [ 'nuget:package' ] do
113
+ ensure_output_location local_path
114
+ FileUtils.cp FileList["#{solution.nuget.build_location}/*"], local_path
115
+ end
116
+ task.add_description 'Copy nuget packages to local path'
117
+ end
118
+ end
119
+ end
120
+
121
+ def nuget_project_names
122
+ Set.new(@options.project_files.map { |f| Albacore::Project.new f }.map { |p| p.name })
123
+ end
124
+
125
+ def add_task_aliases
126
+ task = Rake::Task.define_task :package => [ 'nuget:package' ]
127
+ task.add_description 'Package all nugets'
128
+
129
+ task = Rake::Task.define_task :publish => [ 'nuget:publish' ]
130
+ task.add_description 'Publish nuget packages to feed'
131
+ end
132
+ end
133
+ end