capistrano-conditional 0.0.4 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b993e23a21fae3f4070e2e14427b7bb2699edd2a
4
- data.tar.gz: d429a2ef57a187e3168998f550acf760782be43e
3
+ metadata.gz: 64ab0159258e31d984ab66b427d33caf82dfaa23
4
+ data.tar.gz: 9b5fbe11ff09c04be713d8fba77b3a28c921a5bb
5
5
  SHA512:
6
- metadata.gz: a199f14d69b1e6292d79fa3e0379b46e1f57cc35c5da6ff7ccd6bdb4fc9a73aacc3ea7a16d496e0da1637c70efbb78fa97bcffd459622fbaef4b591f792dc051
7
- data.tar.gz: d44ab7a4b1eba8f5a1c1ca86b68c2b064616dd37f228ed53e9b0a87d7e44d0d4dac4f55f9491105fc0f1e2a125864683e665de80684c5c80a09aff09f519f9e2
6
+ metadata.gz: 0f36f346973da57b1d9a0abaedc40a81d6ec131e93890b6c5aa07ed0fe9e2d8ecc38ec76e7b604d126a123511630e642ea8c18306508df472067924625d81bda
7
+ data.tar.gz: 070d4a2781d1e1b1a85294f56339d44c1574c23afd3071b236963fe45187a096b33acada75e183f51031445cd18afc4c86d8640793bf4211944c418d0c350cc9
data/README.md CHANGED
@@ -1,9 +1,13 @@
1
1
  # capistrano-conditional
2
2
 
3
- This gem extends capistrano deployments to allow certain tasks to only be run under certain conditions -- i.e. conditionally.
3
+ This gem extends capistrano v2 deployments to allow certain tasks to only be run under certain conditions -- i.e. conditionally.
4
4
 
5
5
  It hasn't yet been extended to work with Capistrano 3; pull requests welcomed!
6
6
 
7
+ ## BREAKING UPDATES
8
+
9
+ * v. 0.1.0 pulls the branch to be deployed from capistrano multistage, rather than assuming it's whatever you currently have checked out in your working directory (among other things, this allows tweaking the deploy recipe multiple times without having to commit those changes).
10
+
7
11
  ## Installation
8
12
 
9
13
  Add to your Gemfile:
