circus-deployment 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. data/LICENSE +23 -0
  2. data/README.md +0 -0
  3. data/bin/circus +24 -0
  4. data/lib/bundler/circus_bundler.rb +24 -0
  5. data/lib/bundler/circus_util.rb +43 -0
  6. data/lib/bundler/patches.rb +18 -0
  7. data/lib/circus/act.rb +74 -0
  8. data/lib/circus/actstore_client.rb +30 -0
  9. data/lib/circus/agents/agent.rb +59 -0
  10. data/lib/circus/agents/client.rb +77 -0
  11. data/lib/circus/agents/connection.rb +76 -0
  12. data/lib/circus/agents/conversation.rb +17 -0
  13. data/lib/circus/agents/dbus_connection.rb +85 -0
  14. data/lib/circus/agents/dbus_logger.rb +34 -0
  15. data/lib/circus/agents/encoding.rb +32 -0
  16. data/lib/circus/agents/logger.rb +52 -0
  17. data/lib/circus/agents/params.rb +47 -0
  18. data/lib/circus/agents/ssh_connection.rb +120 -0
  19. data/lib/circus/application.rb +99 -0
  20. data/lib/circus/booth_client.rb +25 -0
  21. data/lib/circus/booth_tool.rb +98 -0
  22. data/lib/circus/cli.rb +147 -0
  23. data/lib/circus/clown_client.rb +27 -0
  24. data/lib/circus/connection_builder.rb +32 -0
  25. data/lib/circus/external_util.rb +14 -0
  26. data/lib/circus/local_config.rb +65 -0
  27. data/lib/circus/profiles/base.rb +115 -0
  28. data/lib/circus/profiles/django.rb +90 -0
  29. data/lib/circus/profiles/jekyll.rb +90 -0
  30. data/lib/circus/profiles/make_base.rb +17 -0
  31. data/lib/circus/profiles/pure_py.rb +46 -0
  32. data/lib/circus/profiles/pure_rb.rb +48 -0
  33. data/lib/circus/profiles/python_base.rb +39 -0
  34. data/lib/circus/profiles/rack.rb +59 -0
  35. data/lib/circus/profiles/ruby_base.rb +52 -0
  36. data/lib/circus/profiles/shell.rb +46 -0
  37. data/lib/circus/profiles.rb +10 -0
  38. data/lib/circus/repos/git.rb +42 -0
  39. data/lib/circus/repos/mercurial.rb +42 -0
  40. data/lib/circus/repos.rb +16 -0
  41. data/lib/circus/resource_allocator_client.rb +19 -0
  42. data/lib/circus/stdout_logger.rb +11 -0
  43. data/lib/circus/version.rb +3 -0
  44. data/lib/circus.rb +9 -0
  45. data/vendor/ruby-dbus/COPYING +504 -0
  46. data/vendor/ruby-dbus/ChangeLog +782 -0
  47. data/vendor/ruby-dbus/HOWTO-RELEASE +14 -0
  48. data/vendor/ruby-dbus/NEWS +104 -0
  49. data/vendor/ruby-dbus/README +53 -0
  50. data/vendor/ruby-dbus/Rakefile +47 -0
  51. data/vendor/ruby-dbus/doc/tutorial/src/00.index.page +12 -0
  52. data/vendor/ruby-dbus/doc/tutorial/src/10.intro.page +127 -0
  53. data/vendor/ruby-dbus/doc/tutorial/src/20.basic_client.page +174 -0
  54. data/vendor/ruby-dbus/doc/tutorial/src/30.service.page +121 -0
  55. data/vendor/ruby-dbus/doc/tutorial/src/default.css +129 -0
  56. data/vendor/ruby-dbus/doc/tutorial/src/default.template +46 -0
  57. data/vendor/ruby-dbus/examples/gdbus/gdbus +255 -0
  58. data/vendor/ruby-dbus/examples/gdbus/gdbus.glade +184 -0
  59. data/vendor/ruby-dbus/examples/gdbus/launch.sh +4 -0
  60. data/vendor/ruby-dbus/examples/no-introspect/nm-test.rb +21 -0
  61. data/vendor/ruby-dbus/examples/no-introspect/tracker-test.rb +16 -0
  62. data/vendor/ruby-dbus/examples/rhythmbox/playpause.rb +25 -0
  63. data/vendor/ruby-dbus/examples/service/call_service.rb +25 -0
  64. data/vendor/ruby-dbus/examples/service/service_newapi.rb +51 -0
  65. data/vendor/ruby-dbus/examples/simple/call_introspect.rb +34 -0
  66. data/vendor/ruby-dbus/examples/utils/listnames.rb +11 -0
  67. data/vendor/ruby-dbus/examples/utils/notify.rb +19 -0
  68. data/vendor/ruby-dbus/lib/dbus/auth.rb +156 -0
  69. data/vendor/ruby-dbus/lib/dbus/bus.rb +750 -0
  70. data/vendor/ruby-dbus/lib/dbus/export.rb +133 -0
  71. data/vendor/ruby-dbus/lib/dbus/introspect.rb +544 -0
  72. data/vendor/ruby-dbus/lib/dbus/marshall.rb +443 -0
  73. data/vendor/ruby-dbus/lib/dbus/matchrule.rb +100 -0
  74. data/vendor/ruby-dbus/lib/dbus/message.rb +293 -0
  75. data/vendor/ruby-dbus/lib/dbus/type.rb +222 -0
  76. data/vendor/ruby-dbus/lib/dbus.rb +89 -0
  77. data/vendor/ruby-dbus/ruby-dbus.gemspec +28 -0
  78. data/vendor/ruby-dbus/setup.rb +1585 -0
  79. data/vendor/ruby-dbus/test/Makefile +4 -0
  80. data/vendor/ruby-dbus/test/bus_driver_test.rb +21 -0
  81. data/vendor/ruby-dbus/test/server_robustness_test.rb +41 -0
  82. data/vendor/ruby-dbus/test/server_test.rb +44 -0
  83. data/vendor/ruby-dbus/test/service_newapi.rb +99 -0
  84. data/vendor/ruby-dbus/test/session_bus_test_manual.rb +20 -0
  85. data/vendor/ruby-dbus/test/signal_test.rb +57 -0
  86. data/vendor/ruby-dbus/test/t1 +4 -0
  87. data/vendor/ruby-dbus/test/t2.rb +66 -0
  88. data/vendor/ruby-dbus/test/t3-ticket27.rb +18 -0
  89. data/vendor/ruby-dbus/test/t5-report-dbus-interface.rb +58 -0
  90. data/vendor/ruby-dbus/test/t6-loop.rb +85 -0
  91. data/vendor/ruby-dbus/test/test_all +26 -0
  92. data/vendor/ruby-dbus/test/test_server +74 -0
  93. data/vendor/ruby-dbus/test/variant_test.rb +66 -0
  94. metadata +225 -0
