forklift_etl 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +10 -0
  3. data/.rbenv-version +1 -0
  4. data/.travis.yml +10 -0
  5. data/Gemfile +10 -0
  6. data/Gemfile.lock +74 -0
  7. data/Rakefile +13 -0
  8. data/bin/forklift +61 -0
  9. data/doc/EmailSuffix.html +228 -0
  10. data/doc/Forklift.html +187 -0
  11. data/doc/Forklift/Base.html +167 -0
  12. data/doc/Forklift/Base/Connection.html +590 -0
  13. data/doc/Forklift/Base/Logger.html +453 -0
  14. data/doc/Forklift/Base/Mailer.html +399 -0
  15. data/doc/Forklift/Base/Mailer/ERBBinding.html +256 -0
  16. data/doc/Forklift/Base/Pid.html +489 -0
  17. data/doc/Forklift/Base/Utils.html +252 -0
  18. data/doc/Forklift/Connection.html +164 -0
  19. data/doc/Forklift/Connection/Elasticsearch.html +419 -0
  20. data/doc/Forklift/Connection/Mysql.html +939 -0
  21. data/doc/Forklift/Patterns.html +164 -0
  22. data/doc/Forklift/Patterns/Elasticsearch.html +169 -0
  23. data/doc/Forklift/Patterns/Mysql.html +402 -0
  24. data/doc/Forklift/Plan.html +704 -0
  25. data/doc/Gemfile.html +132 -0
  26. data/doc/Object.html +326 -0
  27. data/doc/Rakefile.html +138 -0
  28. data/doc/SpecClient.html +291 -0
  29. data/doc/SpecPlan.html +253 -0
  30. data/doc/SpecSeeds.html +303 -0
  31. data/doc/created.rid +35 -0
  32. data/doc/example/Gemfile.html +129 -0
  33. data/doc/images/add.png +0 -0
  34. data/doc/images/brick.png +0 -0
  35. data/doc/images/brick_link.png +0 -0
  36. data/doc/images/bug.png +0 -0
  37. data/doc/images/bullet_black.png +0 -0
  38. data/doc/images/bullet_toggle_minus.png +0 -0
  39. data/doc/images/bullet_toggle_plus.png +0 -0
  40. data/doc/images/date.png +0 -0
  41. data/doc/images/delete.png +0 -0
  42. data/doc/images/find.png +0 -0
  43. data/doc/images/loadingAnimation.gif +0 -0
  44. data/doc/images/macFFBgHack.png +0 -0
  45. data/doc/images/package.png +0 -0
  46. data/doc/images/page_green.png +0 -0
  47. data/doc/images/page_white_text.png +0 -0
  48. data/doc/images/page_white_width.png +0 -0
  49. data/doc/images/plugin.png +0 -0
  50. data/doc/images/ruby.png +0 -0
  51. data/doc/images/tag_blue.png +0 -0
  52. data/doc/images/tag_green.png +0 -0
  53. data/doc/images/transparent.png +0 -0
  54. data/doc/images/wrench.png +0 -0
  55. data/doc/images/wrench_orange.png +0 -0
  56. data/doc/images/zoom.png +0 -0
  57. data/doc/index.html +122 -0
  58. data/doc/js/darkfish.js +155 -0
  59. data/doc/js/jquery.js +18 -0
  60. data/doc/js/navigation.js +142 -0
  61. data/doc/js/search.js +94 -0
  62. data/doc/js/search_index.js +1 -0
  63. data/doc/js/searcher.js +228 -0
  64. data/doc/rdoc.css +543 -0
  65. data/doc/table_of_contents.html +309 -0
  66. data/example/Gemfile +3 -0
  67. data/example/Gemfile.lock +55 -0
  68. data/example/config/connections/elasticsearch/source.yml +1 -0
  69. data/example/config/connections/mysql/destination.yml +6 -0
  70. data/example/config/connections/mysql/source.yml +6 -0
  71. data/example/config/email.yml +18 -0
  72. data/example/plan.rb +87 -0
  73. data/example/template/email.erb +6 -0
  74. data/example/transformations/cleanup.sql +1 -0
  75. data/example/transformations/combined_name.sql +7 -0
  76. data/example/transformations/email_suffix.rb +20 -0
  77. data/forklift.jpg +0 -0
  78. data/forklift_etl.gemspec +28 -0
  79. data/lib/forklift/base/connection.rb +72 -0
  80. data/lib/forklift/base/logger.rb +49 -0
  81. data/lib/forklift/base/mailer.rb +83 -0
  82. data/lib/forklift/base/pid.rb +55 -0
  83. data/lib/forklift/base/utils.rb +23 -0
  84. data/lib/forklift/forklift.rb +19 -0
  85. data/lib/forklift/patterns/elasticsearch_patterns.rb +7 -0
  86. data/lib/forklift/patterns/mysql_patterns.rb +87 -0
  87. data/lib/forklift/plan.rb +138 -0
  88. data/lib/forklift/transports/elasticsearch.rb +75 -0
  89. data/lib/forklift/transports/mysql.rb +241 -0
  90. data/lib/forklift/version.rb +3 -0
  91. data/readme.md +410 -0
  92. data/spec/config/connections/elasticsearch/forklift_test.yml +1 -0
  93. data/spec/config/connections/mysql/forklift_test_destination.yml +6 -0
  94. data/spec/config/connections/mysql/forklift_test_source_a.yml +6 -0
  95. data/spec/config/connections/mysql/forklift_test_source_b.yml +6 -0
  96. data/spec/config/connections/mysql/forklift_test_working.yml +6 -0
  97. data/spec/config/email.yml +4 -0
  98. data/spec/integration/basic_spec.rb +29 -0
  99. data/spec/integration/elasticsearch_patterns_spec.rb +5 -0
  100. data/spec/integration/elasticsearch_spec.rb +95 -0
  101. data/spec/integration/multi_transport_spec.rb +112 -0
  102. data/spec/integration/mysql_patterns_spec.rb +76 -0
  103. data/spec/integration/mysql_spec.rb +138 -0
  104. data/spec/spec_helper.rb +30 -0
  105. data/spec/support/dumps/elasticsearch/forklift_test.json +7 -0
  106. data/spec/support/dumps/mysql/forklift_test_source_a.sql +79 -0
  107. data/spec/support/dumps/mysql/forklift_test_source_b.sql +23 -0
  108. data/spec/support/spec_client.rb +30 -0
  109. data/spec/support/spec_plan.rb +15 -0
  110. data/spec/support/spec_seeds.rb +69 -0
  111. data/spec/template/spec_email_template.erb +4 -0
  112. data/spec/unit/connection/mysql_spec.rb +102 -0
  113. data/spec/unit/misc/email_spec.rb +37 -0
  114. data/spec/unit/misc/pid_spec.rb +25 -0
  115. data/spec/unit/misc/step_spec.rb +53 -0
  116. data/template/destination.yml +6 -0
  117. data/template/email.erb +1 -0
  118. data/template/email.yml +18 -0
  119. data/template/plan.rb +10 -0
  120. data/template/source.yml +6 -0
  121. metadata +289 -0
