auto_tagger 0.1.0 → 0.1.2
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.
- data/.document +6 -0
- data/CHANGELOG +6 -0
- data/README.md +4 -5
- data/Rakefile +46 -0
- data/VERSION +1 -1
- data/auto_tagger.gemspec +15 -12
- data/bin/autotag +5 -14
- data/features/support/step_helpers.rb +0 -1
- data/features/templates/cap_ext_deploy.erb +1 -1
- data/features/templates/deploy.erb +1 -1
- data/lib/auto_tagger/base.rb +26 -0
- data/lib/auto_tagger/capistrano_helper.rb +33 -31
- data/lib/auto_tagger/commander.rb +14 -10
- data/{recipes/release_tagger.rb → lib/auto_tagger/recipes.rb} +5 -5
- data/lib/auto_tagger/repository.rb +31 -30
- data/lib/auto_tagger/stage_manager.rb +17 -17
- data/lib/auto_tagger/tag.rb +31 -29
- data/lib/auto_tagger.rb +1 -1
- data/spec/auto_tagger/base_spec.rb +85 -0
- data/spec/auto_tagger/capistrano_helper_spec.rb +27 -27
- data/spec/auto_tagger/commander_spec.rb +5 -5
- data/spec/auto_tagger/repository_spec.rb +20 -20
- data/spec/auto_tagger/stage_manager_spec.rb +7 -7
- data/spec/auto_tagger/tag_spec.rb +8 -8
- metadata +31 -14
- data/lib/auto_tagger/auto_tagger.rb +0 -26
- data/spec/auto_tagger/auto_tagger_spec.rb +0 -85
data/.document
ADDED
data/CHANGELOG
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
2010-04-25
|
2
|
+
|
3
|
+
- Fixed creating incorrect tags when deploying from a branch, tag, or from head (Brian Takita & Bruce Krysiak)
|
4
|
+
- Namespaced all classes under AutoTagger (Pat Nakajima)
|
5
|
+
- Renamed Commander.execute! to Commander.execute? (Pat Nakjima)
|
6
|
+
|
1
7
|
2009-10-15
|
2
8
|
|
3
9
|
- You can now define your stages as strings or symbols and auto-tagger will not fail (thanks to Chad Wooley for the bug report)
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# IMPORTANT NOTE
|
2
2
|
|
3
|
-
This
|
3
|
+
This creates and pushes tags to your git repository, please use with caution.
|
4
4
|
|
5
5
|
# AutoTagger
|
6
6
|
|
@@ -16,12 +16,10 @@ You can use the `autotag` command to tag releases on your CI box, then use the c
|
|
16
16
|
|
17
17
|
## Installation
|
18
18
|
|
19
|
-
gem
|
20
|
-
sudo gem install zilkey-auto_tagger
|
19
|
+
sudo gem install auto_tagger
|
21
20
|
|
22
21
|
## Contribute
|
23
22
|
|
24
|
-
* [Tracker Project](http://www.pivotaltracker.com/projects/11988)
|
25
23
|
* [GitHub Repository](http://github.com/zilkey/auto_tagger/tree/master)
|
26
24
|
|
27
25
|
## The autotag executable
|
@@ -164,12 +162,13 @@ To run the cucumber features, execute:
|
|
164
162
|
|
165
163
|
## Acknowledgments
|
166
164
|
|
167
|
-
Special thanks to
|
165
|
+
Special thanks to:
|
168
166
|
|
169
167
|
* Brian Takita for the original recipes
|
170
168
|
* Mike Dalessio for his git fu
|
171
169
|
* Chad Wooley for his feature ideas
|
172
170
|
* Tim Holahan for his QA
|
171
|
+
* Pat Nakajima for making auto_tagger a better ruby citizen
|
173
172
|
|
174
173
|
## Links
|
175
174
|
|
data/Rakefile
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "auto_tagger"
|
8
|
+
gem.summary = %Q{Helps you automatically create tags for each stage in a multi-stage deploment and deploy from the latest tag from the previous environment}
|
9
|
+
gem.email = "jeff@zilkey.com"
|
10
|
+
gem.homepage = "http://github.com/zilkey/auto_tagger"
|
11
|
+
gem.authors = ["Jeff Dean", "Brian Takita", "Mike Grafton", "Bruce Krysiak", "Pat Nakajima", "Jay Zeschin", "Mike Barinek"]
|
12
|
+
gem.add_dependency('capistrano', [">= 2.5.3"])
|
13
|
+
gem.require_paths = ["lib"]
|
14
|
+
gem.executables = ["autotag"]
|
15
|
+
gem.default_executable = %q{autotag}
|
16
|
+
gem.date = %q{2010-04-25}
|
17
|
+
end
|
18
|
+
Jeweler::GemcutterTasks.new
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'spec/rake/spectask'
|
24
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
25
|
+
spec.libs << 'lib' << 'spec'
|
26
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
27
|
+
end
|
28
|
+
|
29
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
30
|
+
spec.libs << 'lib' << 'spec'
|
31
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
32
|
+
spec.rcov = true
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
task :default => :spec
|
37
|
+
|
38
|
+
require 'rake/rdoctask'
|
39
|
+
Rake::RDocTask.new do |rdoc|
|
40
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
41
|
+
|
42
|
+
rdoc.rdoc_dir = 'rdoc'
|
43
|
+
rdoc.title = "the-perfect-gem #{version}"
|
44
|
+
rdoc.rdoc_files.include('README*')
|
45
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
46
|
+
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.2
|
data/auto_tagger.gemspec
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{auto_tagger}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
-
s.authors = ["Jeff Dean", "Brian Takita"]
|
12
|
-
s.date = %q{
|
11
|
+
s.authors = ["Jeff Dean", "Brian Takita", "Mike Grafton", "Bruce Krysiak", "Pat Nakajima", "Jay Zeschin", "Mike Barinek"]
|
12
|
+
s.date = %q{2010-04-25}
|
13
13
|
s.default_executable = %q{autotag}
|
14
14
|
s.email = %q{jeff@zilkey.com}
|
15
15
|
s.executables = ["autotag"]
|
@@ -17,10 +17,12 @@ Gem::Specification.new do |s|
|
|
17
17
|
"README.md"
|
18
18
|
]
|
19
19
|
s.files = [
|
20
|
-
".
|
20
|
+
".document",
|
21
|
+
".gitignore",
|
21
22
|
"CHANGELOG",
|
22
23
|
"MIT-LICENSE",
|
23
24
|
"README.md",
|
25
|
+
"Rakefile",
|
24
26
|
"VERSION",
|
25
27
|
"auto_tagger.gemspec",
|
26
28
|
"bin/autotag",
|
@@ -35,14 +37,14 @@ Gem::Specification.new do |s|
|
|
35
37
|
"features/templates/stage.erb",
|
36
38
|
"geminstaller.yml",
|
37
39
|
"lib/auto_tagger.rb",
|
38
|
-
"lib/auto_tagger/
|
40
|
+
"lib/auto_tagger/base.rb",
|
39
41
|
"lib/auto_tagger/capistrano_helper.rb",
|
40
42
|
"lib/auto_tagger/commander.rb",
|
43
|
+
"lib/auto_tagger/recipes.rb",
|
41
44
|
"lib/auto_tagger/repository.rb",
|
42
45
|
"lib/auto_tagger/stage_manager.rb",
|
43
46
|
"lib/auto_tagger/tag.rb",
|
44
|
-
"
|
45
|
-
"spec/auto_tagger/auto_tagger_spec.rb",
|
47
|
+
"spec/auto_tagger/base_spec.rb",
|
46
48
|
"spec/auto_tagger/capistrano_helper_spec.rb",
|
47
49
|
"spec/auto_tagger/commander_spec.rb",
|
48
50
|
"spec/auto_tagger/repository_spec.rb",
|
@@ -52,11 +54,11 @@ Gem::Specification.new do |s|
|
|
52
54
|
]
|
53
55
|
s.homepage = %q{http://github.com/zilkey/auto_tagger}
|
54
56
|
s.rdoc_options = ["--charset=UTF-8"]
|
55
|
-
s.require_paths = ["lib"
|
56
|
-
s.rubygems_version = %q{1.3.
|
57
|
+
s.require_paths = ["lib"]
|
58
|
+
s.rubygems_version = %q{1.3.6}
|
57
59
|
s.summary = %q{Helps you automatically create tags for each stage in a multi-stage deploment and deploy from the latest tag from the previous environment}
|
58
60
|
s.test_files = [
|
59
|
-
"spec/auto_tagger/
|
61
|
+
"spec/auto_tagger/base_spec.rb",
|
60
62
|
"spec/auto_tagger/capistrano_helper_spec.rb",
|
61
63
|
"spec/auto_tagger/commander_spec.rb",
|
62
64
|
"spec/auto_tagger/repository_spec.rb",
|
@@ -78,3 +80,4 @@ Gem::Specification.new do |s|
|
|
78
80
|
s.add_dependency(%q<capistrano>, [">= 2.5.3"])
|
79
81
|
end
|
80
82
|
end
|
83
|
+
|
data/bin/autotag
CHANGED
@@ -2,10 +2,6 @@
|
|
2
2
|
require File.expand_path(File.join(File.dirname(__FILE__), "..", "lib", "auto_tagger"))
|
3
3
|
require 'getoptlong'
|
4
4
|
|
5
|
-
opts = GetoptLong.new(
|
6
|
-
['--help', '-h', '-?', GetoptLong::NO_ARGUMENT]
|
7
|
-
)
|
8
|
-
|
9
5
|
def usage
|
10
6
|
puts
|
11
7
|
puts "USAGE: #{File.basename($0)} <stage> [<repository>]"
|
@@ -23,16 +19,11 @@ def usage
|
|
23
19
|
exit 0
|
24
20
|
end
|
25
21
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
end
|
32
|
-
|
33
|
-
if ARGV[0]
|
34
|
-
AutoTagger.new(ARGV[0], ARGV[1]).create_tag
|
35
|
-
exit 0
|
22
|
+
if ARGV[0] && ["-h", "--help", "-?", "--?"].include?(ARGV[0])
|
23
|
+
usage
|
24
|
+
elsif ARGV[0]
|
25
|
+
AutoTagger::Runner.new(ARGV[0], ARGV[1]).create_tag
|
26
|
+
exit 1
|
36
27
|
else
|
37
28
|
usage
|
38
29
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "lib", "auto_tagger", "recipes"))
|
2
2
|
|
3
3
|
set :autotagger_stages, [:ci, :staging, :production]
|
4
4
|
set :stages, [:staging, :production]
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "lib", "auto_tagger", "recipes"))
|
2
2
|
|
3
3
|
set :autotagger_stages, ["<%= environments.join('", "') %>"]
|
4
4
|
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module AutoTagger
|
2
|
+
class EnvironmentCannotBeBlankError < StandardError; end
|
3
|
+
|
4
|
+
class Runner
|
5
|
+
attr_reader :stage, :repository, :working_directory
|
6
|
+
|
7
|
+
def initialize(stage, path = nil)
|
8
|
+
raise EnvironmentCannotBeBlankError if stage.to_s.strip == ""
|
9
|
+
@working_directory = File.expand_path(path ||= Dir.pwd)
|
10
|
+
@repository = Repository.new(@working_directory)
|
11
|
+
@stage = stage
|
12
|
+
end
|
13
|
+
|
14
|
+
def create_tag(commit = nil)
|
15
|
+
repository.tags.fetch
|
16
|
+
new_tag = repository.tags.create(stage, commit)
|
17
|
+
repository.tags.push
|
18
|
+
new_tag
|
19
|
+
end
|
20
|
+
|
21
|
+
def latest_tag
|
22
|
+
repository.tags.fetch
|
23
|
+
repository.tags.latest_from(stage)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -1,39 +1,41 @@
|
|
1
|
-
|
1
|
+
module AutoTagger
|
2
|
+
class CapistranoHelper
|
2
3
|
|
3
|
-
|
4
|
+
attr_reader :variables, :stage, :working_directory
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
def initialize(variables)
|
7
|
+
@stage_manager = StageManager.new(variables[:autotagger_stages])
|
8
|
+
@variables = variables
|
9
|
+
@stage = variables[:stage]
|
10
|
+
@working_directory = variables[:working_directory] || Dir.pwd
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
def previous_stage
|
14
|
+
@stage_manager.previous_stage(stage)
|
15
|
+
end
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
17
|
+
def branch
|
18
|
+
if variables.has_key?(:head)
|
19
|
+
variables[:branch]
|
20
|
+
elsif variables.has_key?(:tag)
|
21
|
+
variables[:tag]
|
22
|
+
elsif previous_stage && (latest = Runner.new(previous_stage, working_directory).latest_tag)
|
23
|
+
latest
|
24
|
+
else
|
25
|
+
variables[:branch]
|
26
|
+
end
|
25
27
|
end
|
26
|
-
end
|
27
28
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
29
|
+
def release_tag_entries
|
30
|
+
entries = []
|
31
|
+
@stage_manager.stages.each do |stage|
|
32
|
+
tagger = Runner.new(stage, working_directory)
|
33
|
+
tag = tagger.latest_tag
|
34
|
+
commit = tagger.repository.commit_for(tag)
|
35
|
+
entries << "#{stage.to_s.ljust(10, " ")} #{tag.to_s.ljust(30, " ")} #{commit.to_s}"
|
36
|
+
end
|
37
|
+
entries
|
35
38
|
end
|
36
|
-
entries
|
37
|
-
end
|
38
39
|
|
39
|
-
end
|
40
|
+
end
|
41
|
+
end
|
@@ -1,15 +1,19 @@
|
|
1
|
-
|
2
|
-
class
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
module AutoTagger
|
2
|
+
class Commander
|
3
|
+
class << self
|
4
|
+
def execute(path, cmd)
|
5
|
+
`#{command_in_context(path, cmd)}`
|
6
|
+
end
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
8
|
+
def execute?(path, cmd)
|
9
|
+
system command_in_context(path, cmd)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
10
13
|
|
11
|
-
|
12
|
-
|
14
|
+
def command_in_context(path, cmd)
|
15
|
+
"cd #{path} && #{cmd}"
|
16
|
+
end
|
13
17
|
end
|
14
18
|
end
|
15
19
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), "..", "
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "auto_tagger"))
|
2
2
|
|
3
3
|
Capistrano::Configuration.instance(:must_exist).load do
|
4
4
|
namespace :release_tagger do
|
@@ -7,7 +7,7 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|
7
7
|
Use -Shead=true to set the branch to master, -Stag=<tag> to specify the tag explicitly.
|
8
8
|
}
|
9
9
|
task :set_branch do
|
10
|
-
if branch_name = CapistranoHelper.new(variables).branch
|
10
|
+
if branch_name = AutoTagger::CapistranoHelper.new(variables).branch
|
11
11
|
set :branch, branch_name
|
12
12
|
logger.info "setting branch to #{branch_name}"
|
13
13
|
else
|
@@ -18,7 +18,7 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|
18
18
|
desc %Q{Prints the most current tags from all stages}
|
19
19
|
task :print_latest_tags, :roles => :app do
|
20
20
|
logger.info "AUTO TAGGER: release tag history is:"
|
21
|
-
entries = CapistranoHelper.new(variables).release_tag_entries
|
21
|
+
entries = AutoTagger::CapistranoHelper.new(variables).release_tag_entries
|
22
22
|
entries.each do |entry|
|
23
23
|
logger.info entry
|
24
24
|
end
|
@@ -43,10 +43,10 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|
43
43
|
desc %Q{Creates a tag using the stage variable}
|
44
44
|
task :create_tag, :roles => :app do
|
45
45
|
if variables[:stage]
|
46
|
-
tag_name = AutoTagger.new(variables[:stage], variables[:working_directory]).create_tag(real_revision)
|
46
|
+
tag_name = AutoTagger::Runner.new(variables[:stage], variables[:working_directory]).create_tag(real_revision)
|
47
47
|
logger.info "AUTO TAGGER created tag #{tag_name} from #{real_revision}"
|
48
48
|
else
|
49
|
-
tag_name = AutoTagger.new(:production, variables[:working_directory]).create_tag
|
49
|
+
tag_name = AutoTagger::Runner.new(:production, variables[:working_directory]).create_tag
|
50
50
|
logger.info "AUTO TAGGER created tag #{tag_name}"
|
51
51
|
end
|
52
52
|
end
|
@@ -1,42 +1,43 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
module AutoTagger
|
3
2
|
class NoPathProvidedError < StandardError; end
|
4
3
|
class NoSuchPathError < StandardError; end
|
5
4
|
class InvalidGitRepositoryError < StandardError; end
|
6
5
|
class GitCommandFailedError < StandardError; end
|
6
|
+
|
7
|
+
class Repository
|
8
|
+
attr_reader :path
|
9
|
+
|
10
|
+
def initialize(path)
|
11
|
+
if path.to_s.strip == ""
|
12
|
+
raise NoPathProvidedError
|
13
|
+
elsif ! File.exists?(path)
|
14
|
+
raise NoSuchPathError
|
15
|
+
elsif ! File.exists?(File.join(path, ".git"))
|
16
|
+
raise InvalidGitRepositoryError
|
17
|
+
else
|
18
|
+
@path = path
|
19
|
+
end
|
20
|
+
end
|
7
21
|
|
8
|
-
|
9
|
-
|
10
|
-
def initialize(path)
|
11
|
-
if path.to_s.strip == ""
|
12
|
-
raise NoPathProvidedError
|
13
|
-
elsif ! File.exists?(path)
|
14
|
-
raise NoSuchPathError
|
15
|
-
elsif ! File.exists?(File.join(path, ".git"))
|
16
|
-
raise InvalidGitRepositoryError
|
17
|
-
else
|
18
|
-
@path = path
|
22
|
+
def ==(other)
|
23
|
+
other.is_a?(Repository) && other.path == path
|
19
24
|
end
|
20
|
-
end
|
21
25
|
|
22
|
-
|
23
|
-
|
24
|
-
|
26
|
+
def tags
|
27
|
+
@tags ||= Tag.new(self)
|
28
|
+
end
|
25
29
|
|
26
|
-
|
27
|
-
|
28
|
-
|
30
|
+
def commit_for(tag)
|
31
|
+
Commander.execute(path, "git --no-pager log #{tag} --pretty=oneline -1")
|
32
|
+
end
|
29
33
|
|
30
|
-
|
31
|
-
|
32
|
-
|
34
|
+
def run(cmd)
|
35
|
+
Commander.execute(path, cmd)
|
36
|
+
end
|
33
37
|
|
34
|
-
|
35
|
-
|
36
|
-
|
38
|
+
def run!(cmd)
|
39
|
+
Commander.execute?(path, cmd) || raise(GitCommandFailedError)
|
40
|
+
end
|
37
41
|
|
38
|
-
def run!(cmd)
|
39
|
-
Commander.execute!(path, cmd) || raise(GitCommandFailedError)
|
40
42
|
end
|
41
|
-
|
42
|
-
end
|
43
|
+
end
|
@@ -1,23 +1,23 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
module AutoTagger
|
2
|
+
class StageManager
|
3
|
+
class NoStagesSpecifiedError < StandardError
|
4
|
+
def message
|
5
|
+
"You must set the :stages variable to an array, like set :stages, [:ci, :demo]"
|
6
|
+
end
|
6
7
|
end
|
7
|
-
end
|
8
8
|
|
9
|
-
|
9
|
+
attr_reader :stages
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
def initialize(stages)
|
12
|
+
raise NoStagesSpecifiedError unless stages && stages.is_a?(Array)
|
13
|
+
@stages = stages.map{|stage| stage.to_s }
|
14
|
+
end
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
def previous_stage(stage)
|
17
|
+
if stage
|
18
|
+
index = stages.index(stage.to_s) - 1
|
19
|
+
stages[index] if index > -1
|
20
|
+
end
|
20
21
|
end
|
21
22
|
end
|
22
|
-
|
23
|
-
end
|
23
|
+
end
|
data/lib/auto_tagger/tag.rb
CHANGED
@@ -1,41 +1,43 @@
|
|
1
1
|
# git --no-pager log --pretty=oneline -1
|
2
2
|
# git tag -a -m 'Successful continuous integration build on #{timestamp}' #{tag_name}"
|
3
|
-
|
3
|
+
module AutoTagger
|
4
|
+
class Tag
|
4
5
|
|
5
|
-
|
6
|
+
attr_reader :repository
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
8
|
+
def initialize(repository)
|
9
|
+
@repository = repository
|
10
|
+
end
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
def find_all
|
13
|
+
repository.run("git tag").split("\n")
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
def fetch
|
17
|
+
repository.run! "git fetch origin --tags"
|
18
|
+
end
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
def latest_from(stage)
|
21
|
+
find_all.select{|tag| tag =~ /^#{stage}\//}.sort.last
|
22
|
+
end
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
def push
|
25
|
+
repository.run! "git push origin --tags"
|
26
|
+
end
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
28
|
+
def create(stage, commit = nil)
|
29
|
+
tag_name = name_for(stage)
|
30
|
+
cmd = "git tag #{tag_name}"
|
31
|
+
cmd += " #{commit}" if commit
|
32
|
+
repository.run! cmd
|
33
|
+
tag_name
|
34
|
+
end
|
34
35
|
|
35
|
-
|
36
|
+
private
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
38
|
+
def name_for(stage)
|
39
|
+
"%s/%s" % [stage, Time.now.utc.strftime('%Y%m%d%H%M%S')]
|
40
|
+
end
|
40
41
|
|
41
|
-
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/auto_tagger.rb
CHANGED
@@ -0,0 +1,85 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe AutoTagger::Runner do
|
4
|
+
before(:each) do
|
5
|
+
stub(Dir).pwd { File.join(File.dirname(__FILE__), '..', '..') }
|
6
|
+
end
|
7
|
+
|
8
|
+
describe ".new" do
|
9
|
+
it "blows up if you don't pass an stage" do
|
10
|
+
proc do
|
11
|
+
AutoTagger::Runner.new(nil)
|
12
|
+
end.should raise_error(AutoTagger::EnvironmentCannotBeBlankError)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "sets the stage when it's passed" do
|
16
|
+
AutoTagger::Runner.new("ci").stage.should == "ci"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "sets the path to Dir.pwd when nil" do
|
20
|
+
mock(Dir).pwd { "/foo" }
|
21
|
+
mock(AutoTagger::Repository).new("/foo")
|
22
|
+
AutoTagger::Runner.new("ci")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "expands the path when the path is passed" do
|
26
|
+
mock(AutoTagger::Repository).new(File.expand_path("."))
|
27
|
+
AutoTagger::Runner.new("ci", ".")
|
28
|
+
end
|
29
|
+
|
30
|
+
it "exposes the working directory" do
|
31
|
+
mock(AutoTagger::Repository).new(File.expand_path("."))
|
32
|
+
AutoTagger::Runner.new("ci", ".").working_directory.should == File.expand_path(".")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#create_tag" do
|
37
|
+
it "generates the correct commands" do
|
38
|
+
time = Time.local(2001,1,1)
|
39
|
+
mock(Time).now.once {time}
|
40
|
+
timestamp = time.utc.strftime('%Y%m%d%H%M%S')
|
41
|
+
mock(File).exists?(anything).twice { true }
|
42
|
+
|
43
|
+
mock(AutoTagger::Commander).execute?("/foo", "git fetch origin --tags") {true}
|
44
|
+
mock(AutoTagger::Commander).execute?("/foo", "git tag ci/#{timestamp}") {true}
|
45
|
+
mock(AutoTagger::Commander).execute?("/foo", "git push origin --tags") {true}
|
46
|
+
|
47
|
+
AutoTagger::Runner.new("ci", "/foo").create_tag
|
48
|
+
end
|
49
|
+
|
50
|
+
it "allows you to base it off an existing tag or commit" do
|
51
|
+
time = Time.local(2001,1,1)
|
52
|
+
mock(Time).now.once {time}
|
53
|
+
timestamp = time.utc.strftime('%Y%m%d%H%M%S')
|
54
|
+
mock(File).exists?(anything).twice { true }
|
55
|
+
|
56
|
+
mock(AutoTagger::Commander).execute?("/foo", "git fetch origin --tags") {true}
|
57
|
+
mock(AutoTagger::Commander).execute?("/foo", "git tag ci/#{timestamp} guid") {true}
|
58
|
+
mock(AutoTagger::Commander).execute?("/foo", "git push origin --tags") {true}
|
59
|
+
|
60
|
+
AutoTagger::Runner.new("ci", "/foo").create_tag("guid")
|
61
|
+
end
|
62
|
+
|
63
|
+
it "returns the tag that was created" do
|
64
|
+
time = Time.local(2001,1,1)
|
65
|
+
mock(Time).now.once {time}
|
66
|
+
timestamp = time.utc.strftime('%Y%m%d%H%M%S')
|
67
|
+
mock(File).exists?(anything).twice { true }
|
68
|
+
mock(AutoTagger::Commander).execute?(anything, anything).times(any_times) {true}
|
69
|
+
|
70
|
+
AutoTagger::Runner.new("ci", "/foo").create_tag.should == "ci/#{timestamp}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "#latest_tag" do
|
75
|
+
it "generates the correct commands" do
|
76
|
+
mock(File).exists?(anything).twice { true }
|
77
|
+
|
78
|
+
mock(AutoTagger::Commander).execute?("/foo", "git fetch origin --tags") {true}
|
79
|
+
mock(AutoTagger::Commander).execute("/foo", "git tag") { "ci_01" }
|
80
|
+
|
81
|
+
AutoTagger::Runner.new("ci", "/foo").latest_tag
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
@@ -1,53 +1,53 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../spec_helper'
|
2
2
|
|
3
|
-
describe CapistranoHelper do
|
3
|
+
describe AutoTagger::CapistranoHelper do
|
4
4
|
|
5
5
|
describe ".new" do
|
6
6
|
it "blows up if there are no stages" do
|
7
7
|
proc do
|
8
|
-
CapistranoHelper.new({})
|
9
|
-
end.should raise_error(StageManager::NoStagesSpecifiedError)
|
8
|
+
AutoTagger::CapistranoHelper.new({})
|
9
|
+
end.should raise_error(AutoTagger::StageManager::NoStagesSpecifiedError)
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
13
|
describe "#variables" do
|
14
14
|
it "returns all variables" do
|
15
|
-
CapistranoHelper.new({:autotagger_stages => [:bar]}).variables.should == {:autotagger_stages => [:bar]}
|
15
|
+
AutoTagger::CapistranoHelper.new({:autotagger_stages => [:bar]}).variables.should == {:autotagger_stages => [:bar]}
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
19
|
describe "#working_directory" do
|
20
20
|
it "returns the hashes' working directory value" do
|
21
|
-
CapistranoHelper.new({:autotagger_stages => [:bar], :working_directory => "/foo"}).working_directory.should == "/foo"
|
21
|
+
AutoTagger::CapistranoHelper.new({:autotagger_stages => [:bar], :working_directory => "/foo"}).working_directory.should == "/foo"
|
22
22
|
end
|
23
23
|
|
24
24
|
it "defaults to Dir.pwd if it's not set, or it's nil" do
|
25
25
|
mock(Dir).pwd { "/bar" }
|
26
|
-
CapistranoHelper.new({:autotagger_stages => [:bar]}).working_directory.should == "/bar"
|
26
|
+
AutoTagger::CapistranoHelper.new({:autotagger_stages => [:bar]}).working_directory.should == "/bar"
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
30
|
describe "#stage" do
|
31
31
|
it "returns the hashes' current stage value" do
|
32
|
-
CapistranoHelper.new({:autotagger_stages => [:bar], :stage => :bar}).stage.should == :bar
|
33
|
-
CapistranoHelper.new({:autotagger_stages => [:bar]}).stage.should be_nil
|
32
|
+
AutoTagger::CapistranoHelper.new({:autotagger_stages => [:bar], :stage => :bar}).stage.should == :bar
|
33
|
+
AutoTagger::CapistranoHelper.new({:autotagger_stages => [:bar]}).stage.should be_nil
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
37
|
describe "#release_tag_entries" do
|
38
38
|
it "returns a column-justifed version of all the commits" do
|
39
|
-
mock(Commander).execute("/foo", "git tag").times(any_times) { "ci/01\nstaging/01\nproduction/01" }
|
40
|
-
mock(Commander).execute("/foo", "git --no-pager log ci/01 --pretty=oneline -1") { "guid1" }
|
41
|
-
mock(Commander).execute("/foo", "git --no-pager log staging/01 --pretty=oneline -1") { "guid2" }
|
42
|
-
mock(Commander).execute("/foo", "git --no-pager log production/01 --pretty=oneline -1") { "guid3" }
|
43
|
-
mock(Commander).execute
|
39
|
+
mock(AutoTagger::Commander).execute("/foo", "git tag").times(any_times) { "ci/01\nstaging/01\nproduction/01" }
|
40
|
+
mock(AutoTagger::Commander).execute("/foo", "git --no-pager log ci/01 --pretty=oneline -1") { "guid1" }
|
41
|
+
mock(AutoTagger::Commander).execute("/foo", "git --no-pager log staging/01 --pretty=oneline -1") { "guid2" }
|
42
|
+
mock(AutoTagger::Commander).execute("/foo", "git --no-pager log production/01 --pretty=oneline -1") { "guid3" }
|
43
|
+
mock(AutoTagger::Commander).execute?("/foo", "git fetch origin --tags").times(any_times) { true }
|
44
44
|
mock(File).exists?(anything).times(any_times) {true}
|
45
45
|
|
46
46
|
variables = {
|
47
47
|
:working_directory => "/foo",
|
48
48
|
:autotagger_stages => [:ci, :staging, :production]
|
49
49
|
}
|
50
|
-
histories = CapistranoHelper.new(variables).release_tag_entries
|
50
|
+
histories = AutoTagger::CapistranoHelper.new(variables).release_tag_entries
|
51
51
|
histories.length.should == 3
|
52
52
|
histories[0].should include("ci/01", "guid1")
|
53
53
|
histories[1].should include("staging/01", "guid2")
|
@@ -55,16 +55,16 @@ describe CapistranoHelper do
|
|
55
55
|
end
|
56
56
|
|
57
57
|
it "ignores tags delimited with '_'" do
|
58
|
-
mock(Commander).execute("/foo", "git tag").times(any_times) { "ci/01\nci_02" }
|
59
|
-
mock(Commander).execute("/foo", "git --no-pager log ci/01 --pretty=oneline -1") { "guid1" }
|
60
|
-
mock(Commander).execute
|
58
|
+
mock(AutoTagger::Commander).execute("/foo", "git tag").times(any_times) { "ci/01\nci_02" }
|
59
|
+
mock(AutoTagger::Commander).execute("/foo", "git --no-pager log ci/01 --pretty=oneline -1") { "guid1" }
|
60
|
+
mock(AutoTagger::Commander).execute?("/foo", "git fetch origin --tags").times(any_times) { true }
|
61
61
|
mock(File).exists?(anything).times(any_times) {true}
|
62
62
|
|
63
63
|
variables = {
|
64
64
|
:working_directory => "/foo",
|
65
65
|
:autotagger_stages => [:ci]
|
66
66
|
}
|
67
|
-
histories = CapistranoHelper.new(variables).release_tag_entries
|
67
|
+
histories = AutoTagger::CapistranoHelper.new(variables).release_tag_entries
|
68
68
|
histories.length.should == 1
|
69
69
|
histories[0].should include("ci/01", "guid1")
|
70
70
|
end
|
@@ -78,7 +78,7 @@ describe CapistranoHelper do
|
|
78
78
|
:head => nil,
|
79
79
|
:branch => "foo"
|
80
80
|
}
|
81
|
-
CapistranoHelper.new(variables).branch.should == "foo"
|
81
|
+
AutoTagger::CapistranoHelper.new(variables).branch.should == "foo"
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
@@ -88,7 +88,7 @@ describe CapistranoHelper do
|
|
88
88
|
:autotagger_stages => [:bar],
|
89
89
|
:head => nil
|
90
90
|
}
|
91
|
-
CapistranoHelper.new(variables).branch.should == nil
|
91
|
+
AutoTagger::CapistranoHelper.new(variables).branch.should == nil
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
@@ -98,7 +98,7 @@ describe CapistranoHelper do
|
|
98
98
|
:autotagger_stages => [:bar],
|
99
99
|
:branch => "foo"
|
100
100
|
}
|
101
|
-
CapistranoHelper.new(variables).branch.should == "foo"
|
101
|
+
AutoTagger::CapistranoHelper.new(variables).branch.should == "foo"
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
@@ -112,8 +112,8 @@ describe CapistranoHelper do
|
|
112
112
|
}
|
113
113
|
tagger = Object.new
|
114
114
|
mock(tagger).latest_tag { "foo_01" }
|
115
|
-
mock(AutoTagger).new("foo", "/foo") { tagger }
|
116
|
-
CapistranoHelper.new(variables).branch.should == "foo_01"
|
115
|
+
mock(AutoTagger::Runner).new("foo", "/foo") { tagger }
|
116
|
+
AutoTagger::CapistranoHelper.new(variables).branch.should == "foo_01"
|
117
117
|
end
|
118
118
|
end
|
119
119
|
|
@@ -126,8 +126,8 @@ describe CapistranoHelper do
|
|
126
126
|
}
|
127
127
|
tagger = Object.new
|
128
128
|
mock(tagger).latest_tag { nil }
|
129
|
-
mock(AutoTagger).new("foo", "/foo") { tagger }
|
130
|
-
CapistranoHelper.new(variables).branch.should == nil
|
129
|
+
mock(AutoTagger::Runner).new("foo", "/foo") { tagger }
|
130
|
+
AutoTagger::CapistranoHelper.new(variables).branch.should == nil
|
131
131
|
end
|
132
132
|
end
|
133
133
|
|
@@ -137,8 +137,8 @@ describe CapistranoHelper do
|
|
137
137
|
:autotagger_stages => [:bar],
|
138
138
|
:stage => :bar
|
139
139
|
}
|
140
|
-
CapistranoHelper.new(variables).previous_stage.should be_nil
|
141
|
-
CapistranoHelper.new(variables).branch.should == nil
|
140
|
+
AutoTagger::CapistranoHelper.new(variables).previous_stage.should be_nil
|
141
|
+
AutoTagger::CapistranoHelper.new(variables).branch.should == nil
|
142
142
|
end
|
143
143
|
end
|
144
144
|
end
|
@@ -1,17 +1,17 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../spec_helper'
|
2
2
|
|
3
|
-
describe Commander do
|
3
|
+
describe AutoTagger::Commander do
|
4
4
|
describe ".execute" do
|
5
5
|
it "execute the command and returns the results" do
|
6
|
-
mock(Commander).`("cd /foo && ls") { "" } #`
|
7
|
-
Commander.execute("/foo", "ls")
|
6
|
+
mock(AutoTagger::Commander).`("cd /foo && ls") { "" } #`
|
7
|
+
AutoTagger::Commander.execute("/foo", "ls")
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
11
|
describe "system" do
|
12
12
|
it "executes and doesn't return anything" do
|
13
|
-
mock(Commander).system("cd /foo && ls")
|
14
|
-
Commander.execute
|
13
|
+
mock(AutoTagger::Commander).system("cd /foo && ls")
|
14
|
+
AutoTagger::Commander.execute?("/foo", "ls")
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
@@ -1,71 +1,71 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../spec_helper'
|
2
2
|
|
3
|
-
describe Repository do
|
3
|
+
describe AutoTagger::Repository do
|
4
4
|
describe ".new" do
|
5
5
|
it "sets the repo" do
|
6
6
|
mock(File).exists?(anything).twice { true }
|
7
|
-
repo = Repository.new("/foo")
|
7
|
+
repo = AutoTagger::Repository.new("/foo")
|
8
8
|
repo.path.should == "/foo"
|
9
9
|
end
|
10
10
|
|
11
11
|
it "raises an error when the path is blank" do
|
12
12
|
proc do
|
13
|
-
Repository.new(" ")
|
14
|
-
end.should raise_error(
|
13
|
+
AutoTagger::Repository.new(" ")
|
14
|
+
end.should raise_error(AutoTagger::NoPathProvidedError)
|
15
15
|
end
|
16
16
|
|
17
17
|
it "raises an error when the path is nil" do
|
18
18
|
proc do
|
19
|
-
Repository.new(nil)
|
20
|
-
end.should raise_error(
|
19
|
+
AutoTagger::Repository.new(nil)
|
20
|
+
end.should raise_error(AutoTagger::NoPathProvidedError)
|
21
21
|
end
|
22
22
|
|
23
23
|
it "raises an error with a file that doesn't exist" do
|
24
24
|
mock(File).exists?("/foo") { false }
|
25
25
|
proc do
|
26
|
-
Repository.new("/foo")
|
27
|
-
end.should raise_error(
|
26
|
+
AutoTagger::Repository.new("/foo")
|
27
|
+
end.should raise_error(AutoTagger::NoSuchPathError)
|
28
28
|
end
|
29
29
|
|
30
30
|
it "raises an error with a non-git repository" do
|
31
31
|
mock(File).exists?("/foo") { true }
|
32
32
|
mock(File).exists?("/foo/.git") { false }
|
33
33
|
proc do
|
34
|
-
Repository.new("/foo")
|
35
|
-
end.should raise_error(
|
34
|
+
AutoTagger::Repository.new("/foo")
|
35
|
+
end.should raise_error(AutoTagger::InvalidGitRepositoryError)
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
39
|
describe "#==" do
|
40
40
|
it "compares paths" do
|
41
41
|
mock(File).exists?(anything).times(any_times) { true }
|
42
|
-
Repository.new("/foo").should_not == "/foo"
|
43
|
-
Repository.new("/foo").should_not == Repository.new("/bar")
|
44
|
-
Repository.new("/foo").should == Repository.new("/foo")
|
42
|
+
AutoTagger::Repository.new("/foo").should_not == "/foo"
|
43
|
+
AutoTagger::Repository.new("/foo").should_not == AutoTagger::Repository.new("/bar")
|
44
|
+
AutoTagger::Repository.new("/foo").should == AutoTagger::Repository.new("/foo")
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
48
|
describe "#run" do
|
49
49
|
it "sends the correct command" do
|
50
50
|
mock(File).exists?(anything).twice { true }
|
51
|
-
mock(Commander).execute("/foo", "bar")
|
52
|
-
Repository.new("/foo").run("bar")
|
51
|
+
mock(AutoTagger::Commander).execute("/foo", "bar")
|
52
|
+
AutoTagger::Repository.new("/foo").run("bar")
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
56
|
describe "run!" do
|
57
57
|
it "sends the correct command" do
|
58
58
|
mock(File).exists?(anything).twice { true }
|
59
|
-
mock(Commander).execute
|
60
|
-
Repository.new("/foo").run!("bar")
|
59
|
+
mock(AutoTagger::Commander).execute?("/foo", "bar") { true }
|
60
|
+
AutoTagger::Repository.new("/foo").run!("bar")
|
61
61
|
end
|
62
62
|
|
63
63
|
it "raises an exception if it the command returns false" do
|
64
64
|
mock(File).exists?(anything).twice { true }
|
65
|
-
mock(Commander).execute
|
65
|
+
mock(AutoTagger::Commander).execute?("/foo", "bar") { false }
|
66
66
|
proc do
|
67
|
-
Repository.new("/foo").run!("bar")
|
68
|
-
end.should raise_error(
|
67
|
+
AutoTagger::Repository.new("/foo").run!("bar")
|
68
|
+
end.should raise_error(AutoTagger::GitCommandFailedError)
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
@@ -1,32 +1,32 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../spec_helper'
|
2
2
|
|
3
|
-
describe StageManager do
|
3
|
+
describe AutoTagger::StageManager do
|
4
4
|
|
5
5
|
describe ".new" do
|
6
6
|
[nil, ""].each do |value|
|
7
7
|
it "blows up if there are stages == #{value.inspect}" do
|
8
8
|
proc do
|
9
|
-
StageManager.new(value)
|
10
|
-
end.should raise_error(StageManager::NoStagesSpecifiedError)
|
9
|
+
AutoTagger::StageManager.new(value)
|
10
|
+
end.should raise_error(AutoTagger::StageManager::NoStagesSpecifiedError)
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
15
|
describe "#previous_stage" do
|
16
16
|
it "returns the previous stage as a string if there is more than one stage, and there is a current stage" do
|
17
|
-
StageManager.new([:foo, :bar]).previous_stage(:bar).should == "foo"
|
17
|
+
AutoTagger::StageManager.new([:foo, :bar]).previous_stage(:bar).should == "foo"
|
18
18
|
end
|
19
19
|
|
20
20
|
it "returns nil if there is no previous stage" do
|
21
|
-
StageManager.new([:bar]).previous_stage(:bar).should be_nil
|
21
|
+
AutoTagger::StageManager.new([:bar]).previous_stage(:bar).should be_nil
|
22
22
|
end
|
23
23
|
|
24
24
|
it "deals with mixed strings and symbols" do
|
25
|
-
StageManager.new([:"foo-bar", "baz"]).previous_stage(:baz).should == "foo-bar"
|
25
|
+
AutoTagger::StageManager.new([:"foo-bar", "baz"]).previous_stage(:baz).should == "foo-bar"
|
26
26
|
end
|
27
27
|
|
28
28
|
it "returns nil if there is no current stage" do
|
29
|
-
StageManager.new([:bar]).previous_stage(nil).should be_nil
|
29
|
+
AutoTagger::StageManager.new([:bar]).previous_stage(nil).should be_nil
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../spec_helper'
|
2
2
|
|
3
|
-
describe Tag do
|
3
|
+
describe AutoTagger::Tag do
|
4
4
|
|
5
5
|
before(:each) do
|
6
6
|
@repository = Object.new
|
@@ -8,25 +8,25 @@ describe Tag do
|
|
8
8
|
|
9
9
|
describe ".new" do
|
10
10
|
it "sets the repository" do
|
11
|
-
Tag.new(@repository).repository.should == @repository
|
11
|
+
AutoTagger::Tag.new(@repository).repository.should == @repository
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
15
|
describe "#find_all" do
|
16
16
|
it "returns an array of tags" do
|
17
17
|
mock(@repository).run("git tag") { "ci_01\nci_02" }
|
18
|
-
Tag.new(@repository).find_all.should == ["ci_01", "ci_02"]
|
18
|
+
AutoTagger::Tag.new(@repository).find_all.should == ["ci_01", "ci_02"]
|
19
19
|
end
|
20
20
|
|
21
21
|
it "returns an empty array if there are none" do
|
22
22
|
mock(@repository).run("git tag") { "" }
|
23
|
-
Tag.new(@repository).find_all.should be_empty
|
23
|
+
AutoTagger::Tag.new(@repository).find_all.should be_empty
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
27
|
describe "#latest_from" do
|
28
28
|
before do
|
29
|
-
@tag = Tag.new(@repository)
|
29
|
+
@tag = AutoTagger::Tag.new(@repository)
|
30
30
|
mock(@tag).find_all { ["ci/01", "ci/02"] }
|
31
31
|
end
|
32
32
|
|
@@ -42,14 +42,14 @@ describe Tag do
|
|
42
42
|
describe "#fetch_tags" do
|
43
43
|
it "sends the correct command" do
|
44
44
|
mock(@repository).run!("git fetch origin --tags")
|
45
|
-
Tag.new(@repository).fetch
|
45
|
+
AutoTagger::Tag.new(@repository).fetch
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
49
|
describe "#push" do
|
50
50
|
it "sends the correct command" do
|
51
51
|
mock(@repository).run!("git push origin --tags")
|
52
|
-
Tag.new(@repository).push
|
52
|
+
AutoTagger::Tag.new(@repository).push
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
@@ -59,7 +59,7 @@ describe Tag do
|
|
59
59
|
mock(Time).now.once {time}
|
60
60
|
tag_name = "ci/#{time.utc.strftime('%Y%m%d%H%M%S')}"
|
61
61
|
mock(@repository).run!("git tag #{tag_name}")
|
62
|
-
Tag.new(@repository).create("ci").should == tag_name
|
62
|
+
AutoTagger::Tag.new(@repository).create("ci").should == tag_name
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
metadata
CHANGED
@@ -1,28 +1,42 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: auto_tagger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 2
|
9
|
+
version: 0.1.2
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Jeff Dean
|
8
13
|
- Brian Takita
|
14
|
+
- Mike Grafton
|
15
|
+
- Bruce Krysiak
|
16
|
+
- Pat Nakajima
|
17
|
+
- Jay Zeschin
|
18
|
+
- Mike Barinek
|
9
19
|
autorequire:
|
10
20
|
bindir: bin
|
11
21
|
cert_chain: []
|
12
22
|
|
13
|
-
date:
|
23
|
+
date: 2010-04-25 00:00:00 -04:00
|
14
24
|
default_executable: autotag
|
15
25
|
dependencies:
|
16
26
|
- !ruby/object:Gem::Dependency
|
17
27
|
name: capistrano
|
18
|
-
|
19
|
-
|
20
|
-
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
prerelease: false
|
29
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
21
30
|
requirements:
|
22
31
|
- - ">="
|
23
32
|
- !ruby/object:Gem::Version
|
33
|
+
segments:
|
34
|
+
- 2
|
35
|
+
- 5
|
36
|
+
- 3
|
24
37
|
version: 2.5.3
|
25
|
-
|
38
|
+
type: :runtime
|
39
|
+
version_requirements: *id001
|
26
40
|
description:
|
27
41
|
email: jeff@zilkey.com
|
28
42
|
executables:
|
@@ -32,10 +46,12 @@ extensions: []
|
|
32
46
|
extra_rdoc_files:
|
33
47
|
- README.md
|
34
48
|
files:
|
49
|
+
- .document
|
35
50
|
- .gitignore
|
36
51
|
- CHANGELOG
|
37
52
|
- MIT-LICENSE
|
38
53
|
- README.md
|
54
|
+
- Rakefile
|
39
55
|
- VERSION
|
40
56
|
- auto_tagger.gemspec
|
41
57
|
- bin/autotag
|
@@ -50,14 +66,14 @@ files:
|
|
50
66
|
- features/templates/stage.erb
|
51
67
|
- geminstaller.yml
|
52
68
|
- lib/auto_tagger.rb
|
53
|
-
- lib/auto_tagger/
|
69
|
+
- lib/auto_tagger/base.rb
|
54
70
|
- lib/auto_tagger/capistrano_helper.rb
|
55
71
|
- lib/auto_tagger/commander.rb
|
72
|
+
- lib/auto_tagger/recipes.rb
|
56
73
|
- lib/auto_tagger/repository.rb
|
57
74
|
- lib/auto_tagger/stage_manager.rb
|
58
75
|
- lib/auto_tagger/tag.rb
|
59
|
-
-
|
60
|
-
- spec/auto_tagger/auto_tagger_spec.rb
|
76
|
+
- spec/auto_tagger/base_spec.rb
|
61
77
|
- spec/auto_tagger/capistrano_helper_spec.rb
|
62
78
|
- spec/auto_tagger/commander_spec.rb
|
63
79
|
- spec/auto_tagger/repository_spec.rb
|
@@ -73,28 +89,29 @@ rdoc_options:
|
|
73
89
|
- --charset=UTF-8
|
74
90
|
require_paths:
|
75
91
|
- lib
|
76
|
-
- recipes
|
77
92
|
required_ruby_version: !ruby/object:Gem::Requirement
|
78
93
|
requirements:
|
79
94
|
- - ">="
|
80
95
|
- !ruby/object:Gem::Version
|
96
|
+
segments:
|
97
|
+
- 0
|
81
98
|
version: "0"
|
82
|
-
version:
|
83
99
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
100
|
requirements:
|
85
101
|
- - ">="
|
86
102
|
- !ruby/object:Gem::Version
|
103
|
+
segments:
|
104
|
+
- 0
|
87
105
|
version: "0"
|
88
|
-
version:
|
89
106
|
requirements: []
|
90
107
|
|
91
108
|
rubyforge_project:
|
92
|
-
rubygems_version: 1.3.
|
109
|
+
rubygems_version: 1.3.6
|
93
110
|
signing_key:
|
94
111
|
specification_version: 3
|
95
112
|
summary: Helps you automatically create tags for each stage in a multi-stage deploment and deploy from the latest tag from the previous environment
|
96
113
|
test_files:
|
97
|
-
- spec/auto_tagger/
|
114
|
+
- spec/auto_tagger/base_spec.rb
|
98
115
|
- spec/auto_tagger/capistrano_helper_spec.rb
|
99
116
|
- spec/auto_tagger/commander_spec.rb
|
100
117
|
- spec/auto_tagger/repository_spec.rb
|
@@ -1,26 +0,0 @@
|
|
1
|
-
class AutoTagger
|
2
|
-
|
3
|
-
class EnvironmentCannotBeBlankError < StandardError; end
|
4
|
-
|
5
|
-
attr_reader :stage, :repository, :working_directory
|
6
|
-
|
7
|
-
def initialize(stage, path = nil)
|
8
|
-
raise EnvironmentCannotBeBlankError if stage.to_s.strip == ""
|
9
|
-
@working_directory = File.expand_path(path ||= Dir.pwd)
|
10
|
-
@repository = Repository.new(@working_directory)
|
11
|
-
@stage = stage
|
12
|
-
end
|
13
|
-
|
14
|
-
def create_tag(commit = nil)
|
15
|
-
repository.tags.fetch
|
16
|
-
new_tag = repository.tags.create(stage, commit)
|
17
|
-
repository.tags.push
|
18
|
-
new_tag
|
19
|
-
end
|
20
|
-
|
21
|
-
def latest_tag
|
22
|
-
repository.tags.fetch
|
23
|
-
repository.tags.latest_from(stage)
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
@@ -1,85 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
-
|
3
|
-
describe AutoTagger do
|
4
|
-
before(:each) do
|
5
|
-
stub(Dir).pwd { File.join(File.dirname(__FILE__), '..', '..') }
|
6
|
-
end
|
7
|
-
|
8
|
-
describe ".new" do
|
9
|
-
it "blows up if you don't pass an stage" do
|
10
|
-
proc do
|
11
|
-
AutoTagger.new(nil)
|
12
|
-
end.should raise_error(AutoTagger::EnvironmentCannotBeBlankError)
|
13
|
-
end
|
14
|
-
|
15
|
-
it "sets the stage when it's passed" do
|
16
|
-
AutoTagger.new("ci").stage.should == "ci"
|
17
|
-
end
|
18
|
-
|
19
|
-
it "sets the path to Dir.pwd when nil" do
|
20
|
-
mock(Dir).pwd { "/foo" }
|
21
|
-
mock(Repository).new("/foo")
|
22
|
-
AutoTagger.new("ci")
|
23
|
-
end
|
24
|
-
|
25
|
-
it "expands the path when the path is passed" do
|
26
|
-
mock(Repository).new(File.expand_path("."))
|
27
|
-
AutoTagger.new("ci", ".")
|
28
|
-
end
|
29
|
-
|
30
|
-
it "exposes the working directory" do
|
31
|
-
mock(Repository).new(File.expand_path("."))
|
32
|
-
AutoTagger.new("ci", ".").working_directory.should == File.expand_path(".")
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
describe "#create_tag" do
|
37
|
-
it "generates the correct commands" do
|
38
|
-
time = Time.local(2001,1,1)
|
39
|
-
mock(Time).now.once {time}
|
40
|
-
timestamp = time.utc.strftime('%Y%m%d%H%M%S')
|
41
|
-
mock(File).exists?(anything).twice { true }
|
42
|
-
|
43
|
-
mock(Commander).execute!("/foo", "git fetch origin --tags") {true}
|
44
|
-
mock(Commander).execute!("/foo", "git tag ci/#{timestamp}") {true}
|
45
|
-
mock(Commander).execute!("/foo", "git push origin --tags") {true}
|
46
|
-
|
47
|
-
AutoTagger.new("ci", "/foo").create_tag
|
48
|
-
end
|
49
|
-
|
50
|
-
it "allows you to base it off an existing tag or commit" do
|
51
|
-
time = Time.local(2001,1,1)
|
52
|
-
mock(Time).now.once {time}
|
53
|
-
timestamp = time.utc.strftime('%Y%m%d%H%M%S')
|
54
|
-
mock(File).exists?(anything).twice { true }
|
55
|
-
|
56
|
-
mock(Commander).execute!("/foo", "git fetch origin --tags") {true}
|
57
|
-
mock(Commander).execute!("/foo", "git tag ci/#{timestamp} guid") {true}
|
58
|
-
mock(Commander).execute!("/foo", "git push origin --tags") {true}
|
59
|
-
|
60
|
-
AutoTagger.new("ci", "/foo").create_tag("guid")
|
61
|
-
end
|
62
|
-
|
63
|
-
it "returns the tag that was created" do
|
64
|
-
time = Time.local(2001,1,1)
|
65
|
-
mock(Time).now.once {time}
|
66
|
-
timestamp = time.utc.strftime('%Y%m%d%H%M%S')
|
67
|
-
mock(File).exists?(anything).twice { true }
|
68
|
-
mock(Commander).execute!(anything, anything).times(any_times) {true}
|
69
|
-
|
70
|
-
AutoTagger.new("ci", "/foo").create_tag.should == "ci/#{timestamp}"
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
describe "#latest_tag" do
|
75
|
-
it "generates the correct commands" do
|
76
|
-
mock(File).exists?(anything).twice { true }
|
77
|
-
|
78
|
-
mock(Commander).execute!("/foo", "git fetch origin --tags") {true}
|
79
|
-
mock(Commander).execute("/foo", "git tag") { "ci_01" }
|
80
|
-
|
81
|
-
AutoTagger.new("ci", "/foo").latest_tag
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
end
|