@@ -0,0 +1,115 @@
1
+ require 'net/http'
2
+ require 'yaml'
3
+ require 'circus/external_util'
4
+
5
+ module Circus
6
+ module Profiles
7
+ PROFILES=[]
8
+
9
+ # Base functionality for an Profile
10
+ class Base
11
+ def initialize(name, dir, props)
12
+ @name = name
13
+ @dir = dir
14
+ @props = props
15
+ end
16
+
17
+ def package_base_dir?
18
+ true
19
+ end
20
+
21
+ def extra_dirs
22
+ []
23
+ end
24
+
25
+ def package_for_dev(logger, run_dir)
26
+ return false unless prepare_for_dev(logger, run_dir)
27
+ write_run_script(run_dir) do |f|
28
+ f.write(dev_run_script_content.strip)
29
+ end
30
+ end
31
+
32
+ def package_for_deploy(logger, run_dir)
33
+ return false unless prepare_for_deploy(logger, run_dir)
34
+ write_run_script(run_dir) do |f|
35
+ f.write(deploy_run_script_content.strip)
36
+ end
37
+ File.open(File.join(run_dir, 'requirements.yaml'), 'w') do |f|
38
+ f.write(requirements.to_yaml)
39
+ end
40
+ end
41
+
42
+ def cleanup_after_deploy(logger, overlay_dir)
43
+ end
44
+
45
+ # Overriden by subclasses to specify the resources that they require. Defaults to a resource
46
+ # hash provided in the act definition
47
+ def requirements
48
+ (@props['requirements'] || {}).dup
49
+ end
50
+
51
+ protected
52
+ # Overriden by subclasses to handle development preparation. Defaults to the same as the deployment preparation.
53
+ def prepare_for_dev(logger, run_dir)
54
+ prepare_for_deploy(logger, run_dir)
55
+ end
56
+
57
+ # Overriden by classes to handle generating the run script content for development.
58
+ def dev_run_script_content
59
+ end
60
+
61
+ # Overriden by subclasses to handle deployment preparation
62
+ def prepare_for_deploy(logger, run_dir)
63
+ true
64
+ end
65
+
66
+ # Overriden by classes to handle generating the run script content for deployment.
67
+ def deploy_run_script_content
68
+ end
69
+
70
+ def write_run_script(run_dir)
71
+ File.open(File.join(run_dir, 'run'), 'w') do |f|
72
+ yield f
73
+ end
74
+ File.chmod 0777, File.join(run_dir, 'run')
75
+ end
76
+
77
+ def shell_run_script
78
+ <<-EOT
79
+ #!/bin/sh
80
+
81
+ #{yield}
82
+ EOT
83
+ end
84
+
85
+ def write_dev_run_script(run_dir)
86
+ write_run_script(run_dir) do |f|
87
+ base_template = <<-EOT
88
+ #!/bin/sh
89
+
90
+ cd #{@dir}
91
+ EOT
92
+
93
+ f.write(base_template.lstrip)
94
+ yield f
95
+ end
96
+ end
97
+
98
+ def write_deploy_run_script(run_dir)
99
+ write_run_script(run_dir) do |f|
100
+ base_template = <<-EOT
101
+ #!/bin/sh
102
+
103
+ EOT
104
+
105
+ f.write(base_template.lstrip)
106
+ yield f
107
+ end
108
+ end
109
+
110
+ def run_external(logger, desc, cmd)
111
+ ExternalUtil.run_external(logger, desc, cmd)
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,90 @@
1
+ require File.expand_path('../python_base', __FILE__)
2
+
3
+ module Circus
4
+ module Profiles
5
+ class Django < PythonBase
6
+ DJANGO_APP_PROPERTY='django-app'
7
+
8
+ # Checks if this is a Django application. Will accept the application if it
9
+ # has a file named manage.py, or has a 'django-app' property describing the entry point.
10
+ def self.accepts?(name, dir, props)
11
+ return true if props.include? DJANGO_APP_PROPERTY
12
+ return File.exists?(File.join(dir, "manage.py"))
13
+ end
14
+
15
+ def initialize(name, dir, props)
16
+ super(name, dir, props)
17
+
18
+ @manage_script = props[DJANGO_APP_PROPERTY] || "manage.py"
19
+ end
20
+
21
+ # The name of this profile
22
+ def name
23
+ "django"
24
+ end
25
+
26
+ def prepare_for_deploy(logger, overlay_dir)
27
+ return false unless super
28
+
29
+ File.open(File.join(overlay_dir, 'local_settings.py'), 'w') do |f|
30
+ f.write <<-EOT
31
+ import os
32
+
33
+ DATABASE_ENGINE = 'postgresql_psycopg2'
34
+ DATABASE_NAME = os.getenv('DATABASE_NAME')
35
+ DATABASE_USER = os.getenv('DATABASE_USER')
36
+ DATABASE_PASSWORD = os.getenv('DATABASE_PASSWORD')
37
+ DATABASE_HOST = os.getenv('DATABASE_HOST')
38
+ EOT
39
+ end
40
+ true
41
+ end
42
+
43
+ def dev_run_script_content
44
+ shell_run_script do
45
+ <<-EOT
46
+ cd #{@dir}
47
+ exec vendor/bin/python #{@manage_script} runserver
48
+ EOT
49
+ end
50
+ end
51
+
52
+ def deploy_run_script_content
53
+ shell_run_script do
54
+ <<-EOT
55
+ exec vendor/bin/python #{@manage_script} runserver --noreload 0.0.0.0:$LISTEN_PORT
56
+ EOT
57
+ end
58
+ end
59
+
60
+ # Describes the requirements of the deployed application. Django applications automatically
61
+ # require a database with accessible credentials.
62
+ def requirements
63
+ res = super
64
+
65
+ db_name = @props['database_name'] || @name
66
+ res['resources'] ||= []
67
+ res['resources'] << {
68
+ 'type' => 'Postgres',
69
+ 'name' => db_name,
70
+ 'user' => @props['database_user'] || db_name,
71
+ 'password' => @props['database_password'] || db_name
72
+ }
73
+
74
+ # TODO: The clown should be able to automatically allocate listening ports
75
+ res['system-properties'] ||= {}
76
+ res['system-properties']['LISTEN_PORT'] = 3000
77
+
78
+ # TODO: The clown should be able to automatically respond with DB details
79
+ res['system-properties']['DATABASE_NAME'] = db_name
80
+ res['system-properties']['DATABASE_USER'] = db_name
81
+ res['system-properties']['DATABASE_PASSWORD'] = @props['database_password'] || db_name
82
+ res['system-properties']['DATABASE_HOST'] = 'localhost'
83
+
84
+ res
85
+ end
86
+ end
87
+
88
+ PROFILES << Django
89
+ end
90
+ end
@@ -0,0 +1,90 @@
1
+ require File.expand_path('../base', __FILE__)
2
+
3
+ module Circus
4
+ module Profiles
5
+ class Jekyll < Base
6
+ # Checks if this is a Jekyll site based on whether there is a file named
7
+ # _config.yml on the root directory
8
+ def self.accepts?(name, dir, props)
9
+ return File.exists?(File.join(dir, "_config.yml"))
10
+ end
11
+
12
+ def initialize(name, dir, props)
13
+ super(name, dir, props)
14
+ end
15
+
16
+ # The name of this profile
17
+ def name
18
+ "jekyll"
19
+ end
20
+
21
+ def package_base_dir?
22
+ false
23
+ end
24
+
25
+ def extra_dirs
26
+ ["#{@dir}/_site"]
27
+ end
28
+
29
+ def prepare_for_deploy(logger, overlay_dir)
30
+ run_external(logger, 'Generate site with Jekyll', "cd #{@dir}; jekyll")
31
+
32
+ # Create lighttpd.conf
33
+ File.open(File.join(overlay_dir, 'lighttpd.conf'), 'w') do |f|
34
+ f.write <<-EOT
35
+ server.document-root = "_site/"
36
+
37
+ server.port = env.HTTPD_PORT
38
+
39
+ mimetype.assign = (
40
+ ".html" => "text/html",
41
+ ".txt" => "text/plain",
42
+ ".css" => "text/css",
43
+ ".jpg" => "image/jpeg",
44
+ ".png" => "image/png"
45
+ )
46
+
47
+ static-file.exclude-extensions = ( ".yaml" )
48
+ index-file.names = ( "index.html" )
49
+ EOT
50
+ end
51
+ true
52
+ end
53
+
54
+ def cleanup_after_deploy(logger, overlay_dir)
55
+ FileUtils.rm_rf(File.join(@dir, '_site'))
56
+ end
57
+
58
+ def dev_run_script_content
59
+ shell_run_script do
60
+ <<-EOT
61
+ cd #{@dir}
62
+ exec jekyll --auto --server
63
+ EOT
64
+ end
65
+ end
66
+
67
+ def deploy_run_script_content
68
+ shell_run_script do
69
+ <<-EOT
70
+ exec lighttpd -D -f lighttpd.conf
71
+ EOT
72
+ end
73
+ end
74
+
75
+ # Describes the resources required by the deployed application. Jekyll sites automatically
76
+ # require a port to serve content on.
77
+ def requirements
78
+ res = super
79
+
80
+ # TODO: The clown should be able to automatically allocate listening ports
81
+ res['system-properties'] ||= {}
82
+ res['system-properties']['HTTPD_PORT'] = 3000
83
+
84
+ res
85
+ end
86
+ end
87
+
88
+ PROFILES << Jekyll
89
+ end
90
+ end
@@ -0,0 +1,17 @@
1
+ require File.expand_path('../base', __FILE__)
2
+
3
+ module Circus
4
+ module Profiles
5
+ class MakeBase < Base
6
+ # Development preparation is the same as deployment
7
+ def prepare_for_dev(logger, run_dir)
8
+ prepare_for_deploy(logger, run_dir)
9
+ end
10
+
11
+ def prepare_for_deploy(logger, overlay_dir)
12
+ # Build the application
13
+ run_external(logger, 'Compile application', "cd #{@dir}; make")
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,46 @@
1
+ require File.expand_path('../python_base', __FILE__)
2
+
3
+ module Circus
4
+ module Profiles
5
+ class PurePy < PythonBase
6
+ PUREPY_APP_PROPERTY='purepy-app'
7
+
8
+ # Checks if this is a pure python application. Will accept the application if it
9
+ # has a file named <name>.py, or has a 'purepy-app' property describing the entry point.
10
+ def self.accepts?(name, dir, props)
11
+ return true if props.include? PUREPY_APP_PROPERTY
12
+ return File.exists?(File.join(dir, "#{name}.py"))
13
+ end
14
+
15
+ def initialize(name, dir, props)
16
+ super(name, dir, props)
17
+
18
+ @py_script = props[PUREPY_APP_PROPERTY] || "#{name}.py"
19
+ end
20
+
21
+ # The name of this profile
22
+ def name
23
+ "pure-py"
24
+ end
25
+
26
+ def dev_run_script_content
27
+ shell_run_script do
28
+ <<-EOT
29
+ cd #{@dir}
30
+ exec vendor/bin/python #{@py_script}
31
+ EOT
32
+ end
33
+ end
34
+
35
+ def deploy_run_script_content
36
+ shell_run_script do
37
+ <<-EOT
38
+ exec vendor/bin/python #{@py_script}
39
+ EOT
40
+ end
41
+ end
42
+ end
43
+
44
+ PROFILES << PurePy
45
+ end
46
+ end
@@ -0,0 +1,48 @@
1
+ require File.expand_path('../ruby_base', __FILE__)
2
+
3
+ module Circus
4
+ module Profiles
5
+ class PureRb < RubyBase
6
+ PURERB_APP_PROPERTY='purerb-app'
7
+
8
+ # Checks if this is a pure ruby application. Will accept the application if it
9
+ # has a file named <name>.rb, or has a 'purerb-app' property describing the entry point.
10
+ def self.accepts?(name, dir, props)
11
+ return true if props.include? PURERB_APP_PROPERTY
12
+ return File.exists?(File.join(dir, "#{name}.rb"))
13
+ end
14
+
15
+ def initialize(name, dir, props)
16
+ super(name, dir, props)
17
+
18
+ @rb_script = props[PURERB_APP_PROPERTY] || "#{name}.rb"
19
+ end
20
+
21
+ # The name of this profile
22
+ def name
23
+ "pure-rb"
24
+ end
25
+
26
+ # Just run the script in development
27
+ def dev_run_script_content
28
+ shell_run_script do
29
+ <<-EOT
30
+ cd #{@dir}
31
+ exec ruby #{@rb_script}
32
+ EOT
33
+ end
34
+ end
35
+
36
+ # Install our gems and then run in deployment
37
+ def deploy_run_script_content
38
+ shell_run_script do
39
+ <<-EOT
40
+ exec ruby #{@rb_script}
41
+ EOT
42
+ end
43
+ end
44
+ end
45
+
46
+ PROFILES << PureRb
47
+ end
48
+ end
@@ -0,0 +1,39 @@
1
+ require File.expand_path('../base', __FILE__)
2
+
3
+ module Circus
4
+ module Profiles
5
+ class PythonBase < Base
6
+ # Development preparation is the same as deployment
7
+ def prepare_for_dev(logger, run_dir)
8
+ prepare_for_deploy(logger, run_dir)
9
+ end
10
+
11
+ def prepare_for_deploy(logger, overlay_dir)
12
+ # Build the virtualenv
13
+ if has_depsfile?
14
+ unless File.exists? "#{@dir}/vendor"
15
+ return false unless run_external(logger, "Create virtualenv", "cd #{@dir}; virtualenv --no-site-packages vendor")
16
+ end
17
+
18
+ File.read(depsfile_fn).lines.each do |dep|
19
+ return false unless run_external(logger, "Install dep #{dep}",
20
+ "cd #{@dir}; vendor/bin/easy_install -q \"#{dep.strip}\"")
21
+ end
22
+
23
+ return false unless run_external(logger, "Make virtualenv relocatable", "cd #{@dir}; virtualenv --relocatable vendor")
24
+ end
25
+
26
+ true
27
+ end
28
+
29
+ protected
30
+ def depsfile_fn
31
+ "#{@dir}/Pydeps"
32
+ end
33
+
34
+ def has_depsfile?
35
+ File.exists? depsfile_fn
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,59 @@
1
+ require File.expand_path('../ruby_base', __FILE__)
2
+
3
+ module Circus
4
+ module Profiles
5
+ class Rack < RubyBase
6
+ RACKFILE_NAME='ruby-rackfile'
7
+
8
+ # Checks if this is a rack applcation. Will accept the application if it has a config.ru, or if the
9
+ # properties describe the location of an alternative rack entry point.
10
+ def self.accepts?(name, dir, props)
11
+ return true if props.include? RACKFILE_NAME
12
+ return File.exists?(File.join(dir, 'config.ru'))
13
+ end
14
+
15
+ def initialize(name, dir, props)
16
+ super(name, dir, props)
17
+
18
+ @rackup_name = props[RACKFILE_NAME] || 'config.ru'
19
+ end
20
+
21
+ # The name of this profile
22
+ def name
23
+ "rack"
24
+ end
25
+
26
+ def dev_run_script_content
27
+ shell_run_script do
28
+ <<-EOT
29
+ cd #{@dir}
30
+ exec bundle exec thin -R #{@rackup_name} -p #{listen_port} start
31
+ EOT
32
+ end
33
+ end
34
+
35
+ def deploy_run_script_content
36
+ shell_run_script do
37
+ <<-EOT
38
+ exec bundle exec vendor/bin/thin -R #{@rackup_name} -p #{listen_port} start
39
+ EOT
40
+ end
41
+ end
42
+
43
+ def extra_dirs
44
+ if has_gemfile?
45
+ ["#{@dir}/.bundle"]
46
+ else
47
+ []
48
+ end
49
+ end
50
+
51
+ private
52
+ def listen_port
53
+ @props['web-app-port'] || 3000
54
+ end
55
+ end
56
+
57
+ PROFILES << Rack
58
+ end
59
+ end
@@ -0,0 +1,52 @@
1
+ require File.expand_path('../base', __FILE__)
2
+ require 'fileutils'
3
+ require 'bundler/circus_util'
4
+
5
+ module Circus
6
+ module Profiles
7
+ class RubyBase < Base
8
+ BUNDLER_TOOL=File.expand_path('../../../bundler/circus_bundler.rb', __FILE__)
9
+
10
+ def initialize(name, dir, props)
11
+ super(name, dir, props)
12
+ end
13
+
14
+ # No dev preparation required. Don't override dev_run_script_content, since it is the
15
+ # same as the deployment variant.
16
+ def prepare_for_dev(logger, run_dir); true; end
17
+
18
+ def prepare_for_deploy(logger, overlay_dir)
19
+ # Run the gem bundler if necessary
20
+ if has_gemfile?
21
+ logger.info("Bundling gems")
22
+ run_external(logger, 'gem bundling', "cd #{@dir}; ruby #{BUNDLER_TOOL}")
23
+ end
24
+
25
+ true
26
+ end
27
+
28
+ def cleanup_after_deploy(logger, overlay_dir)
29
+ Bundler::CircusUtil.unfix_external_paths(@dir)
30
+ end
31
+
32
+ def extra_dirs
33
+ if has_gemfile?
34
+ ["#{@dir}/.bundle"]
35
+ else
36
+ []
37
+ end
38
+ end
39
+
40
+ protected
41
+ def has_gemfile?
42
+ File.exists? "#{@dir}/Gemfile"
43
+ end
44
+
45
+ # class LoggingShell
46
+ # def say(msg)
47
+ # puts msg
48
+ # end
49
+ # end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,46 @@
1
+ require File.expand_path('../make_base', __FILE__)
2
+
3
+ module Circus
4
+ module Profiles
5
+ class Shell < MakeBase
6
+ SHELL_APP_PROPERTY='shell-app'
7
+
8
+ # Checks if this is a shell applcation. Will accept the application if it
9
+ # has a file named <name>.sh, or has a 'shell-app' property describing the entry point.
10
+ def self.accepts?(name, dir, props)
11
+ return true if props.include? SHELL_APP_PROPERTY
12
+ return File.exists?(File.join(dir, "#{name}.sh"))
13
+ end
14
+
15
+ def initialize(name, dir, props)
16
+ super(name, dir, props)
17
+
18
+ @sh_script = props[SHELL_APP_PROPERTY] || "#{name}.sh"
19
+ end
20
+
21
+ # The name of this profile
22
+ def name
23
+ "shell"
24
+ end
25
+
26
+ def dev_run_script_content
27
+ shell_run_script do
28
+ <<-EOT
29
+ cd #{@dir}
30
+ exec sh #{@sh_script}
31
+ EOT
32
+ end
33
+ end
34
+
35
+ def deploy_run_script_content
36
+ shell_run_script do
37
+ <<-EOT
38
+ exec sh #{@sh_script}
39
+ EOT
40
+ end
41
+ end
42
+ end
43
+
44
+ PROFILES << Shell
45
+ end
46
+ end
@@ -0,0 +1,10 @@
1
+ require File.expand_path('../profiles/base', __FILE__)
2
+ require File.expand_path('../profiles/ruby_base', __FILE__)
3
+ require File.expand_path('../profiles/rack', __FILE__)
4
+ require File.expand_path('../profiles/pure_rb', __FILE__)
5
+ require File.expand_path('../profiles/python_base', __FILE__)
6
+ require File.expand_path('../profiles/pure_py', __FILE__)
7
+ require File.expand_path('../profiles/make_base', __FILE__)
8
+ require File.expand_path('../profiles/shell', __FILE__)
9
+ require File.expand_path('../profiles/django', __FILE__)
10
+ require File.expand_path('../profiles/jekyll', __FILE__)
@@ -0,0 +1,42 @@
1
+ module Circus
2
+ module Repos
3
+ class Git
4
+ # Checks if the current directory (or a parent) are Git working trees. Uses
5
+ # a call to git remote to test (which will fail with a non-zero exit if the
6
+ # tree isn't a valid git tree)
7
+ def self.accepts_dir? dir_name
8
+ `git remote >/dev/null 2>/dev/null`
9
+ $? == 0
10
+ end
11
+
12
+ def self.accepts_id?(key)
13
+ key == 'git'
14
+ end
15
+
16
+ def self.type_id
17
+ 'git'
18
+ end
19
+
20
+ def initialize(dir)
21
+ @dir = dir
22
+ end
23
+
24
+ def repo_url
25
+ first_remote = `(cd #{@dir}; git remote -v) | grep fetch`.lines.first
26
+ return nil unless first_remote
27
+
28
+ first_remote.split(' ', 2)[1].gsub('(fetch)', '').strip
29
+ end
30
+
31
+ def current_revision
32
+ `(cd #{@dir}; git rev-parse HEAD)`.strip
33
+ end
34
+
35
+ def write_patch(patch_fn)
36
+ `(cd #{@dir}; git diff HEAD >#{patch_fn})`.strip
37
+ end
38
+ end
39
+
40
+ REPOS << Git
41
+ end
42
+ end
@@ -0,0 +1,42 @@
1
+ module Circus
2
+ module Repos
3
+ class Mercurial
4
+ # Checks if the current directory (or a parent) are Hg working trees. Uses
5
+ # a call to hg status to test (which will fail with a non-zero exit if the
6
+ # tree isn't a valid git tree)
7
+ def self.accepts_dir? dir_name
8
+ `hg st >/dev/null 2>/dev/null`
9
+ $? == 0
10
+ end
11
+
12
+ def self.accepts_id?(key)
13
+ key == 'hg' || key == 'mercurial'
14
+ end
15
+
16
+ def self.type_id
17
+ 'hg'
18
+ end
19
+
20
+ def initialize(dir)
21
+ @dir = dir
22
+ end
23
+
24
+ def repo_url
25
+ first_path = `(cd #{@dir}; hg paths)`.lines.first
26
+ return nil unless first_path
27
+
28
+ first_path.split('=', 2)[1].strip
29
+ end
30
+
31
+ def current_revision
32
+ `(cd #{@dir}; hg id -i)`[0..11]
33
+ end
34
+
35
+ def write_patch(patch_fn)
36
+ `(cd #{@dir}; hg diff >#{patch_fn})`.strip
37
+ end
38
+ end
39
+
40
+ REPOS << Mercurial
41
+ end
42
+ end