@@ -0,0 +1,30 @@
1
+ #############
2
+ ## WARNING ##
3
+ #############
4
+
5
+ # THIS TEST SUITE IS VERY MEAN TO MYSQL AND ELASTICSEARCH
6
+ # IT *WILL* DELETE ANY CONTENT IN THE TEST DBs
7
+
8
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
9
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
10
+ APP_DIR ||= File.expand_path('../../', __FILE__)
11
+
12
+ require 'forklift/forklift'
13
+ require 'awesome_print'
14
+ require 'rspec'
15
+ require 'fileutils'
16
+
17
+ ENV["FORKLIFT_RUN_ALL_STEPS"] = 'true'
18
+
19
+ Dir["#{APP_DIR}/spec/support/**/*.rb"].each {|f| require f}
20
+
21
+ RSpec.configure do |config|
22
+
23
+ config.before(:all) do
24
+ piddir = "#{File.dirname(__FILE__)}/pid"
25
+ FileUtils.rmdir(piddir) if File.exists?(piddir)
26
+ SpecSeeds.setup_mysql
27
+ SpecSeeds.setup_elasticsearch
28
+ end
29
+
30
+ end
@@ -0,0 +1,7 @@
1
+ [
2
+ {"id": 1, "user_id": 1, "product_id": 1, "viewed_at": 1396552251},
3
+ {"id": 2, "user_id": 1, "product_id": 2, "viewed_at": 1396552252},
4
+ {"id": 3, "user_id": 2, "product_id": 5, "viewed_at": 1396552253},
5
+ {"id": 4, "user_id": 2, "product_id": 5, "viewed_at": 1396552254},
6
+ {"id": 5, "user_id": 2, "product_id": 5, "viewed_at": 1396552255}
7
+ ]
@@ -0,0 +1,79 @@
1
+ # Dump of table products
2
+ # ------------------------------------------------------------
3
+
4
+ DROP TABLE IF EXISTS `products`;
5
+
6
+ CREATE TABLE `products` (
7
+ `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
8
+ `name` varchar(255) NOT NULL DEFAULT '',
9
+ `inventory` int(11) DEFAULT NULL,
10
+ `created_at` datetime NOT NULL,
11
+ `updated_at` datetime NOT NULL,
12
+ PRIMARY KEY (`id`)
13
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
14
+
15
+ LOCK TABLES `products` WRITE;
16
+
17
+ INSERT INTO `products` (`id`, `name`, `inventory`, `created_at`, `updated_at`)
18
+ VALUES
19
+ (1,'car',10,'2014-04-03 11:45:51','2014-04-03 11:45:51'),
20
+ (2,'boat',3,'2014-04-03 11:45:52','2014-04-03 11:45:52'),
21
+ (3,'bus',5,'2014-04-03 11:45:54','2014-04-03 11:45:54'),
22
+ (4,'motorcycle',23,'2014-04-03 11:45:56','2014-04-03 11:45:56'),
23
+ (5,'hang_glider',2,'2014-04-03 11:46:19','2014-04-03 11:46:19');
24
+
25
+ UNLOCK TABLES;
26
+
27
+
28
+ # Dump of table sales
29
+ # ------------------------------------------------------------
30
+
31
+ DROP TABLE IF EXISTS `sales`;
32
+
33
+ CREATE TABLE `sales` (
34
+ `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
35
+ `user_id` int(11) NOT NULL,
36
+ `product_id` int(11) NOT NULL,
37
+ `timestamp` datetime NOT NULL,
38
+ PRIMARY KEY (`id`)
39
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
40
+
41
+ LOCK TABLES `sales` WRITE;
42
+
43
+ INSERT INTO `sales` (`id`, `user_id`, `product_id`, `timestamp`)
44
+ VALUES
45
+ (1,1,1,'2014-04-03 11:47:11'),
46
+ (2,1,2,'2014-04-03 11:47:11'),
47
+ (3,4,5,'2014-04-03 11:47:12'),
48
+ (4,4,4,'2014-04-03 11:47:25'),
49
+ (5,5,5,'2014-04-03 11:47:26');
50
+
51
+ UNLOCK TABLES;
52
+
53
+
54
+ # Dump of table users
55
+ # ------------------------------------------------------------
56
+
57
+ DROP TABLE IF EXISTS `users`;
58
+
59
+ CREATE TABLE `users` (
60
+ `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
61
+ `email` varchar(255) NOT NULL DEFAULT '',
62
+ `first_name` varchar(255) NOT NULL DEFAULT '',
63
+ `last_name` varchar(255) NOT NULL DEFAULT '',
64
+ `created_at` datetime NOT NULL,
65
+ `updated_at` datetime NOT NULL,
66
+ PRIMARY KEY (`id`)
67
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
68
+
69
+ LOCK TABLES `users` WRITE;
70
+
71
+ INSERT INTO `users` (`id`, `email`, `first_name`, `last_name`, `created_at`, `updated_at`)
72
+ VALUES
73
+ (1,'evan@example.com','Evan','T','2014-04-03 11:40:12','2014-04-03 11:39:28'),
74
+ (2,'pablo@example.com','Pablo ','J','2014-04-03 11:41:08','2014-04-03 11:41:08'),
75
+ (3,'kevin@example.com','Kevin','B','2014-04-03 11:41:10','2014-04-03 11:41:10'),
76
+ (4,'brian@example.com','Brian','L','2014-04-03 11:41:12','2014-04-03 11:41:12'),
77
+ (5,'aaront@example.com','Aaron','B','2014-04-03 11:41:13','2014-04-03 11:41:13');
78
+
79
+ UNLOCK TABLES;
@@ -0,0 +1,23 @@
1
+ # Dump of table admin_notes
2
+ # ------------------------------------------------------------
3
+
4
+ DROP TABLE IF EXISTS `admin_notes`;
5
+
6
+ CREATE TABLE `admin_notes` (
7
+ `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
8
+ `user_id` int(11) NOT NULL,
9
+ `note` text NOT NULL,
10
+ `created_at` datetime NOT NULL,
11
+ `updated_at` datetime NOT NULL,
12
+ PRIMARY KEY (`id`)
13
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
14
+
15
+ LOCK TABLES `admin_notes` WRITE;
16
+
17
+ INSERT INTO `admin_notes` (`id`, `user_id`, `note`, `created_at`, `updated_at`)
18
+ VALUES
19
+ (1,1,'User 1 called customer support\n','2014-04-03 11:50:25','2014-04-03 11:50:25'),
20
+ (2,2,'User 2 called customer support','2014-04-03 11:50:26','2014-04-03 11:50:26'),
21
+ (3,5,'User 5 returned the purchase','2014-04-03 11:50:28','2014-04-03 11:50:28');
22
+
23
+ UNLOCK TABLES;
@@ -0,0 +1,30 @@
1
+ require 'yaml'
2
+ require 'erb'
3
+
4
+ class SpecClient
5
+
6
+ def self.load_config(file)
7
+ YAML.load(ERB.new(File.read(file)).result)
8
+ end
9
+
10
+ def self.mysql(name)
11
+ file = File.join(File.dirname(__FILE__), '..', 'config', 'connections', 'mysql', "#{name}.yml")
12
+ config = self.load_config(file)
13
+ db = config[:database]
14
+ config.delete(:database)
15
+ connection = ::Mysql2::Client.new(config)
16
+ begin
17
+ connection.query("use `#{db}`")
18
+ rescue Exception => e
19
+ puts "#{e} => will create new databse #{db}"
20
+ end
21
+ connection
22
+ end
23
+
24
+ def self.elasticsearch(name)
25
+ file = File.join(File.dirname(__FILE__), '..', 'config', 'connections', 'elasticsearch', "#{name}.yml")
26
+ config = self.load_config(file)
27
+ ::Elasticsearch::Client.new(config)
28
+ end
29
+
30
+ end
@@ -0,0 +1,15 @@
1
+ class SpecPlan
2
+ def self.config
3
+ return {
4
+ :project_root => File.join(Dir.pwd, 'spec'),
5
+ :logger => {
6
+ :stdout => false,
7
+ :debug => false,
8
+ },
9
+ }
10
+ end
11
+
12
+ def self.new
13
+ return Forklift::Plan.new(self.config)
14
+ end
15
+ end
@@ -0,0 +1,69 @@
1
+ require 'json'
2
+
3
+ class SpecSeeds
4
+
5
+ def self.setup_mysql
6
+ mysql_connections = []
7
+ mysql_databases = []
8
+
9
+ files = Dir["#{File.dirname(__FILE__)}/../config/connections/mysql/*.yml"]
10
+ files.each do |f|
11
+ name = f.split('/').last.gsub('.yml','')
12
+ mysql_connections << ::SpecClient.mysql(name)
13
+ mysql_databases << name
14
+ end
15
+
16
+ i = 0
17
+ while i < mysql_connections.count
18
+ conn = mysql_connections[i]
19
+ db = mysql_databases[i]
20
+ seed = File.join(File.dirname(__FILE__), '..', 'support', 'dumps', 'mysql', "#{db}.sql")
21
+ conn.query("drop database if exists `#{db}`")
22
+ conn.query("create database `#{db}`")
23
+ conn.query("use `#{db}`")
24
+ if File.exists? seed
25
+ lines = File.read(seed).split(";")
26
+ lines.each do |line|
27
+ conn.query(line) if line[0] != "#"
28
+ end
29
+ end
30
+
31
+ i = i + 1
32
+ end
33
+ end
34
+
35
+ def self.setup_elasticsearch
36
+ elasticsearch_connections = []
37
+ elasticsearch_databases = []
38
+
39
+ files = Dir["#{File.dirname(__FILE__)}/../config/connections/elasticsearch/*.yml"]
40
+ files.each do |f|
41
+ name = f.split('/').last.gsub('.yml','')
42
+ elasticsearch_connections << ::SpecClient.elasticsearch(name)
43
+ elasticsearch_databases << name
44
+ end
45
+
46
+ i = 0
47
+ while i < elasticsearch_connections.count
48
+ conn = elasticsearch_connections[i]
49
+ index = elasticsearch_databases[i]
50
+ seed = File.join(File.dirname(__FILE__), '..', 'support', 'dumps', 'elasticsearch', "#{index}.json")
51
+ conn.indices.delete({ :index => index }) if conn.indices.exists({ :index => index })
52
+ if File.exists? seed
53
+ lines = JSON.parse(File.read(seed))
54
+ lines.each do |line|
55
+ object = {
56
+ :index => index,
57
+ :body => line,
58
+ :type => 'forklift',
59
+ :id => line['id']
60
+ }
61
+ conn.index object # assumes ES is setup to allow index creation on write
62
+ end
63
+ conn.indices.refresh({ :index => index })
64
+ end
65
+ i = i + 1
66
+ end
67
+ end
68
+
69
+ end
@@ -0,0 +1,4 @@
1
+ ## Your forklift email ##
2
+
3
+ Total Users: <%= @total_users_count %>
4
+ New Users: <%= @new_users_count %>
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+ require 'zlib'
3
+
4
+ describe Forklift::Connection::Mysql do
5
+
6
+ describe "read/write utils" do
7
+ before(:each) do
8
+ SpecSeeds.setup_mysql
9
+ end
10
+
11
+ it "can read a list of tables" do
12
+ plan = SpecPlan.new
13
+ plan.do! {
14
+ source = plan.connections[:mysql][:forklift_test_source_a]
15
+ expect(source.tables).to include 'users'
16
+ expect(source.tables).to include 'products'
17
+ expect(source.tables).to include 'sales'
18
+ }
19
+ end
20
+
21
+ it "can delte a table" do
22
+ plan = SpecPlan.new
23
+ table = "users"
24
+ plan.do! {
25
+ source = plan.connections[:mysql][:forklift_test_source_a]
26
+ expect(source.tables).to include 'users'
27
+ source.drop! table
28
+ expect(source.tables).to_not include 'users'
29
+ }
30
+ end
31
+
32
+ it "can count the rows in a table" do
33
+ plan = SpecPlan.new
34
+ table = "users"
35
+ plan.do! {
36
+ source = plan.connections[:mysql][:forklift_test_source_a]
37
+ expect(source.count(table)).to eql 5
38
+ }
39
+ end
40
+
41
+ it "can truncate a table (both with and without !)" do
42
+ plan = SpecPlan.new
43
+ table = "users"
44
+ plan.do! {
45
+ source = plan.connections[:mysql][:forklift_test_source_a]
46
+ expect(source.count(table)).to eql 5
47
+ source.truncate! table
48
+ expect(source.count(table)).to eql 0
49
+ expect { source.truncate(table) }.to_not raise_error
50
+ }
51
+ end
52
+
53
+ it 'trunacte! will raise if the table does not exist' do
54
+ plan = SpecPlan.new
55
+ table = "other_table"
56
+ plan.do! {
57
+ source = plan.connections[:mysql][:forklift_test_source_a]
58
+ expect { source.truncate!(table) }.to raise_error(/Table 'forklift_test_source_a.other_table' doesn't exist/)
59
+ }
60
+ end
61
+
62
+ it "can get the columns of a table" do
63
+ plan = SpecPlan.new
64
+ table = "sales"
65
+ plan.do! {
66
+ source = plan.connections[:mysql][:forklift_test_source_a]
67
+ expect(source.columns(table)).to include 'id'
68
+ expect(source.columns(table)).to include 'user_id'
69
+ expect(source.columns(table)).to include 'product_id'
70
+ expect(source.columns(table)).to include 'timestamp'
71
+ }
72
+ end
73
+
74
+ it "can create a mysqldump" do
75
+ dump = "/tmp/destination.sql.gz"
76
+ plan = SpecPlan.new
77
+ plan.do! {
78
+ source = plan.connections[:mysql][:forklift_test_source_a]
79
+ source.dump(dump)
80
+ }
81
+
82
+ expect(File.exists?(dump)).to eql true
83
+ contents = Zlib::GzipReader.new(StringIO.new(File.read(dump))).read
84
+ expect(contents).to include "(1,'evan@example.com','Evan','T','2014-04-03 11:40:12','2014-04-03 11:39:28')"
85
+ end
86
+
87
+ end
88
+
89
+ describe "#safe_values" do
90
+ subject { described_class.new({}, {}) }
91
+
92
+ it "escapes one trailing backslash" do
93
+ values = ["foo\\"]
94
+ subject.send(:safe_values, values).should == "\"foo\\\\\""
95
+ end
96
+
97
+ it "escapes two trailing backslashes" do
98
+ values = ["foo\\\\"]
99
+ subject.send(:safe_values, values).should == "\"foo\\\\\\\\\""
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+ require "email_spec"
3
+
4
+ describe 'misc forklift core' do
5
+ describe 'email' do
6
+ include EmailSpec::Helpers
7
+ include EmailSpec::Matchers
8
+
9
+ it "can send mail with an email template" do
10
+ plan = SpecPlan.new
11
+ plan.do! {
12
+ email_args = {
13
+ :to => "YOU@FAKE.com",
14
+ :from => "Forklift",
15
+ :subject => "Forklift has moved your database",
16
+ }
17
+ email_variables = {
18
+ :total_users_count => 10,
19
+ :new_users_count => 5,
20
+ }
21
+ email_template = "#{File.dirname(__FILE__)}/../../template/spec_email_template.erb"
22
+ @email = plan.mailer.send_template(email_args, email_template, email_variables).first
23
+ }
24
+
25
+ @email.should deliver_to("YOU@FAKE.com")
26
+ @email.should have_subject(/Forklift has moved your database/)
27
+ @email.should have_body_text(/Your forklift email/) # base
28
+ @email.should have_body_text(/Total Users: 10/) # template
29
+ @email.should have_body_text(/New Users: 5/) # template
30
+ end
31
+
32
+ it "can send mail with an attachment" do
33
+ pending("how to test email attachments?")
34
+ end
35
+ end
36
+
37
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'misc forklift core' do
4
+
5
+ describe 'pidfile' do
6
+ it "can create a pidfile and will remove it when the plan is over" do
7
+ plan = SpecPlan.new
8
+ pid = "#{File.dirname(__FILE__)}/../../pid/pidfile"
9
+ expect(File.exists?(pid)).to eql false
10
+ plan.do! {
11
+ expect(File.exists?(pid)).to eql true
12
+ expect(File.read(pid).to_i).to eql Process.pid
13
+ }
14
+ expect(File.exists?(pid)).to eql false
15
+ end
16
+
17
+ it "will not run with an existing pidfile" do
18
+ plan = SpecPlan.new
19
+ plan.pid.store!
20
+ expect { plan.do! }.to raise_error SystemExit
21
+ plan.pid.delete!
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'misc forklift core' do
4
+ describe 'steps' do
5
+
6
+ before(:each) do
7
+ ENV['FORKLIFT_RUN_ALL_STEPS'] = 'false'
8
+ end
9
+
10
+ after(:each) do
11
+ ENV['FORKLIFT_RUN_ALL_STEPS'] = 'true'
12
+ end
13
+
14
+ it "will run all steps with no extra ARGV" do
15
+ plan = SpecPlan.new
16
+ plan.stub(:argv){ ['/path/to/plan'] }
17
+ steps_run = []
18
+ plan.do! {
19
+ plan.step("a"){ steps_run << 'a' }
20
+ plan.step("b"){ steps_run << 'b' }
21
+ plan.step("c"){ steps_run << 'c' }
22
+ }
23
+ expect(steps_run).to include 'a'
24
+ expect(steps_run).to include 'b'
25
+ expect(steps_run).to include 'c'
26
+ end
27
+
28
+ it "will only run steps named within ARGV" do
29
+ plan = SpecPlan.new
30
+ plan.stub(:argv){ ['/path/to/plan', 'a','c'] }
31
+ steps_run = []
32
+ plan.do! {
33
+ plan.step("a"){ steps_run << 'a' }
34
+ plan.step("b"){ steps_run << 'b' }
35
+ plan.step("c"){ steps_run << 'c' }
36
+ }
37
+ expect(steps_run).to include 'a'
38
+ expect(steps_run).to_not include 'b'
39
+ expect(steps_run).to include 'c'
40
+ end
41
+
42
+ it "won't run on a badly defined step" do
43
+ plan = SpecPlan.new
44
+ plan.stub(:argv){ ['/path/to/plan', 'missing_step'] }
45
+ expect{
46
+ plan.do! {
47
+ plan.step("a"){ raise 'never should get here' }
48
+ }
49
+ }.to raise_error SystemExit
50
+ end
51
+ end
52
+
53
+ end