capistrano 3.8.2 → 3.9.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: 7f88f4b773f72433e56b0f290b92e2565952295e
4
- data.tar.gz: ac9af7055287f89ff36d9a16dd735166a02cdf80
3
+ metadata.gz: a4ae57e87cafad9fe7cb1307d847f5f3bd9d7ccb
4
+ data.tar.gz: e6ea828e10e6863b07c9fcd685a334464a3a3890
5
5
  SHA512:
6
- metadata.gz: c4f12ab9a1d3c746d969c8c8ea738b9a63978b4e93d0654a9ca0e70d5956eeb7e93061cc258947d15ccb7790bab9554925814c1c3d93f182c7bead906d16791f
7
- data.tar.gz: 147305f082e0043d2ca4185f23088f90693d9ce31aab3816301e1f2060bc8006c1841f6f09176b6e43af0fdd1aacbd83912840b710862677a1270fb2d014a2ef
6
+ metadata.gz: 49fd63f868fdc87cefd58e047dc22c2b05cd95211a7a99080a010f627c3f32944539a16876ade7496257d4a8b71e18fc099a57ec126abf3f2efa7d2991d36c41
7
+ data.tar.gz: 35064cfd5c3da3a39e8ca044aa1eae03b8b0fbbea3c22a08fb08d5c2755b1fe18f7be8f2e7bccc431214d166f0d953e5c112d026b818a462105761528f3478cc
@@ -1,5 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
+ - 2.4.1
3
4
  - 2.3.1
4
5
  - 2.2
5
6
  - 2.1
@@ -16,10 +16,26 @@ gem "capistrano", :github => "capistrano/capistrano"
16
16
 
17
17
  ## master
18
18
 
19
- https://github.com/capistrano/capistrano/compare/v3.8.1...HEAD
19
+ https://github.com/capistrano/capistrano/compare/v3.9.0...HEAD
20
20
 
21
21
  * Your contribution here!
22
22
 
