capistrano-distribution 0.2.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 +7 -0
- data/.yardopts +1 -0
- data/LICENSE +22 -0
- data/NEWS.md +35 -0
- data/README.md +165 -0
- data/Rakefile +243 -0
- data/lib/capistrano/distribution/distributor/abstract.rb +85 -0
- data/lib/capistrano/distribution/distributor/abstract_archiver.rb +60 -0
- data/lib/capistrano/distribution/distributor/abstract_curl.rb +28 -0
- data/lib/capistrano/distribution/distributor/abstract_git.rb +56 -0
- data/lib/capistrano/distribution/distributor/curl_tar.rb +36 -0
- data/lib/capistrano/distribution/distributor/curl_zip.rb +40 -0
- data/lib/capistrano/distribution/distributor/git_pull.rb +67 -0
- data/lib/capistrano/distribution/distributor/git_push.rb +73 -0
- data/lib/capistrano/distribution/distributor/tar.rb +35 -0
- data/lib/capistrano/distribution/distributor/tar_helper.rb +40 -0
- data/lib/capistrano/distribution/distributor/zip.rb +31 -0
- data/lib/capistrano/distribution/distributor.rb +102 -0
- data/lib/capistrano/distribution/version.rb +9 -0
- data/lib/capistrano/distribution.rb +68 -0
- data/lib/capistrano/tasks/distribution.cap +33 -0
- metadata +152 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 51e2dcb1ba15f838b76d6eaf72e6f451c793f32b
|
4
|
+
data.tar.gz: 1cb882b4e420dc6c2292e897657f681b831d5515
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8f0275b355b9ee5311373aff3b70640ddb381fecd3dd3b6b57b9eab3817e17217a2c25667b53047dc69aa8fc3065050203fe7d828026c2f4bcfa1dc63ac2788c
|
7
|
+
data.tar.gz: 20a82ec2110fe7bfebd8ae1dfcd149e249f75332b1cde1d1fbeb4ac86afa6df2dff926958b2473b26c19882627f13414a02bc954540bc4cda5d87a2b5b70b78d
|
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--protected --private abstract lib/**/*.rb - README.md NEWS.md LICENSE
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
(The MIT License)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Spiceworks, Inc.
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
'Software'), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
20
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
21
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
22
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/NEWS.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# News and Notifications by Version
|
2
|
+
|
3
|
+
This file lists noteworthy changes which may affect users of this project. More
|
4
|
+
detailed information is available in the rest of the documentation.
|
5
|
+
|
6
|
+
**NOTE:** Date stamps in the following entries are in YYYY/MM/DD format.
|
7
|
+
|
8
|
+
|
9
|
+
## v0.2.0 (2016/02/29)
|
10
|
+
|
11
|
+
* Provide a setting (`:distribution_runner_opts`) to configure runner options.
|
12
|
+
* Must be a hash of options acceptable by the `on` method of sshkit.
|
13
|
+
* Git distributables can now change the repo URL without manual intervention.
|
14
|
+
* Pruning of dead Git branches now happens during repository update.
|
15
|
+
* Avoids too many dead branches causing updates to run forever.
|
16
|
+
|
17
|
+
## v0.1.0 (2016/02/09)
|
18
|
+
|
19
|
+
* Incompatible changes
|
20
|
+
* The `distribution` setting is now a stack of distributor definitions to be
|
21
|
+
applied in order as a series of overlays in the release area.
|
22
|
+
* Provides the `distribution:set_current_revision` task used by newer
|
23
|
+
Capistrano releases.
|
24
|
+
* A `release_id` setting is required to provide a reasonable value.
|
25
|
+
|
26
|
+
## v0.0.2 (2014/03/17)
|
27
|
+
|
28
|
+
* Ensure that the internal_path attribute of AbstractArchiver is a Pathname
|
29
|
+
* Fixes extraction of ZIP archives.
|
30
|
+
* Silence curl and unzip in the CurlZip distributor
|
31
|
+
* Silence unzip in the Zip distributor
|
32
|
+
|
33
|
+
## v0.0.1 (2014/02/27)
|
34
|
+
|
35
|
+
* Birthday
|
data/README.md
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
# Capistrano Distribution: More Than Just Git Deployments
|
2
|
+
|
3
|
+
Flexible distribution for Capistrano 3.x.
|
4
|
+
|
5
|
+
## LINKS
|
6
|
+
|
7
|
+
* Homepage :: http://github.com/spiceworks/capistrano-distribution
|
8
|
+
* Documentation :: http://rdoc.info/gems/capistrano-distribution/frames
|
9
|
+
* Source :: http://github.com/spiceworks/capistrano-distribution
|
10
|
+
|
11
|
+
## DESCRIPTION
|
12
|
+
|
13
|
+
This gem hooks into the SCM functionality of Capistrano 3.x in order to provide
|
14
|
+
a more generic distribution strategy. Not only is it possible to deploy from a
|
15
|
+
simple Git repository, but deployment of contents from Tar and ZIP files is also
|
16
|
+
possible. It is even easy to create deployments based on multiple sources.
|
17
|
+
|
18
|
+
With the exception of the Git push method, all distribution operations pull
|
19
|
+
content from providers on each target host. For Git-based distributions
|
20
|
+
whether using the push or pull method, this is very efficient after the first
|
21
|
+
deployment because a mirror git repository is saved on each host such that only
|
22
|
+
differentials are needed for future deployments. All other types perform a
|
23
|
+
full download of the source artifact, so these could be expensive and/or slow.
|
24
|
+
|
25
|
+
## Features
|
26
|
+
|
27
|
+
* Distribute from Git repositories and Tar/Zip archives.
|
28
|
+
* Use remote and local sources, anything supported by Git and Curl.
|
29
|
+
* Create homogenous deployments from multiple sources.
|
30
|
+
|
31
|
+
## Known Bugs/Limitations
|
32
|
+
|
33
|
+
* None so far...
|
34
|
+
|
35
|
+
## SYNOPSIS
|
36
|
+
|
37
|
+
Simple Git-based distribution (master branch of the current repository):
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
# config/deploy.rb
|
41
|
+
...
|
42
|
+
set :scm, :distribution
|
43
|
+
set :release_id, ->{ `git rev-parse HEAD`.chomp }
|
44
|
+
set :distribution, ->{
|
45
|
+
[[
|
46
|
+
'http://example.com/repositories/example.git',
|
47
|
+
fetch(:release_id)
|
48
|
+
]]
|
49
|
+
}
|
50
|
+
...
|
51
|
+
```
|
52
|
+
|
53
|
+
Simple Tar-based distribution (everything in the `example.tar.gz` archive is
|
54
|
+
within an `example` subdirectory):
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
# config/deploy.rb
|
58
|
+
...
|
59
|
+
set :scm, :distribution
|
60
|
+
set :release_id, ->{ "example-#{fetch(:release_timestamp)}" }
|
61
|
+
set :distribution, 'http://example.com/tarballs/example.tar.gz'
|
62
|
+
...
|
63
|
+
```
|
64
|
+
|
65
|
+
Heterogenous distribution (a Redmine deployment with plugins):
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
# config/deploy.rb
|
69
|
+
...
|
70
|
+
set :scm, :distribution
|
71
|
+
set :release_id, ->{ "2.3.4-#{fetch(:release_timestamp)}" }
|
72
|
+
set :distribution,
|
73
|
+
[
|
74
|
+
'http://www.redmine.org/releases/redmine-2.3.4.tar.gz'
|
75
|
+
],
|
76
|
+
[
|
77
|
+
'https://bitbucket.org/akiko_pusu/redmine_issue_templates/get/0.0.4.tar.gz',
|
78
|
+
{
|
79
|
+
subtree: 'akiko_pusu-redmine_issue_templates-b885dfe8263d',
|
80
|
+
target: 'plugins/redmine_issue_templates'
|
81
|
+
}
|
82
|
+
],
|
83
|
+
[
|
84
|
+
'https://bitbucket.org/haru_iida/redmine_code_review/get/0.6.2.tar.gz',
|
85
|
+
{
|
86
|
+
subtree: 'haru_iida-redmine_code_review-e79f98b8a77f',
|
87
|
+
target: 'plugins/redmine_code_review'
|
88
|
+
}
|
89
|
+
],
|
90
|
+
[
|
91
|
+
'https://github.com/Undev/notify_custom_users/archive/0.0.5.tar.gz',
|
92
|
+
{
|
93
|
+
subtree: 'notify_custom_users-0.0.5',
|
94
|
+
target: 'plugins/notify_custom_users'
|
95
|
+
}
|
96
|
+
],
|
97
|
+
[
|
98
|
+
'https://github.com/thorin/redmine_ldap_sync/archive/2.0.3.tar.gz',
|
99
|
+
{
|
100
|
+
subtree: 'redmine_ldap_sync-2.0.3',
|
101
|
+
target: 'plugins/redmine_ldap_sync'
|
102
|
+
}
|
103
|
+
]
|
104
|
+
...
|
105
|
+
```
|
106
|
+
|
107
|
+
## REQUIREMENTS
|
108
|
+
|
109
|
+
* Git binary (for Git repositories)
|
110
|
+
* Curl binary (for remote archives)
|
111
|
+
* Unzip binary (for ZIP archives)
|
112
|
+
* Tar binary (for Tar archives)
|
113
|
+
|
114
|
+
## DEVELOPERS
|
115
|
+
|
116
|
+
After checking out the source, run:
|
117
|
+
|
118
|
+
$ bundle install
|
119
|
+
$ bundle exec rake test yard
|
120
|
+
|
121
|
+
This will install all dependencies, run the tests/specs, and generate the
|
122
|
+
documentation.
|
123
|
+
|
124
|
+
## AUTHORS
|
125
|
+
|
126
|
+
Thanks to all contributors. Without your help this project would not exist.
|
127
|
+
|
128
|
+
* Jeremy Bopp :: jeremyb@spiceworks.com
|
129
|
+
|
130
|
+
## Contributing
|
131
|
+
|
132
|
+
Contributions for bug fixes, documentation, extensions, tests, etc. are
|
133
|
+
encouraged.
|
134
|
+
|
135
|
+
1. Clone the repository.
|
136
|
+
2. Fix a bug or add a feature.
|
137
|
+
3. Add tests for the fix or feature.
|
138
|
+
4. Make a pull request.
|
139
|
+
|
140
|
+
## LICENSE
|
141
|
+
|
142
|
+
```
|
143
|
+
(The MIT License)
|
144
|
+
|
145
|
+
Copyright (c) 2014 Spiceworks, Inc.
|
146
|
+
|
147
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
148
|
+
a copy of this software and associated documentation files (the
|
149
|
+
'Software'), to deal in the Software without restriction, including
|
150
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
151
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
152
|
+
permit persons to whom the Software is furnished to do so, subject to
|
153
|
+
the following conditions:
|
154
|
+
|
155
|
+
The above copyright notice and this permission notice shall be
|
156
|
+
included in all copies or substantial portions of the Software.
|
157
|
+
|
158
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
159
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
160
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
161
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
162
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
163
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
164
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
165
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,243 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
|
6
|
+
require 'erb'
|
7
|
+
require 'rake/testtask'
|
8
|
+
require 'rubygems/package_task'
|
9
|
+
require 'rake/clean'
|
10
|
+
require 'yard'
|
11
|
+
|
12
|
+
# Load the gemspec file for this project.
|
13
|
+
GEMSPEC = Dir['*.gemspec'].first
|
14
|
+
SPEC = eval(File.read(GEMSPEC), nil, GEMSPEC)
|
15
|
+
|
16
|
+
# The path to the version.rb file and a string to eval to find the version.
|
17
|
+
VERSION_RB = "lib/#{SPEC.name.gsub('-', '/')}/version.rb"
|
18
|
+
VERSION_REF =
|
19
|
+
"#{SPEC.name.split('-').map { |p| p.split('_').map(&:capitalize).join }.join('::')}::VERSION"
|
20
|
+
|
21
|
+
# A dynamically generated list of files that should match the manifest (the
|
22
|
+
# combined contents of SPEC.files and SPEC.test_files). The idea is for this
|
23
|
+
# list to contain all project files except for those that have been explicitly
|
24
|
+
# excluded. This list will be compared with the manifest from the SPEC in order
|
25
|
+
# to help catch the addition or removal of files to or from the project that
|
26
|
+
# have not been accounted for either by an exclusion here or an inclusion in the
|
27
|
+
# SPEC manifest.
|
28
|
+
#
|
29
|
+
# NOTE:
|
30
|
+
# It is critical that the manifest is *not* automatically generated via globbing
|
31
|
+
# and the like; otherwise, this will yield a simple comparison between
|
32
|
+
# redundantly generated lists of files that probably will not protect the
|
33
|
+
# project from the unintentional inclusion or exclusion of files in the
|
34
|
+
# distribution.
|
35
|
+
PKG_FILES = FileList.new(Dir.glob('**/*', File::FNM_DOTMATCH)) do |files|
|
36
|
+
# Exclude anything that doesn't exist as well as directories.
|
37
|
+
files.exclude {|file| ! File.exist?(file) || File.directory?(file)}
|
38
|
+
# Exclude Git administrative files.
|
39
|
+
files.exclude(%r{(^|[/\\])\.git(ignore|modules|keep)?([/\\]|$)})
|
40
|
+
# Exclude editor swap/temporary files.
|
41
|
+
files.exclude('**/.*.sw?')
|
42
|
+
# Exclude the gemspec file.
|
43
|
+
files.exclude(GEMSPEC)
|
44
|
+
# Exclude the README template file.
|
45
|
+
files.exclude('README.md.erb')
|
46
|
+
# Exclude resources for bundler.
|
47
|
+
files.exclude('Gemfile', 'Gemfile.lock')
|
48
|
+
files.exclude(%r{^.bundle([/\\]|$)})
|
49
|
+
files.exclude(%r{^vendor/bundle([/\\]|$)})
|
50
|
+
# Exclude generated content, except for the README file.
|
51
|
+
files.exclude(%r{^(pkg|doc|.yardoc)([/\\]|$)})
|
52
|
+
# Exclude Rubinius compiled Ruby files.
|
53
|
+
files.exclude('**/*.rbc')
|
54
|
+
end
|
55
|
+
|
56
|
+
# Make sure that :clean and :clobber will not whack the repository files.
|
57
|
+
CLEAN.exclude('.git/**')
|
58
|
+
# Vim swap files are fair game for clean up.
|
59
|
+
CLEAN.include('**/.*.sw?')
|
60
|
+
|
61
|
+
# Returns the value of the VERSION environment variable as a Gem::Version object
|
62
|
+
# assuming it is set and a valid Gem version string. Otherwise, raises an
|
63
|
+
# exception.
|
64
|
+
def get_version_argument
|
65
|
+
version = ENV['VERSION']
|
66
|
+
if version.to_s.empty?
|
67
|
+
raise "No version specified: Add VERSION=X.Y.Z to the command line"
|
68
|
+
end
|
69
|
+
begin
|
70
|
+
Gem::Version.create(version.dup)
|
71
|
+
rescue ArgumentError
|
72
|
+
raise "Invalid version specified in `VERSION=#{version}'"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Performs an in place, per line edit of the file indicated by _path_ by calling
|
77
|
+
# the sub method on each line and passing _pattern_, _replacement_, and _b_ as
|
78
|
+
# arguments.
|
79
|
+
def file_sub(path, pattern, replacement = nil, &b)
|
80
|
+
tmp_path = "#{path}.tmp"
|
81
|
+
File.open(path) do |infile|
|
82
|
+
File.open(tmp_path, 'w') do |outfile|
|
83
|
+
infile.each do |line|
|
84
|
+
outfile.write(line.sub(pattern, replacement, &b))
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
File.rename(tmp_path, path)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Updates the version string in the gemspec file and a version.rb file it to the
|
92
|
+
# string in _version_.
|
93
|
+
def set_version(version)
|
94
|
+
file_sub(GEMSPEC, /(\.version\s*=\s*).*/, "\\1'#{version}'")
|
95
|
+
file_sub(VERSION_RB, /^(\s*VERSION\s*=\s*).*/, "\\1'#{version}'")
|
96
|
+
end
|
97
|
+
|
98
|
+
# Returns a string that is line wrapped at word boundaries, where each line is
|
99
|
+
# no longer than _line_width_ characters.
|
100
|
+
#
|
101
|
+
# This is mostly lifted directly from ActionView::Helpers::TextHelper.
|
102
|
+
def word_wrap(text, line_width = 80)
|
103
|
+
text.split("\n").collect do |line|
|
104
|
+
line.length > line_width ?
|
105
|
+
line.gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip :
|
106
|
+
line
|
107
|
+
end * "\n"
|
108
|
+
end
|
109
|
+
|
110
|
+
desc 'Alias for build:gem'
|
111
|
+
task :build => 'build:gem'
|
112
|
+
|
113
|
+
# Build related tasks.
|
114
|
+
namespace :build do
|
115
|
+
# Create the gem and package tasks.
|
116
|
+
Gem::PackageTask.new(SPEC).define
|
117
|
+
|
118
|
+
# Ensure that the that the manifest is consulted when building the gem. Any
|
119
|
+
# generated/compiled files should be available at that time.
|
120
|
+
task :gem => :check_manifest
|
121
|
+
|
122
|
+
desc 'Verify the manifest'
|
123
|
+
task :check_manifest do
|
124
|
+
manifest_files = (SPEC.files + SPEC.test_files).sort.uniq
|
125
|
+
pkg_files = PKG_FILES.sort.uniq
|
126
|
+
if manifest_files != pkg_files then
|
127
|
+
common_files = manifest_files & pkg_files
|
128
|
+
manifest_files -= common_files
|
129
|
+
pkg_files -= common_files
|
130
|
+
message = ["The manifest does not match the automatic file list."]
|
131
|
+
unless manifest_files.empty? then
|
132
|
+
message << " Extraneous files:\n " + manifest_files.join("\n ")
|
133
|
+
end
|
134
|
+
unless pkg_files.empty?
|
135
|
+
message << " Missing files:\n " + pkg_files.join("\n ")
|
136
|
+
end
|
137
|
+
raise message.join("\n")
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Creates the README.md file from a template and the gemspec contents.
|
142
|
+
file 'README.md' => ['README.md.erb', GEMSPEC] do
|
143
|
+
spec = SPEC
|
144
|
+
File.open('README.md', 'w') do |readme|
|
145
|
+
readme.write(
|
146
|
+
ERB.new(File.read('README.md.erb'), nil, '-').result(binding)
|
147
|
+
)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# Ensure that the clobber task also clobbers package files.
|
153
|
+
task :clobber => 'build:clobber_package'
|
154
|
+
|
155
|
+
# Create the documentation task.
|
156
|
+
YARD::Rake::YardocTask.new
|
157
|
+
# Ensure that the README file is (re)generated first.
|
158
|
+
task :yard => 'README.md'
|
159
|
+
|
160
|
+
# Gem related tasks.
|
161
|
+
namespace :gem do
|
162
|
+
desc 'Alias for build:gem'
|
163
|
+
task :build => 'build:gem'
|
164
|
+
|
165
|
+
desc 'Publish the gemfile'
|
166
|
+
task :publish => ['version:check', :test, 'repo:tag', :build] do
|
167
|
+
sh "gem push pkg/#{SPEC.name}-#{SPEC.version}*.gem"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
Rake::TestTask.new do |t|
|
172
|
+
t.pattern = 'spec/**/*_spec.rb'
|
173
|
+
end
|
174
|
+
|
175
|
+
# Version string management tasks.
|
176
|
+
namespace :version do
|
177
|
+
desc 'Set the version for the project to a specified version'
|
178
|
+
task :set do
|
179
|
+
set_version(get_version_argument)
|
180
|
+
end
|
181
|
+
|
182
|
+
desc 'Set the version for the project back to 0.0.0'
|
183
|
+
task :reset do
|
184
|
+
set_version('0.0.0')
|
185
|
+
end
|
186
|
+
|
187
|
+
desc 'Check that all version strings are correctly set'
|
188
|
+
task :check => ['version:check:spec', 'version:check:version_rb', 'version:check:news']
|
189
|
+
|
190
|
+
namespace :check do
|
191
|
+
desc 'Check that the version in the gemspec is correctly set'
|
192
|
+
task :spec do
|
193
|
+
version = get_version_argument
|
194
|
+
if version != SPEC.version
|
195
|
+
raise "The given version `#{version}' does not match the gemspec version `#{SPEC.version}'"
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
desc 'Check that the version in the version.rb file is correctly set'
|
200
|
+
task :version_rb do
|
201
|
+
version = get_version_argument
|
202
|
+
begin
|
203
|
+
load VERSION_RB
|
204
|
+
internal_version = Gem::Version.create(eval(VERSION_REF))
|
205
|
+
if version != internal_version
|
206
|
+
raise "The given version `#{version}' does not match the version.rb version `#{internal_version}'"
|
207
|
+
end
|
208
|
+
rescue ArgumentError
|
209
|
+
raise "Invalid version specified in `#{VERSION_RB}'"
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
desc 'Check that the NEWS.md file mentions the version'
|
214
|
+
task :news do
|
215
|
+
version = get_version_argument
|
216
|
+
begin
|
217
|
+
File.open('NEWS.md') do |news|
|
218
|
+
unless news.each_line.any? {|l| l =~ /^## v#{Regexp.escape(version.to_s)} /}
|
219
|
+
raise "The NEWS.md file does not mention version `#{version}'"
|
220
|
+
end
|
221
|
+
end
|
222
|
+
rescue Errno::ENOENT
|
223
|
+
raise 'No NEWS.md file found'
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
# Repository and workspace management tasks.
|
230
|
+
namespace :repo do
|
231
|
+
desc 'Tag the current HEAD with the version string'
|
232
|
+
task :tag => :check_workspace do
|
233
|
+
version = get_version_argument
|
234
|
+
sh "git tag -s -m 'Release v#{version}' v#{version}"
|
235
|
+
end
|
236
|
+
|
237
|
+
desc 'Ensure the workspace is fully committed and clean'
|
238
|
+
task :check_workspace => ['README.md'] do
|
239
|
+
unless `git status --untracked-files=all --porcelain`.empty?
|
240
|
+
raise 'Workspace has been modified. Commit pending changes and try again.'
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Capistrano
|
2
|
+
class Distribution
|
3
|
+
module Distributor
|
4
|
+
|
5
|
+
##
|
6
|
+
# @abstract Subclass and override {#check} and {#distribute} to create a
|
7
|
+
# distributor.
|
8
|
+
#
|
9
|
+
# An abstract distributor upon which all distributors should ultimately be
|
10
|
+
# based.
|
11
|
+
#
|
12
|
+
# See the existing concrete distributor definitions for examples.
|
13
|
+
class Abstract
|
14
|
+
##
|
15
|
+
# @param context [(#test, #execute)] a Capistrano context used to run
|
16
|
+
# commands.
|
17
|
+
# @param url [URI, String] a URL to be used for fetching the artifact to be
|
18
|
+
# distributed
|
19
|
+
# @param opts [Hash] options to override default settings
|
20
|
+
# @option opts [String] :target ('') a path within the release area to be the
|
21
|
+
# root of the distribution.
|
22
|
+
def initialize(context, url, opts = {})
|
23
|
+
@context = context
|
24
|
+
@url = URI === url ? url : URI.parse(url)
|
25
|
+
@target = opts.fetch(:target, '')
|
26
|
+
|
27
|
+
@repo_id = Digest::SHA1.hexdigest(url.to_s)
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# @abstract Override to provide a meaningful check for prerequisites during
|
32
|
+
# deployment.
|
33
|
+
#
|
34
|
+
# @return [Boolean] +true+ when prerequisites are met and +false+
|
35
|
+
# otherwise.
|
36
|
+
def check
|
37
|
+
false
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# @abstract Override to provide meaningful distribution logic during
|
42
|
+
# deployment.
|
43
|
+
#
|
44
|
+
# @return [nil]
|
45
|
+
#
|
46
|
+
# @raise [exception] when distribution fails.
|
47
|
+
def distribute
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
##
|
53
|
+
# The source URL for the artifact to be distributed.
|
54
|
+
attr_reader :url
|
55
|
+
|
56
|
+
##
|
57
|
+
# The Capistrano context in which the distributor will operate.
|
58
|
+
attr_reader :context
|
59
|
+
|
60
|
+
##
|
61
|
+
# A unique identifier for the distributor for use under {#repo_path}.
|
62
|
+
attr_reader :repo_id
|
63
|
+
|
64
|
+
##
|
65
|
+
# A path relative to the release location in which to distribute the artifact.
|
66
|
+
attr_reader :target
|
67
|
+
|
68
|
+
##
|
69
|
+
# @return [Pathname] a path to the release location in which to distribute the
|
70
|
+
# artifact based on {#target}
|
71
|
+
def release_path
|
72
|
+
context.release_path.join(target)
|
73
|
+
end
|
74
|
+
|
75
|
+
##
|
76
|
+
# @return [Pathname] a path under the repo location to a unique workspace for
|
77
|
+
# the distributor
|
78
|
+
def repo_path
|
79
|
+
context.repo_path.join(repo_id)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
require 'capistrano/distribution/distributor/abstract'
|
4
|
+
|
5
|
+
module Capistrano
|
6
|
+
class Distribution
|
7
|
+
module Distributor
|
8
|
+
|
9
|
+
##
|
10
|
+
# @abstract Subclass and override {#distribute} to create a distributor that
|
11
|
+
# extracts archives found on the local filesystem.
|
12
|
+
#
|
13
|
+
# A convenience class for distributors that extract an archive file.
|
14
|
+
class AbstractArchiver < Abstract
|
15
|
+
##
|
16
|
+
# A regexp that matches file extentions typically found on archives used to
|
17
|
+
# distribute program binaries and source releases.
|
18
|
+
EXT_MATCHER = %r{(\.[^\d.]+[^.]*)+$}
|
19
|
+
|
20
|
+
##
|
21
|
+
# @param context [{#test, #execute}] a Capistrano context used to run
|
22
|
+
# commands.
|
23
|
+
# @param url [URI, String] a URL to be used for fetching the artifact to be
|
24
|
+
# distributed
|
25
|
+
# @param opts [Hash] options to override default settings
|
26
|
+
# @option opts [String] :subtree a path within the archive to extract as if
|
27
|
+
# its contents were at the root of the archive
|
28
|
+
def initialize(context, url, opts = {})
|
29
|
+
super(context, url, opts)
|
30
|
+
@subtree = Pathname.new(
|
31
|
+
opts.fetch(:subtree, File.basename(url).sub(ext_matcher, ''))
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Tests whether or not the archive indicated by {#url} is locally available.
|
37
|
+
#
|
38
|
+
# @return [Boolean] +true+ if the archive is available; otherwise, +false+.
|
39
|
+
#
|
40
|
+
# @see Abstract#check
|
41
|
+
def check
|
42
|
+
context.test '[', '-f', url.path, ']'
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
##
|
48
|
+
# The path within the archive to extract. May be an empty string.
|
49
|
+
attr_reader :subtree
|
50
|
+
|
51
|
+
##
|
52
|
+
# @return [Regexp] a regexp that matches file extentions.
|
53
|
+
def ext_matcher
|
54
|
+
EXT_MATCHER
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'capistrano/distribution/distributor/abstract_archiver'
|
2
|
+
|
3
|
+
module Capistrano
|
4
|
+
class Distribution
|
5
|
+
module Distributor
|
6
|
+
|
7
|
+
##
|
8
|
+
# @abstract Subclass and override {#distribute} to create a distributor that
|
9
|
+
# extracts archives reachable via +curl+ command.
|
10
|
+
#
|
11
|
+
# A convenience class for distributors that extract an archive downloaded using
|
12
|
+
# the +curl+ command.
|
13
|
+
class AbstractCurl < AbstractArchiver
|
14
|
+
##
|
15
|
+
# Tests whether or not the archive indicated by {#url} is available via the
|
16
|
+
# +curl+ command.
|
17
|
+
#
|
18
|
+
# @return [Boolean] +true+ if the archive is available; otherwise, +false+.
|
19
|
+
#
|
20
|
+
# @see Abstract#check
|
21
|
+
def check
|
22
|
+
context.test 'curl', '--fail', '--location', '--silent', '--head', '--request', 'GET', url
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|