capistrano-net_storage 0.3.2 → 0.5.0
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 +5 -5
- data/.github/PULL_REQUEST_TEMPLATE.md +7 -0
- data/.travis.yml +4 -6
- data/CHANGELOG.md +18 -0
- data/README.md +9 -3
- data/capistrano-net_storage.gemspec +0 -1
- data/lib/capistrano/net_storage/archiver/base.rb +1 -2
- data/lib/capistrano/net_storage/archiver/tar_gzip.rb +1 -1
- data/lib/capistrano/net_storage/archiver/zip.rb +5 -2
- data/lib/capistrano/net_storage/cleaner.rb +84 -11
- data/lib/capistrano/net_storage/config.rb +24 -17
- data/lib/capistrano/net_storage/transport/base.rb +1 -1
- data/lib/capistrano/net_storage/utils.rb +11 -11
- data/lib/capistrano/net_storage/version.rb +1 -1
- data/lib/capistrano/tasks/net_storage.rake +20 -7
- metadata +8 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f402751b93d15bbc8660b9669a18977ac69d67381d45c0316afd89d185f750fe
|
4
|
+
data.tar.gz: 38905906ddf2c6aae2706679eb907b6970c1099e058eb8f8c676932656cc3f7d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c61f03392a39f8f69c824fc196ef3e056c206e1c00ecce038e73f18b8782074d4ef5895fbf65d4c5e42666950ab0b0c53b99ceeeeb5d428122c92caa1dc8373
|
7
|
+
data.tar.gz: cd42fc4f35a13075920dff572727a93e4f9db1d28249833d0af85a5edc82d661303a2595511ab2b7067f5a3939cead39d5a5a68ffe7a2577799ea94f03b9c099
|
data/.travis.yml
CHANGED
@@ -1,13 +1,11 @@
|
|
1
1
|
sudo: false
|
2
2
|
language: ruby
|
3
3
|
rvm:
|
4
|
-
- 2.
|
5
|
-
- 2.
|
6
|
-
- 2.
|
7
|
-
- 2.3.5
|
8
|
-
- 2.4.2
|
4
|
+
- 2.6.3
|
5
|
+
- 2.5.5
|
6
|
+
- 2.4.6
|
9
7
|
|
10
|
-
before_install: gem install bundler
|
8
|
+
before_install: gem install bundler
|
11
9
|
install: bundle install
|
12
10
|
script: bundle exec rake spec
|
13
11
|
notifications:
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
## 0.4.0 (2022/05/17)
|
2
|
+
|
3
|
+
Fix Bug:
|
4
|
+
|
5
|
+
- Fix a cleanup issue reported at #9 (#12) @naro143
|
6
|
+
- Before:
|
7
|
+
- Archives such as `.tar.gz` and `.zip` are handled in `releases` directory of each server.
|
8
|
+
- Incomplete deployment leads to uncollected garbage directory under `releases`.
|
9
|
+
- After:
|
10
|
+
- Archives are handled within `#{deploy_to}/net_storage_archives` directory of each server.
|
11
|
+
- NetStorage cleanup `net_storage_archives` directory just as Capistrano do in `releases` directory.
|
12
|
+
- One successful deployment can cleanup old archives and there is no more Capistrano warnings.
|
13
|
+
- This includes the same cleanup policy for `local_releases_path` and `local_archives_path` of NetStorage.
|
14
|
+
|
15
|
+
Changes:
|
16
|
+
|
17
|
+
- Change task name `net_storage:cleanup_remote_release` to `net_storage:cleanup_archives_on_remote_storage`
|
18
|
+
|
1
19
|
## 0.3.2 (2017/11/7)
|
2
20
|
|
3
21
|
Fix Bug:
|
data/README.md
CHANGED
@@ -49,15 +49,21 @@ Set Capistrano variables by `set name, value`.
|
|
49
49
|
`:scm` | `nil` | Set `:net_storage` for capistrano before v3.7
|
50
50
|
`:branch` | `master` | Target branch of SCM to release
|
51
51
|
`:keep_releases` | `5` | Numbers to keep released versions
|
52
|
-
`:net_storage_transport` | `nil` | Transport class for _remote storage_
|
53
52
|
`:net_storage_archiver` | `Capistrano::NetStorage::Archiver::Zip` | Archiver class
|
54
53
|
`:net_storage_scm` | `Capistrano::NetStorage::SCM::Git` | Internal scm class for application repository
|
55
|
-
`:
|
54
|
+
`:net_storage_transport` | `nil` | Transport class for _remote storage_
|
55
|
+
`:net_storage_archive_on_missing` | `true` | If `true`, create and upload archive only when target archive is missing on remote storage
|
56
56
|
`:net_storage_config_files` | `nil` | Files to sync `config/` directory on target servers' application directory
|
57
57
|
`:net_storage_max_parallels` | number of servers | Max concurrency for remote tasks
|
58
|
-
`:
|
58
|
+
`:net_storage_rsync_options` | `#{ssh_options}` | SSH options for rsync command to sync configs
|
59
59
|
`:net_storage_upload_files_by_rsync` | `false` | Use rsync(1) to deploy config files
|
60
|
+
`:net_storage_with_bundle` | `false` | Do `bundle install` when creating archive
|
60
61
|
`:net_storage_local_base_path` | `.local_repo` | Base directory on deploy server
|
62
|
+
`:net_storage_local_mirror_path` | `#{net_storage_local_base_path}/mirror` | Path to clone repository on deploy server
|
63
|
+
`:net_storage_local_releases_path` | `#{net_storage_local_base_path}/releases` | Path to keep release directories on deploy server
|
64
|
+
`:net_storage_local_bundle_path` | `#{net_storage_local_base_path}/bundle` | Shared directory to install gems on deploy server
|
65
|
+
`:net_storage_local_archives_path` | `#{net_storage_local_base_path}/archives` | Archive directories on deploy server
|
66
|
+
`:net_storage_archives_path` | `#{deploy_to}/net_storage_archives` | Archive directories on application server
|
61
67
|
|
62
68
|
### Transport Plugins
|
63
69
|
|
@@ -23,10 +23,10 @@ class Capistrano::NetStorage::Archiver::TarGzip < Capistrano::NetStorage::Archiv
|
|
23
23
|
def extract
|
24
24
|
c = config
|
25
25
|
on c.servers, in: :groups, limit: c.max_parallels do
|
26
|
+
execute :mkdir, '-p', c.archives_path
|
26
27
|
execute :mkdir, '-p', release_path
|
27
28
|
within release_path do
|
28
29
|
execute :tar, 'xzf', c.archive_path
|
29
|
-
execute :rm, '-f', c.archive_path
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
@@ -23,8 +23,11 @@ class Capistrano::NetStorage::Archiver::Zip < Capistrano::NetStorage::Archiver::
|
|
23
23
|
def extract
|
24
24
|
c = config
|
25
25
|
on c.servers, in: :groups, limit: c.max_parallels do
|
26
|
-
execute :
|
27
|
-
execute :
|
26
|
+
execute :mkdir, '-p', c.archives_path
|
27
|
+
execute :mkdir, '-p', release_path
|
28
|
+
within release_path do
|
29
|
+
execute :unzip, c.archive_path
|
30
|
+
end
|
28
31
|
end
|
29
32
|
end
|
30
33
|
end
|
@@ -6,22 +6,95 @@ module Capistrano
|
|
6
6
|
class Cleaner
|
7
7
|
include Capistrano::NetStorage::Utils
|
8
8
|
|
9
|
-
# Clean up
|
9
|
+
# Clean up old release directories on local.
|
10
10
|
# Assumes they are under +config.local_releases_path+
|
11
11
|
# @see Capistrano::NetStorage::Config#local_releases_path
|
12
|
-
def
|
12
|
+
def cleanup_local_releases
|
13
13
|
c = config
|
14
14
|
run_locally do
|
15
|
-
|
16
|
-
#
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
15
|
+
contents = capture(:ls, '-x', c.local_releases_path).split
|
16
|
+
# reference
|
17
|
+
# https://github.com/capistrano/capistrano/blob/cc4f31fdfcb4a21c569422a95868d0bb52844c75/lib/capistrano/tasks/deploy.rake#L152
|
18
|
+
releases, invalid = contents.partition { |e| /^\d{14}$/ =~ e }
|
19
|
+
|
20
|
+
if invalid.any?
|
21
|
+
warn "Invalid contents in #{c.local_releases_path} on local:\n#{invalid.join("\n")}"
|
22
|
+
end
|
23
|
+
|
24
|
+
if releases.count > fetch(:keep_releases)
|
25
|
+
info "Keeping #{fetch(:keep_releases)} of #{releases.count} releases on local"
|
26
|
+
old_releases = (releases - releases.last(fetch(:keep_releases))).map do |release|
|
27
|
+
c.local_releases_path.join(release).to_s
|
28
|
+
end
|
29
|
+
execute :rm, '-rf', *old_releases
|
30
|
+
else
|
31
|
+
info "No old releases (keeping newest #{fetch(:keep_releases)}) in #{c.local_releases_path} on local"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Clean up old archive files on local.
|
37
|
+
# Assumes they are under +config.local_archives_path+
|
38
|
+
# @see Capistrano::NetStorage::Config#local_archives_path
|
39
|
+
def cleanup_local_archives
|
40
|
+
c = config
|
41
|
+
run_locally do
|
42
|
+
contents = capture(:ls, '-x', c.local_archives_path).split
|
43
|
+
archives, invalid = contents.partition { |e| /^\d{14}\.#{Regexp.escape(c.archive_suffix)}$/ =~ e }
|
44
|
+
|
45
|
+
if invalid.any?
|
46
|
+
warn "Invalid contents in #{c.local_archives_path} on local:\n#{invalid.join("\n")}"
|
47
|
+
end
|
48
|
+
|
49
|
+
if archives.count > fetch(:keep_releases)
|
50
|
+
info "Keeping #{fetch(:keep_releases)} of #{archives.count} archives on local"
|
51
|
+
old_archives = (archives - archives.last(fetch(:keep_releases))).map do |archive|
|
52
|
+
c.local_archives_path.join(archive).to_s
|
53
|
+
end
|
54
|
+
execute :rm, '-f', *old_archives
|
55
|
+
else
|
56
|
+
info "No old archives (keeping newest #{fetch(:keep_releases)}) in #{c.local_archives_path} on local"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Clean up old archive files on remote servers.
|
62
|
+
# Assumes they are under +config.archives_path+
|
63
|
+
# @see Capistrano::NetStorage::Config#archives_path
|
64
|
+
def cleanup_archives
|
65
|
+
c = config
|
66
|
+
on c.servers, in: :groups, limit: c.max_parallels do |host|
|
67
|
+
contents = capture(:ls, '-x', c.archives_path).split
|
68
|
+
archives, invalid = contents.partition { |e| /^\d{14}\.#{Regexp.escape(c.archive_suffix)}$/ =~ e }
|
69
|
+
|
70
|
+
if invalid.any?
|
71
|
+
warn "Invalid contents in #{c.archives_path} on #{host}:\n#{invalid.join("\n")}"
|
72
|
+
end
|
73
|
+
|
74
|
+
if archives.count > fetch(:keep_releases)
|
75
|
+
info "Keeping #{fetch(:keep_releases)} of #{archives.count} archives on #{host}"
|
76
|
+
old_archives = (archives - archives.last(fetch(:keep_releases))).map do |archive|
|
77
|
+
c.archives_path.join(archive).to_s
|
78
|
+
end
|
79
|
+
|
80
|
+
if test("[ -d #{current_path} ]")
|
81
|
+
current_release = capture(:readlink, current_path).to_s
|
82
|
+
current_release_archive = c.archives_path.join("#{File.basename(current_release)}.#{c.archive_suffix}")
|
83
|
+
if old_archives.include?(current_release_archive)
|
84
|
+
warn "Current release archive was marked for being removed but it's going to be skipped on #{host}"
|
85
|
+
old_archives.delete(current_release_archive)
|
86
|
+
end
|
87
|
+
else
|
88
|
+
debug "There is no current release present on #{host}"
|
89
|
+
end
|
90
|
+
|
91
|
+
if old_archives.any?
|
92
|
+
old_archives.each_slice(100) do |old_archives_batch|
|
93
|
+
execute :rm, '-f', *old_archives_batch
|
94
|
+
end
|
95
|
+
end
|
23
96
|
else
|
24
|
-
info "No old
|
97
|
+
info "No old archives (keeping newest #{fetch(:keep_releases)}) in #{c.archives_path} on #{host}"
|
25
98
|
end
|
26
99
|
end
|
27
100
|
end
|
@@ -53,7 +53,7 @@ module Capistrano
|
|
53
53
|
@skip_bundle
|
54
54
|
end
|
55
55
|
|
56
|
-
# If +true+, create archive ONLY when it's not found on
|
56
|
+
# If +true+, create archive ONLY when it's not found on remote storage.
|
57
57
|
# Otherwise, create archive ALWAYS.
|
58
58
|
# Defaults to +true+
|
59
59
|
def archive_on_missing?
|
@@ -83,56 +83,63 @@ module Capistrano
|
|
83
83
|
# Path settings
|
84
84
|
#
|
85
85
|
|
86
|
-
# Path of base directory on
|
86
|
+
# Path of base directory on local
|
87
87
|
# @return [Pathname]
|
88
88
|
def local_base_path
|
89
89
|
@local_base_path ||= pathname(fetch(:net_storage_local_base_path, "#{Dir.pwd}/.local_repo"))
|
90
90
|
end
|
91
91
|
|
92
|
-
# Path to clone repository on
|
92
|
+
# Path to clone repository on local
|
93
93
|
# @return [Pathname]
|
94
94
|
def local_mirror_path
|
95
95
|
@local_mirror_path ||= pathname(fetch(:net_storage_local_mirror_path))
|
96
96
|
@local_mirror_path ||= local_base_path.join('mirror')
|
97
97
|
end
|
98
98
|
|
99
|
-
# Path to keep release directories
|
99
|
+
# Path to keep release directories on local
|
100
100
|
# @return [Pathname]
|
101
101
|
def local_releases_path
|
102
102
|
@local_releases_path ||= pathname(fetch(:net_storage_local_releases_path))
|
103
103
|
@local_releases_path ||= local_base_path.join('releases')
|
104
104
|
end
|
105
105
|
|
106
|
-
# Path to take a snapshot of repository for release
|
106
|
+
# Path to take a snapshot of repository for release on local
|
107
107
|
# @return [Pathname]
|
108
108
|
def local_release_path
|
109
|
-
@local_release_path ||= pathname(fetch(:net_storage_local_release_path))
|
110
109
|
@local_release_path ||= local_releases_path.join(release_timestamp)
|
111
110
|
end
|
112
111
|
|
113
|
-
# Shared directory to install gems
|
112
|
+
# Shared directory to install gems on local
|
114
113
|
# @return [Pathname]
|
115
114
|
def local_bundle_path
|
116
115
|
@local_bundle_path ||= pathname(fetch(:net_storage_local_bundle_path))
|
117
116
|
@local_bundle_path ||= local_base_path.join('bundle')
|
118
117
|
end
|
119
118
|
|
120
|
-
#
|
119
|
+
# Path of archive directories on local
|
120
|
+
# @return [Pathname]
|
121
|
+
def local_archives_path
|
122
|
+
@local_archives_path ||= pathname(fetch(:net_storage_local_archives_path))
|
123
|
+
@local_archives_path ||= local_base_path.join('archives')
|
124
|
+
end
|
125
|
+
|
126
|
+
# Destination path to archive application on local
|
121
127
|
# @return [Pathname]
|
122
128
|
def local_archive_path
|
123
|
-
@local_archive_path ||=
|
124
|
-
@local_archive_path ||= pathname("#{local_release_path}.#{archive_suffix}")
|
129
|
+
@local_archive_path ||= local_archives_path.join("#{release_timestamp}.#{archive_suffix}")
|
125
130
|
end
|
126
131
|
|
127
|
-
# Path of archive
|
132
|
+
# Path of archive directories on remote servers
|
133
|
+
# @return [Pathname]
|
134
|
+
def archives_path
|
135
|
+
@archives_path ||= pathname(fetch(:net_storage_archives_path))
|
136
|
+
@archives_path ||= deploy_path.join('net_storage_archives')
|
137
|
+
end
|
138
|
+
|
139
|
+
# Path of archive file to be downloaded on remote servers
|
128
140
|
# @return [Pathname]
|
129
141
|
def archive_path
|
130
|
-
@archive_path ||=
|
131
|
-
@archive_path ||= begin
|
132
|
-
# Set release_timestamp if not set
|
133
|
-
fetch(:release_path, set_release_path)
|
134
|
-
pathname("#{release_path}.#{archive_suffix}")
|
135
|
-
end
|
142
|
+
@archive_path ||= archives_path.join("#{release_timestamp}.#{archive_suffix}")
|
136
143
|
end
|
137
144
|
|
138
145
|
# Suffix of archive file
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'parallel'
|
2
|
-
|
3
1
|
require 'capistrano/net_storage/base'
|
4
2
|
|
5
3
|
module Capistrano
|
@@ -17,17 +15,19 @@ module Capistrano
|
|
17
15
|
def upload_files(files, dest_dir)
|
18
16
|
c = config
|
19
17
|
hosts = ::Capistrano::Configuration.env.filter(c.servers)
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
|
19
|
+
# FIXME: This is a very workaround to architectural issue. Do not copy.
|
20
|
+
build_rsh_option = -> (host) {
|
21
|
+
build_ssh_command(host)
|
22
|
+
}
|
23
|
+
|
24
|
+
on hosts, in: :groups, limit: c.max_parallels do |host|
|
25
|
+
if c.upload_files_by_rsync?
|
26
|
+
rsh_option = build_rsh_option.call(host)
|
23
27
|
run_locally do
|
24
|
-
files.
|
25
|
-
execute :rsync, "-az --rsh='#{ssh}' #{src} #{host}:#{dest_dir}"
|
26
|
-
end
|
28
|
+
execute :rsync, "-az --rsh='#{rsh_option}' #{files.join(' ')} #{host.hostname}:#{dest_dir}"
|
27
29
|
end
|
28
|
-
|
29
|
-
else
|
30
|
-
on c.servers, in: :groups, limit: c.max_parallels do
|
30
|
+
else
|
31
31
|
files.each do |src|
|
32
32
|
upload! src, dest_dir
|
33
33
|
end
|
@@ -43,19 +43,31 @@ namespace :net_storage do
|
|
43
43
|
end
|
44
44
|
after 'net_storage:create_release', 'net_storage:sync_config'
|
45
45
|
|
46
|
-
desc 'Clean up
|
47
|
-
task :
|
48
|
-
Capistrano::NetStorage.cleaner.
|
46
|
+
desc 'Clean up old release directories on local'
|
47
|
+
task :cleanup_local_releases do
|
48
|
+
Capistrano::NetStorage.cleaner.cleanup_local_releases
|
49
49
|
end
|
50
|
-
after 'deploy:cleanup', 'net_storage:
|
50
|
+
after 'deploy:cleanup', 'net_storage:cleanup_local_releases'
|
51
51
|
|
52
|
-
desc 'Clean up old
|
53
|
-
task :
|
52
|
+
desc 'Clean up old archive files on remote storage'
|
53
|
+
task :cleanup_archives_on_remote_storage do
|
54
54
|
transport = Capistrano::NetStorage.transport
|
55
55
|
next unless transport.respond_to?(:cleanup)
|
56
56
|
transport.cleanup
|
57
57
|
end
|
58
|
-
after '
|
58
|
+
after 'deploy:cleanup', 'net_storage:cleanup_archives_on_remote_storage'
|
59
|
+
|
60
|
+
desc 'Clean up old archive files on remote servers'
|
61
|
+
task :cleanup_archives do
|
62
|
+
Capistrano::NetStorage.cleaner.cleanup_archives
|
63
|
+
end
|
64
|
+
after 'deploy:cleanup', 'net_storage:cleanup_archives'
|
65
|
+
|
66
|
+
desc 'Clean up old archive files on local'
|
67
|
+
task :cleanup_local_archives do
|
68
|
+
Capistrano::NetStorage.cleaner.cleanup_local_archives
|
69
|
+
end
|
70
|
+
after 'deploy:cleanup', 'net_storage:cleanup_local_archives'
|
59
71
|
|
60
72
|
task prepare_archive: %i(net_storage:scm:update net_storage:check:bundler) do
|
61
73
|
config = Capistrano::NetStorage.config
|
@@ -103,6 +115,7 @@ namespace :net_storage do
|
|
103
115
|
config.local_base_path,
|
104
116
|
config.local_mirror_path,
|
105
117
|
config.local_releases_path,
|
118
|
+
config.local_archives_path,
|
106
119
|
]
|
107
120
|
dirs << config.local_bundle_path unless config.skip_bundle?
|
108
121
|
run_locally do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capistrano-net_storage
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- progrhyme
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-06-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: capistrano
|
@@ -24,20 +24,6 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 3.3.3
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: parallel
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: bundler
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -97,11 +83,12 @@ dependencies:
|
|
97
83
|
description: |2
|
98
84
|
A Capistrano SCM Plugin to deploy application via remove storage.
|
99
85
|
Logically, this enables O(1) deployment.
|
100
|
-
email:
|
86
|
+
email:
|
101
87
|
executables: []
|
102
88
|
extensions: []
|
103
89
|
extra_rdoc_files: []
|
104
90
|
files:
|
91
|
+
- ".github/PULL_REQUEST_TEMPLATE.md"
|
105
92
|
- ".gitignore"
|
106
93
|
- ".rspec"
|
107
94
|
- ".travis.yml"
|
@@ -134,7 +121,7 @@ homepage: https://github.com/DeNADev/capistrano-net_storage
|
|
134
121
|
licenses:
|
135
122
|
- MIT
|
136
123
|
metadata: {}
|
137
|
-
post_install_message:
|
124
|
+
post_install_message:
|
138
125
|
rdoc_options: []
|
139
126
|
require_paths:
|
140
127
|
- lib
|
@@ -149,9 +136,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
149
136
|
- !ruby/object:Gem::Version
|
150
137
|
version: '0'
|
151
138
|
requirements: []
|
152
|
-
|
153
|
-
|
154
|
-
signing_key:
|
139
|
+
rubygems_version: 3.4.13
|
140
|
+
signing_key:
|
155
141
|
specification_version: 4
|
156
142
|
summary: Capistrano SCM Plugin for fast deployment via remote storage
|
157
143
|
test_files: []
|