@@ -22,7 +26,7 @@ Your application must already be using capistrano for deployments, and (for now
22
26
 
23
27
  ## Usage Instructions
24
28
 
25
- <code>capistrano-conditional</code> adds logic to be run before <code>cap deploy</code> or <code>cap deploy:migrations</code> that compares the local (to be deployed) code with the existing remote (currently deployed) code and lists all files that will be updated by the current deploy. It then checks the list of conditional statements that you've provided and runs any that you want run -- e.g. if you're using [whenever](https://github.com/javan/whenever) and you only want to run the <code>deploy:update_crontab</code> task if <code>config/schedule.rb</code> has been changed, you'd add a block like this to your deploy.rb:
29
+ <code>capistrano-conditional</code> adds logic to be run before <code>cap deploy</code> or <code>cap deploy:migrations</code> that compares the to-be-deployed code with the existing remote (currently deployed) code and lists all files that will be updated by the current deploy. It then checks the list of conditional statements that you've provided and runs any that you want run -- e.g. if you're using [whenever](https://github.com/javan/whenever) and you only want to run the <code>deploy:update_crontab</code> task if <code>config/schedule.rb</code> has been changed, you'd add a block like this to your deploy.rb:
26
30
 
27
31
  ConditionalDeploy.register :whenever, :watchlist => 'config/schedule.rb' do
28
32
  after "deploy:symlink", "deploy:update_crontab"
@@ -30,6 +34,10 @@ Your application must already be using capistrano for deployments, and (for now
30
34
 
31
35
  This example registers a conditional named "whenever" (names aren't programmatically important, but they're used to report what's going to be run at the beginning of each deploy). The contents of the block will be run only if the list of changed files includes a path that matches <code>config/schedule.rb</code>.
32
36
 
37
+ ### Setting branches
38
+
39
+ By default, capistrano-conditional pics up the branch-to-be-deployed from the `:branch` setting used by capistrano multistage, or defaults to `HEAD`. To specify a different branch manually: `set :git_deploying, 'some/other/branch/name'`.
40
+
33
41
  ### Available Conditions
34
42
 
35
43
  There are currently four logic conditions available (well, five, but <code>:watchlist</code> is just an alias for <code>:any_match</code>):
@@ -38,7 +46,7 @@ There are currently four logic conditions available (well, five, but <code>:watc
38
46
  * <code>:none_match</code> => file_list
39
47
  * <code>:if</code> => Proc
40
48
  * <code>:unless</code> => Proc
41
-
49
+
42
50
  Where file_list is either a string or an array of strings which will be <em>matched</em> against the list of changed filenames from git (so <code>:any_match => ['db/migrate']</code> would be true if ANY migration file was added, modified, or deleted).
43
51
 
44
52
  <code>:any_match</code> (aliased as <code>:watchlist</code>) executes the block if ANY of the provided strings match ANY of file paths git reports changed.
@@ -66,17 +74,17 @@ Only run the rake task to update the crontab if the schedule has changed:
66
74
  Only restart the sphinx daemon if our database or schema has changed. Otherwise, just copy the generated sphinx config from the previous release:
67
75
 
68
76
  SPHINX_WATCHLIST = ['db/schema.rb', 'db/migrate', 'sphinx.yml', 'app/indices']
69
-
77
+
70
78
  ConditionalDeploy.register :sphinx, :watchlist => SPHINX_WATCHLIST do
71
79
  before "deploy:update_code", "thinking_sphinx:stop"
72
80
  before "deploy:start", "thinking_sphinx:start"
73
81
  before "deploy:restart", "thinking_sphinx:start"
74
82
  end
75
-
83
+
76
84
  ConditionalDeploy.register :no_sphinx, :none_match => SPHINX_WATCHLIST do
77
85
  after "deploy:update_code", "sphinx:copy_config"
78
86
  end
79
-
87
+
80
88
  namespace :sphinx do
81
89
  desc 'Copy the config file from previous release, if available, or else rerun configuration'
82
90
  task :copy_config, :roles => :app do
@@ -97,7 +105,7 @@ For pre-asset-pipeline versions of Rails, this snippet will reprocess your asset
97
105
  #### Migrations
98
106
 
99
107
  I've got <code>cap deploy</code> in muscle memory, and I used to find myself forgetting to run <code>cap deploy:migrations</code> until after I tested the new changes and found staging wasn't working right. I now add the following code to my apps, so I never have to worry about it again:
100
-
108
+
101
109
  if ARGV.any?{|v| v['deploy:migrations']} # If running deploy:migrations
102
110
  # If there weren't any changes to migrations or the schema file, then abort the deploy
103
111
  ConditionalDeploy.register :unneeded_migrations, :none_match => ['db/schema.rb', 'db/migrate'] do
@@ -107,19 +115,15 @@ I've got <code>cap deploy</code> in muscle memory, and I used to find myself for
107
115
  # If there were changes to migration files, run migrations as part of the deployment
108
116
  ConditionalDeploy.register :forgotten_migrations, :any_match => ['db/schema.rb', 'db/migrate'], :msg => "Forgot to run migrations? It's cool, we'll do it for you." do
109
117
  after "deploy:update_code", "deploy:migrate"
110
- end
118
+ end
111
119
  end
112
120
 
113
- Since I use it on every project, I've wrapped that logic up in a single command:
121
+ Since I use it on every project, I've wrapped that logic up into this gem. To enable, just add `set :monitor_migrations, true`.
114
122
 
115
- ConditionalDeploy.monitor_migrations(self)
116
-
117
123
  ## Advanced Usage
118
124
 
119
- By default <code>capistrano-conditional</code> will abort the deployment if you have uncommited changes in your working directory. You can skip this check on an individual run by setting the ALLOW_UNCOMMITED environment variable (e.g. <code>cap deploy ALLOW_UNCOMMITTED=1</code>).
120
-
121
- If you need to force a particular conditional to run, you can also do that via the environment. Given the examples above, if you want to run the conditional named <code>whenever</code> even though config/schedule.rb hasn't been changed, just run <code>cap deploy RUN_WHENEVER=1</code>. Similarly, if you needed to skip the <code>whenever</code> conditional which would otherwise be run, you can use <code>cap deploy SKIP_WHENEVER=1</code>.
125
+ If you need to force a particular conditional to run, you can do so via the environment. Given the examples above, if you want to run the conditional named <code>whenever</code> even though config/schedule.rb hasn't been changed, just run <code>cap deploy RUN_WHENEVER=1</code>. Similarly, if you needed to skip the <code>whenever</code> conditional which would otherwise be run, you can use <code>cap deploy SKIP_WHENEVER=1</code>.
122
126
 
123
127
  ## License
124
128
 
125
- Copyright &copy; 2013 [Deviantech, Inc.](http://www.deviantech.com) and released under the MIT license.
129
+ Copyright &copy; 2014 [Deviantech, Inc.](http://www.deviantech.com) and released under the MIT license.
@@ -12,6 +12,10 @@ class ConditionalDeploy
12
12
  @@conditionals << Capistrano::Conditional::Unit.new(name, opts, block)
13
13
  end
14
14
 
15
+ def self.configure
16
+ yield self
17
+ end
18
+
15
19
  def self.monitor_migrations(context)
16
20
  if ARGV.any?{|v| v['deploy:migrations']} # If running deploy:migrations
17
21
  # If there weren't any changes to migrations or the schema file, then abort the deploy
@@ -22,80 +26,109 @@ class ConditionalDeploy
22
26
  # If there were changes to migration files, run migrations as part of the deployment
23
27
  ConditionalDeploy.register :forgotten_migrations, :any_match => ['db/schema.rb', 'db/migrate'], :msg => "Forgot to run migrations? It's cool, we'll do it for you." do
24
28
  context.after "deploy:update_code", "deploy:migrate"
25
- end
26
- end
27
- end
28
-
29
- def self.apply_conditions!(deployed)
30
- conditional = self.new(deployed)
31
- conditional.ensure_local_up_to_date
32
- conditional.screen_conditionals
33
- conditional.report_plan
34
- conditional.run_conditionals
29
+ end
30
+ end
35
31
  end
36
32
 
37
-
38
-
39
- def initialize(compare_to = 'HEAD^')
33
+ def initialize(current, deploying)
40
34
  @logger = Capistrano::Logger.new(:output => STDOUT)
41
35
  @logger.level = Capistrano::Logger::MAX_LEVEL
42
-
36
+
43
37
  @verbose = true
44
- @git = Git.open('.')
45
- @last_deployed = @git.object(compare_to)
46
- @diff = @git.diff('HEAD', compare_to)
47
- @changed = @diff.stats[:files].keys.sort
48
- @to_run = []
38
+ @git = Git.open('.')
39
+ @working = get_object 'HEAD'
40
+ @current = get_object current, 'currently deployed'
41
+ @deploying = get_object deploying, 'about to be deployed'
42
+
43
+ @diff = @git.diff(current, deploying)
44
+ @changed = @diff.stats[:files].keys.compact.sort
45
+ @to_run = []
46
+ end
47
+
48
+ def apply_conditions!
49
+ screen_conditionals
50
+ report_plan
51
+ run_conditionals
49
52
  end
50
53
 
51
- def ensure_local_up_to_date
52
- return true if ENV['ALLOW_UNCOMMITTED']
53
- s = @git.status
54
- no_changes = %w(changed added deleted).all? { |attrib| s.send(attrib).empty? }
54
+ protected
55
55
 
56
- unless no_changes
57
- abort "\nYour working copy contains local changes not yet committed to git. \nPlease commit all changes before deploying.\n\n"
56
+ def get_object(name, desc=nil)
57
+ @git.object(name)
58
+ rescue Git::GitExecuteError => e
59
+ msg = desc ? "(#{desc}) #{name}" : name
60
+ abort "Unable to find git object for #{msg}. Is your local repository up to date?\n\n"
61
+ end
62
+
63
+ def report_plan
64
+ @plan = []
65
+ set_report_header
66
+ set_report_files
67
+ set_report_runlist
68
+ log_plan @plan
58
69
  end
59
- end
60
70
 
61
- def report_plan
62
- def log(text = "\n", level = Capistrano::Logger::TRACE)
63
- @logger.log(level, text, "Conditional")
71
+ def screen_conditionals
72
+ @@conditionals.each do |job|
73
+ force = job.name && ENV["RUN_#{job.name.to_s.upcase}"]
74
+ skip = job.name && ENV["SKIP_#{job.name.to_s.upcase}"]
75
+ next unless force || job.applies?(@changed)
76
+ next if skip
77
+ @to_run << job
78
+ end
64
79
  end
65
-
66
- log
67
- log "Conditional Deployment Report:"
68
- log
69
- log "\tLast deployed commit: #{@last_deployed.message}"
70
- log
71
- log "\tFiles Modified:"
72
- @changed.each {|f| log "\t\t- #{f}"}
73
- log
74
- log "\tConditional Runlist:"
75
- if @to_run.empty?
76
- log "\t\t* No conditional tasks have been added"
77
- else
80
+
81
+ def run_conditionals
78
82
  @to_run.each do |job|
79
- out = job.message ? "#{job.name} (#{job.message})" : job.name
80
- log "\t\t* Running #{out}"
83
+ job.block.call
81
84
  end
82
85
  end
83
- log
84
- end
85
86
 
86
- def screen_conditionals
87
- @@conditionals.each do |job|
88
- force = job.name && ENV["RUN_#{job.name.to_s.upcase}"]
89
- skip = job.name && ENV["SKIP_#{job.name.to_s.upcase}"]
90
- next unless force || job.applies?(@changed)
91
- next if skip
92
- @to_run << job
87
+ def set_report_header
88
+ @plan << ''
89
+ @plan << 'Conditional Deployment Report:'
90
+ @plan << ''
91
+ @plan << "\tCurrently deployed: #{commit_details @current}"
92
+ @git.log.between(@current, @deploying).each{|l| @plan << "\t\t* #{commit_details l}"}
93
+ @plan << "\tPreparing to deploy: #{commit_details @deploying}"
94
+ @plan << ''
93
95
  end
94
- end
95
-
96
- def run_conditionals
97
- @to_run.each do |job|
98
- job.block.call
96
+
97
+ def set_report_files
98
+ if @changed.length == 0
99
+ @plan << "\tNo files were modified."
100
+ else
101
+ @plan << "\tFiles Modified:"
102
+ @changed.each do |file|
103
+ @plan << "\t\t- #{file}"
104
+ end
105
+ end
106
+ @plan << ''
99
107
  end
100
- end
108
+
109
+ def set_report_runlist
110
+ @plan << "\tConditional Runlist:"
111
+ @plan << ''
112
+ if @to_run.empty?
113
+ @plan << "\t\t* No conditional tasks have been added"
114
+ else
115
+ @to_run.each do |job|
116
+ out = job.message ? "#{job.name} (#{job.message})" : job.name
117
+ @plan << "\t\t* Running #{out}"
118
+ end
119
+ end
120
+ @plan << ''
121
+ end
122
+
123
+ def commit_details(c)
124
+ # extra = "(#{c.author.name} at #{c.date.strftime("%H:%M %Z on %B %e")})"
125
+ "#{c.sha} #{c.message.split("\n").first}"
126
+ end
127
+
128
+ def log_plan(lines = "\n", level = Capistrano::Logger::TRACE)
129
+ Array(lines).each do |line|
130
+ @logger.log(level, ': ' + line, "Conditional")
131
+ end
132
+ end
133
+
101
134
  end
@@ -2,33 +2,27 @@ Capistrano::Configuration.instance(:must_exist).load do
2
2
  log_formatter([
3
3
  { :match => /^Conditional$/, :color => :cyan, :style => :dim, :priority => 10 }
4
4
  ])
5
-
6
-
5
+
7
6
  abort "\ncapistrano-conditional is not compatible with Capistrano 1.x\n" unless respond_to?(:namespace)
8
7
  abort "\nGit is not defined (are you in a git repository, with the Git gem installed?)\n" unless defined?(Git)
9
8
 
9
+ # By default, assume using multi-stage deployment setting :branch variable, and that the local branch is up to date
10
+ # (although don't require being on that branch to deploy).
11
+ set :git_deploying, -> { fetch(:branch).blank? ? 'HEAD' : "origin/#{fetch(:branch)}"}
12
+ set :git_currently_deployed, -> { capture("cat #{current_path}/REVISION").strip }
13
+ set :monitor_migrations, -> { false }
14
+
10
15
  namespace :conditional do
11
16
  desc "Initializes the conditional deployment functionality"
12
17
  task :apply do
13
- deployed_hash = capture("cat #{current_path}/REVISION").strip
14
- ConditionalDeploy.apply_conditions!( deployed_hash )
15
- end
16
-
17
- desc "Tests to be sure that the newest local and remote git commits match"
18
- task :ensure_latest_git do
19
- remote = capture("cd #{shared_path}/cached-copy && git log --format=oneline -n 1", :pty => false)
20
- local = run_locally("git log --format=oneline -n 1")
21
-
22
- unless local == remote
23
- abort("\nLocal and remote git repositories have different HEADs:\n Local: #{local} Remote: #{remote}\n Make sure you've committed your latest changes, or else pull down the remote updates and try again\n")
24
- end
18
+ ConditionalDeploy.monitor_migrations(self) if monitor_migrations
19
+
20
+ @deploy = ConditionalDeploy.new(git_currently_deployed, git_deploying)
21
+ @deploy.apply_conditions!
25
22
  end
26
23
  end
27
24
 
28
25
  # Ensure deploys apply conditional elements before running the rest of the tasks
29
26
  before 'deploy', 'conditional:apply'
30
27
  before 'deploy:migrations', 'conditional:apply'
31
-
32
- # Abort deployment if mismatch between local and remote git repositories
33
- after 'deploy:update_code', 'conditional:ensure_latest_git'
34
28
  end
@@ -59,7 +59,7 @@ module Capistrano
59
59
  case c.arity
60
60
  when 0 then c.call
61
61
  when 1 then c.call(@changed)
62
- else 2
62
+ else
63
63
  c.call(@changed, @git)
64
64
  end
65
65
  end
@@ -1,5 +1,5 @@
1
1
  module Capistrano
2
2
  module Conditional
3
- VERSION = "0.0.4"
3
+ VERSION = "0.1.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,41 +1,41 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capistrano-conditional
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kali Donovan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-21 00:00:00.000000000 Z
11
+ date: 2014-06-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: git
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: capistrano
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '2.5'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '2.5'
41
41
  description: Allows making tasks for git-based projects conditional based on the specific
@@ -46,7 +46,7 @@ executables: []
46
46
  extensions: []
47
47
  extra_rdoc_files: []
48
48
  files:
49
- - .gitignore
49
+ - ".gitignore"
50
50
  - CHANGELOG.md
51
51
  - Gemfile
52
52
  - README.md
@@ -66,17 +66,17 @@ require_paths:
66
66
  - lib
67
67
  required_ruby_version: !ruby/object:Gem::Requirement
68
68
  requirements:
69
- - - '>='
69
+ - - ">="
70
70
  - !ruby/object:Gem::Version
71
71
  version: '0'
72
72
  required_rubygems_version: !ruby/object:Gem::Requirement
73
73
  requirements:
74
- - - '>='
74
+ - - ">="
75
75
  - !ruby/object:Gem::Version
76
76
  version: '0'
77
77
  requirements: []
78
78
  rubyforge_project: capistrano-conditional
79
- rubygems_version: 2.1.11
79
+ rubygems_version: 2.3.0
80
80
  signing_key:
81
81
  specification_version: 4
82
82
  summary: Adds support for conditional deployment tasks in capistrano