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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 507fe8707e3df873b757a6a44e830852f67d4444
4
- data.tar.gz: 15d1fa62fb07eabb8c40fbe22cb5007f9bef445f
2
+ SHA256:
3
+ metadata.gz: f402751b93d15bbc8660b9669a18977ac69d67381d45c0316afd89d185f750fe
4
+ data.tar.gz: 38905906ddf2c6aae2706679eb907b6970c1099e058eb8f8c676932656cc3f7d
5
5
  SHA512:
6
- metadata.gz: 06d7db8a593c0badde8a5f16f833a3f42f4ab1add488fcb88b1f6bb51f48d8d65a4feac9c14b833c6393de6d0d13225d54752d33afe244e0fb6c3c6033a5ac36
7
- data.tar.gz: d17853a6e94973c78e41f1ac807e635da7ca33d50bd131559a443e75ef6fabc0cd82d14e8344f67bdecaeab5f50196f448a969ccb37a3b5389495926bd010e28
6
+ metadata.gz: 3c61f03392a39f8f69c824fc196ef3e056c206e1c00ecce038e73f18b8782074d4ef5895fbf65d4c5e42666950ab0b0c53b99ceeeeb5d428122c92caa1dc8373
7
+ data.tar.gz: cd42fc4f35a13075920dff572727a93e4f9db1d28249833d0af85a5edc82d661303a2595511ab2b7067f5a3939cead39d5a5a68ffe7a2577799ea94f03b9c099
@@ -0,0 +1,7 @@
1
+ ### Summary
2
+
3
+ ### Other Information
4
+
5
+ ### Checklist
6
+
7
+ * [ ] By placing an "x" in the box, I hereby understand, accept and agree to be bound by the terms and conditions of the [Contribution License Agreement](https://dena.github.io/cla/).
data/.travis.yml CHANGED
@@ -1,13 +1,11 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 2.0.0
5
- - 2.1.8
6
- - 2.2.0
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 -v 1.14.6
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
- `:net_storage_with_bundle` | `false` | Do `bundle install` when creating archive
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
- `:net_storage_archive_on_missing` | `true` | If `true`, create and upload archive only when target archive is missing on remote storage
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
 
@@ -21,7 +21,6 @@ Gem::Specification.new do |spec|
21
21
  spec.required_ruby_version = '>= 2.0'
22
22
 
23
23
  spec.add_runtime_dependency 'capistrano', '>= 3.3.3'
24
- spec.add_runtime_dependency 'parallel'
25
24
  spec.add_runtime_dependency 'bundler'
26
25
 
27
26
  spec.add_development_dependency 'rake'
@@ -16,8 +16,7 @@ module Capistrano
16
16
  raise NotImplementedError
17
17
  end
18
18
 
19
- # Extract archive.
20
- # Archive file should be cleaned up after extracted.
19
+ # Extract archive
21
20
  # @abstract
22
21
  def extract
23
22
  raise NotImplementedError
@@ -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 :unzip, c.archive_path, '-d', release_path
27
- execute :rm, '-f', c.archive_path
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 local release directories and archives.
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 cleanup_local_release
12
+ def cleanup_local_releases
13
13
  c = config
14
14
  run_locally do
15
- releases = capture(:ls, '-xtr', c.local_releases_path).split
16
- # Contains archive files and extracted directories
17
- if releases.count > fetch(:keep_releases) * 2
18
- info "Keeping #{fetch(:keep_releases)} * 2 of #{releases.count} local releases"
19
- olds_str = (releases - releases.last(fetch(:keep_releases) * 2)).map do |file|
20
- c.local_releases_path.join(file)
21
- end.join(' ')
22
- execute :rm, '-rf', olds_str
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 local releases in #{c.local_releases_path}"
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 Network Storage.
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 localhost
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 localhost
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 and archives on localhost
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
- # Destination path to archive application on localhost
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 ||= pathname(fetch(:net_storage_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 file to be downloaded on servers
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 ||= pathname(fetch(:net_storage_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,7 +1,7 @@
1
1
  module Capistrano
2
2
  module NetStorage
3
3
  module Transport
4
- # Abstract class to transport archive from/to Network Storage
4
+ # Abstract class to transport archive from/to remote storage
5
5
  # @abstract
6
6
  class Base
7
7
  # Check prerequisites for transport
@@ -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
- if c.upload_files_by_rsync?
21
- Parallel.each(hosts, in_threads: c.max_parallels) do |host|
22
- ssh = build_ssh_command(host)
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.each do |src|
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
- end
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
@@ -1,5 +1,5 @@
1
1
  module Capistrano
2
2
  module NetStorage
3
- VERSION = '0.3.2'
3
+ VERSION = '0.5.0'
4
4
  end
5
5
  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 local old archives and snapshots'
47
- task :cleanup_local_release do
48
- Capistrano::NetStorage.cleaner.cleanup_local_release
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:cleanup_local_release'
50
+ after 'deploy:cleanup', 'net_storage:cleanup_local_releases'
51
51
 
52
- desc 'Clean up old archives on remote storage'
53
- task :cleanup_remote_release do
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 'net_storage:cleanup_local_release', 'net_storage:cleanup_remote_release'
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.3.2
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: 2017-11-07 00:00:00.000000000 Z
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
- rubyforge_project:
153
- rubygems_version: 2.6.13
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: []