23
+ ## `3.9.0` (2017-07-28)
24
+
25
+ https://github.com/capistrano/capistrano/compare/v3.8.2...v3.9.0
26
+
27
+ ### Breaking changes:
28
+
29
+ * None
30
+
31
+ ### New features:
32
+
33
+ * [#1911](https://github.com/capistrano/capistrano/pull/1911): Add Capistrano::DSL#invoke! for repetetive tasks
34
+
35
+ ### Fixes:
36
+
37
+ * [#1899](https://github.com/capistrano/capistrano/pull/1899): Updated `deploy:cleanup` to continue rotating the releases and skip the invalid directory names instead of skipping the whole rotation of releases. The warning message has changed slightly due to the change of behavior.
38
+
23
39
  ## `3.8.2` (2017-06-16)
24
40
 
25
41
  https://github.com/capistrano/capistrano/compare/v3.8.1...v3.8.2
@@ -41,6 +41,8 @@ Also include in your report:
41
41
 
42
42
  If you are an experienced Ruby programmer, take a few minutes to get the Capistrano test suite running (see [DEVELOPMENT.md][]), and do what you can to get a test case written that fails. *This will be a huge help!*
43
43
 
44
+ If you think you may have discovered a security vulnerability in Capistrano, do not open a GitHub issue. Instead, please send a report to <security@capistranorb.com>.
45
+
44
46
  ## Requesting new features or improvements
45
47
 
46
48
  Capistrano continues to improve thanks to people like you! Feel free to open a GitHub issue for any or all of these ideas:
@@ -28,11 +28,10 @@ Capistrano is a Ruby project, so we expect you to have a functioning Ruby enviro
28
28
 
29
29
  Make sure to install:
30
30
 
31
- * [Bundler](https://bundler.io/) 1.10.5 (see note)
31
+ * [Bundler](https://bundler.io/)
32
32
  * [Vagrant](https://www.vagrantup.com/)
33
33
  * [VirtualBox](https://www.virtualbox.org/wiki/Downloads) (or another [Vagrant-supported](https://docs.vagrantup.com/v2/getting-started/providers.html) VM host)
34
34
 
35
- *Note: As of this writing (December 2015), Vagrant does not work with Bundler > 1.10.5. If you have multiple versions of Bundler installed, use the special underscore command-line argument to force a compatible version, like this: `bundle _1.10.5_ exec rake features`.*
36
35
 
37
36
  ### Running tests
38
37
 
@@ -45,7 +44,7 @@ $ bundle install
45
44
  # Run the RSpec suite
46
45
  $ bundle exec rake spec
47
46
 
48
- # Run the Cucumber suite (requires Bundler 1.10.5)
47
+ # Run the Cucumber suite
49
48
  $ bundle exec rake features
50
49
 
51
50
  # Run the Cucumber suite and leave the VM running (faster for subsequent runs)
data/README.md CHANGED
@@ -103,7 +103,7 @@ Add Capistrano to your project's Gemfile:
103
103
 
104
104
  ``` ruby
105
105
  group :development do
106
- gem "capistrano", "~> 3.8"
106
+ gem "capistrano", "~> 3.9"
107
107
  end
108
108
  ```
109
109
 
@@ -186,6 +186,8 @@ Related GitHub repositories:
186
186
 
187
187
  GitHub issues are for bug reports and feature requests. Please refer to the [CONTRIBUTING](CONTRIBUTING.md) document for guidelines on submitting GitHub issues.
188
188
 
189
+ If you think you may have discovered a security vulnerability in Capistrano, do not open a GitHub issue. Instead, please send a report to <security@capistranorb.com>.
190
+
189
191
  ## How to contribute
190
192
 
191
193
  Contributions to Capistrano, in the form of code, documentation or idea, are gladly accepted. Read the [DEVELOPMENT](DEVELOPMENT.md) document to learn how to hack on Capistrano's code, run the tests, and contribute your first pull request.
@@ -52,3 +52,21 @@ Feature: Deploy
52
52
  When I run cap "deploy:symlink:release"
53
53
  Then the current directory will be a symlink to the release
54
54
 
55
+ Scenario: Cleanup
56
+ Given config stage file has line "set :keep_releases, 3"
57
+ And 5 valid existing releases
58
+ And an invalid release named "new"
59
+ When I run cap "deploy:cleanup"
60
+ Then 3 valid releases are kept
61
+ And the invalid "new" release is ignored
62
+
63
+ Scenario: Rolling Back
64
+ Given I make 2 deployments
65
+ When I run cap "deploy:rollback"
66
+ Then the current symlink points to the previous release
67
+
68
+ Scenario: Rolling Back to a specific release
69
+ Given I make 3 deployments
70
+ When I rollback to a specific release
71
+ Then the current symlink points to that specific release
72
+
@@ -6,7 +6,9 @@ end
6
6
 
7
7
  Then(/^git wrapper permissions are 0700$/) do
8
8
  permissions_test = %Q([ $(stat -c "%a" #{TestApp.git_wrapper_path.shellescape}) == "700" ])
9
- expect(vagrant_cli_command("ssh -c #{permissions_test.shellescape}")).to be_success
9
+ _stdout, _stderr, status = vagrant_cli_command("ssh -c #{permissions_test.shellescape}")
10
+
11
+ expect(status).to be_success
10
12
  end
11
13
 
12
14
  Then(/^the shared path is created$/) do
@@ -17,6 +19,18 @@ Then(/^the releases path is created$/) do
17
19
  run_vagrant_command(test_dir_exists(TestApp.releases_path))
18
20
  end
19
21
 
22
+ Then(/^(\d+) valid releases are kept/) do |num|
23
+ test = %Q([ $(ls -g #{TestApp.releases_path} | grep -E '[0-9]{14}' | wc -l) == "#{num}" ])
24
+ _, _, status = vagrant_cli_command("ssh -c #{test.shellescape}")
25
+ expect(status).to be_success
26
+ end
27
+
28
+ Then(/^the invalid (.+) release is ignored$/) do |filename|
29
+ test = "ls -g #{TestApp.releases_path} | grep #{filename}"
30
+ _, _, status = vagrant_cli_command("ssh -c #{test.shellescape}")
31
+ expect(status).to be_success
32
+ end
33
+
20
34
  Then(/^directories in :linked_dirs are created in shared$/) do
21
35
  TestApp.linked_dirs.each do |dir|
22
36
  run_vagrant_command(test_dir_exists(TestApp.shared_path.join(dir)))
@@ -124,3 +138,15 @@ end
124
138
  Then(/doesn't contain "([^"]*)" in the output/) do |expected|
125
139
  expect(@output).not_to include(expected)
126
140
  end
141
+
142
+ Then(/the current symlink points to the previous release/) do
143
+ previous_release_path = @release_paths[-2]
144
+
145
+ run_vagrant_command(symlinked?(TestApp.current_path, previous_release_path))
146
+ end
147
+
148
+ Then(/^the current symlink points to that specific release$/) do
149
+ specific_release_path = TestApp.releases_path.join(@rollback_release)
150
+
151
+ run_vagrant_command(symlinked?(TestApp.current_path, specific_release_path))
152
+ end
@@ -13,3 +13,9 @@ end
13
13
  When(/^I run "(.*?)"$/) do |command|
14
14
  @success, @output = TestApp.run(command)
15
15
  end
16
+
17
+ When(/^I rollback to a specific release$/) do
18
+ @rollback_release = @release_paths.first.split("/").last
19
+
20
+ step %Q{I run cap "deploy:rollback ROLLBACK_RELEASE=#{@rollback_release}"}
21
+ end
@@ -21,10 +21,16 @@ end
21
21
 
22
22
  Given(/^file "(.*?)" exists in shared path$/) do |file|
23
23
  file_shared_path = TestApp.shared_path.join(file)
24
- run_vagrant_command("mkdir -p #{TestApp.shared_path}")
24
+ run_vagrant_command("mkdir -p #{file_shared_path.dirname}")
25
25
  run_vagrant_command("touch #{file_shared_path}")
26
26
  end
27
27
 
28
+ Given(/^all linked files exists in shared path$/) do
29
+ TestApp.linked_files.each do |linked_file|
30
+ step %Q{file "#{linked_file}" exists in shared path}
31
+ end
32
+ end
33
+
28
34
  Given(/^file "(.*?)" does not exist in shared path$/) do |file|
29
35
  file_shared_path = TestApp.shared_path.join(file)
30
36
  run_vagrant_command("mkdir -p #{TestApp.shared_path}")
@@ -60,3 +66,27 @@ end
60
66
  Given(/^a stage file named (.+)$/) do |filename|
61
67
  TestApp.write_local_stage_file(filename)
62
68
  end
69
+
70
+ Given(/^I make (\d+) deployments$/) do |count|
71
+ step "all linked files exists in shared path"
72
+
73
+ @release_paths = (1..count.to_i).map do
74
+ TestApp.cap("deploy")
75
+ stdout, _stderr = run_vagrant_command("readlink #{TestApp.current_path}")
76
+
77
+ stdout.strip
78
+ end
79
+ end
80
+
81
+ Given(/^(\d+) valid existing releases$/) do |num|
82
+ a_day = 86_400 # in seconds
83
+ offset = -(a_day * num.to_i)
84
+ num.to_i.times do
85
+ run_vagrant_command("mkdir -p #{TestApp.release_path(TestApp.timestamp(offset))}")
86
+ offset += a_day
87
+ end
88
+ end
89
+
90
+ Given(/^an invalid release named "(.+)"$/) do |filename|
91
+ run_vagrant_command("mkdir -p #{TestApp.release_path(filename)}")
92
+ end
@@ -15,6 +15,10 @@ module RemoteCommandHelpers
15
15
  %Q{[ -#{type} "#{path}" ]}
16
16
  end
17
17
 
18
+ def symlinked?(symlink_path, target_path)
19
+ "[ #{symlink_path} -ef #{target_path} ]"
20
+ end
21
+
18
22
  def safely_remove_file(_path)
19
23
  run_vagrant_command("rm #{test_file}")
20
24
  rescue
@@ -1,4 +1,4 @@
1
- require "English"
1
+ require "open3"
2
2
 
3
3
  module VagrantHelpers
4
4
  extend self
@@ -16,17 +16,18 @@ module VagrantHelpers
16
16
 
17
17
  def vagrant_cli_command(command)
18
18
  puts "[vagrant] #{command}"
19
- Dir.chdir(VAGRANT_ROOT) do
20
- `#{VAGRANT_BIN} #{command} 2>&1`.split("\n").each do |line|
21
- puts "[vagrant] #{line}"
22
- end
19
+ stdout, stderr, status = Dir.chdir(VAGRANT_ROOT) do
20
+ Open3.capture3("#{VAGRANT_BIN} #{command}")
23
21
  end
24
- $CHILD_STATUS
22
+
23
+ (stdout + stderr).each_line { |line| puts "[vagrant] #{line}" }
24
+
25
+ [stdout, stderr, status]
25
26
  end
26
27
 
27
28
  def run_vagrant_command(command)
28
- status = vagrant_cli_command("ssh -c #{command.inspect}")
29
- return true if status.success?
29
+ stdout, stderr, status = vagrant_cli_command("ssh -c #{command.inspect}")
30
+ return [stdout, stderr] if status.success?
30
31
  raise VagrantSSHCommandError, status
31
32
  end
32
33
  end
@@ -19,13 +19,19 @@ module Capistrano
19
19
  colors = SSHKit::Color.new($stderr)
20
20
  $stderr.puts colors.colorize("Skipping task `#{task_name}'.", :yellow)
21
21
  $stderr.puts "Capistrano tasks may only be invoked once. Since task `#{task}' was previously invoked, invoke(\"#{task_name}\") at #{file}:#{line} will be skipped."
22
- $stderr.puts "If you really meant to run this task again, first call Rake::Task[\"#{task_name}\"].reenable"
22
+ $stderr.puts "If you really meant to run this task again, use invoke!(\"#{task_name}\")"
23
23
  $stderr.puts colors.colorize("THIS BEHAVIOR MAY CHANGE IN A FUTURE VERSION OF CAPISTRANO. Please join the conversation here if this affects you.", :red)
24
24
  $stderr.puts colors.colorize("https://github.com/capistrano/capistrano/issues/1686", :red)
25
25
  end
26
26
  task.invoke(*args)
27
27
  end
28
28
 
29
+ def invoke!(task_name, *args)
30
+ task = Rake::Task[task_name]
31
+ task.reenable
32
+ task.invoke(*args)
33
+ end
34
+
29
35
  def t(key, options={})
30
36
  I18n.t(key, options.merge(scope: :capistrano))
31
37
  end
@@ -13,7 +13,7 @@ en = {
13
13
  question: "Please enter %{key}: ",
14
14
  question_default: "Please enter %{key} (%{default_value}): ",
15
15
  keeping_releases: "Keeping %{keep_releases} of %{releases} deployed releases on %{host}",
16
- skip_cleanup: "Skipping cleanup of old releases on %{host}; unexpected foldername found (should be timestamp)",
16
+ skip_cleanup: "Skipping cleanup of invalid releases on %{host}; unexpected foldername found (should be timestamp)",
17
17
  no_old_releases: "No old releases (keeping newest %{keep_releases}) on %{host}",
18
18
  linked_file_does_not_exist: "linked file %{file} does not exist on %{host}",
19
19
  cannot_rollback: "There are no older releases to rollback to",
@@ -149,11 +149,13 @@ namespace :deploy do
149
149
  task :cleanup do
150
150
  on release_roles :all do |host|
151
151
  releases = capture(:ls, "-x", releases_path).split
152
- if !(releases.all? { |e| /^\d{14}$/ =~ e })
153
- warn t(:skip_cleanup, host: host.to_s)
154
- elsif releases.count >= fetch(:keep_releases)
155
- info t(:keeping_releases, host: host.to_s, keep_releases: fetch(:keep_releases), releases: releases.count)
156
- directories = (releases - releases.last(fetch(:keep_releases)))
152
+ valid, invalid = releases.partition { |e| /^\d{14}$/ =~ e }
153
+
154
+ warn t(:skip_cleanup, host: host.to_s) if invalid.any?
155
+
156
+ if valid.count >= fetch(:keep_releases)
157
+ info t(:keeping_releases, host: host.to_s, keep_releases: fetch(:keep_releases), releases: valid.count)
158
+ directories = (valid - valid.last(fetch(:keep_releases)))
157
159
  if directories.any?
158
160
  directories_str = directories.map do |release|
159
161
  releases_path.join(release)
@@ -1,3 +1,3 @@
1
1
  module Capistrano
2
- VERSION = "3.8.2".freeze
2
+ VERSION = "3.9.0".freeze
3
3
  end
@@ -71,13 +71,54 @@ module Capistrano
71
71
  end
72
72
 
73
73
  describe "#invoke" do
74
- it "will print a message on stderr, when reinvoking task" do
75
- Rake::Task.define_task("some_task")
74
+ context "reinvoking" do
75
+ it "will not reenable invoking task" do
76
+ counter = 0
76
77
 
77
- dsl.invoke("some_task")
78
- expect do
79
- dsl.invoke("some_task")
80
- end.to output(/.*Capistrano tasks may only be invoked once.*/).to_stderr
78
+ Rake::Task.define_task("A") do
79
+ counter += 1
80
+ end
81
+
82
+ expect do
83
+ dsl.invoke("A")
84
+ dsl.invoke("A")
85
+ end.to change { counter }.by(1)
86
+ end
87
+
88
+ it "will print a message on stderr" do
89
+ Rake::Task.define_task("B")
90
+
91
+ expect do
92
+ dsl.invoke("B")
93
+ dsl.invoke("B")
94
+ end.to output(/If you really meant to run this task again, use invoke!/).to_stderr
95
+ end
96
+ end
97
+ end
98
+
99
+ describe "#invoke!" do
100
+ context "reinvoking" do
101
+ it "will reenable invoking task" do
102
+ counter = 0
103
+
104
+ Rake::Task.define_task("C") do
105
+ counter += 1
106
+ end
107
+
108
+ expect do
109
+ dsl.invoke!("C")
110
+ dsl.invoke!("C")
111
+ end.to change { counter }.by(2)
112
+ end
113
+
114
+ it "will not print a message on stderr" do
115
+ Rake::Task.define_task("D")
116
+
117
+ expect do
118
+ dsl.invoke!("D")
119
+ dsl.invoke!("D")
120
+ end.to_not output(/If you really meant to run this task again, use invoke!/).to_stderr
121
+ end
81
122
  end
82
123
  end
83
124
  end
@@ -132,12 +132,12 @@ module TestApp
132
132
  deploy_to.join("releases")
133
133
  end
134
134
 
135
- def release_path
136
- releases_path.join(timestamp)
135
+ def release_path(t=timestamp)
136
+ releases_path.join(t)
137
137
  end
138
138
 
139
- def timestamp
140
- Time.now.utc.strftime("%Y%m%d%H%M%S")
139
+ def timestamp(offset=0)
140
+ (Time.now.utc + offset).strftime("%Y%m%d%H%M%S")
141
141
  end
142
142
 
143
143
  def repo_path
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capistrano
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.8.2
4
+ version: 3.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Clements
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-06-16 00:00:00.000000000 Z
12
+ date: 2017-07-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: airbrussh
@@ -285,7 +285,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
285
285
  version: '0'
286
286
  requirements: []
287
287
  rubyforge_project:
288
- rubygems_version: 2.6.11
288
+ rubygems_version: 2.6.12
289
289
  signing_key:
290
290
  specification_version: 4
291
291
  summary: Capistrano - Welcome to easy deployment with Ruby over SSH