handshake_service 0.1.0 → 0.1.1

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
2
  SHA1:
3
- metadata.gz: 5b0c53862aa69276500c0eac25fc64bc5108065a
4
- data.tar.gz: aa31a03538a462fd7d917d25e8beca4ff779137e
3
+ metadata.gz: b6014221044bffc0d210e7aecf741aae989ab3f4
4
+ data.tar.gz: 4952eb9e23bd09eb0580c194a5d2300e5405b2e3
5
5
  SHA512:
6
- metadata.gz: 736a7c34be6c55f67551d5463efe994c70a69de1ba40bd36aae5cf635b905d936d3fa1212cff7582541512b33f6cb8feb81fb07b00b19bff1164c232703258ee
7
- data.tar.gz: 1d2b5048abd8a886f2a4d4955beebed6a936e068e24f6564bf7b1a010ef13c76fcf0dce0ca8b8ffeefba6776d5f71b44ae5b1e5cafe7c45dd81308a3821a5c2a
6
+ metadata.gz: 3b97a0224445c81ae9dbb49a28e408c34feea6b6b9b206ff74edc310049c34721f8541d7aee24909891daf5ef8a05384f08b88f3ab2f3e05a875dfb361957202
7
+ data.tar.gz: 4a107452724cdca291e87c1d51fdefad4636344a1188e4e112611ccc47265126dd7a3249a5bb5880d4f747e523aeddf03ab95812309250646158cc53bb8a6f9a
@@ -1,3 +1,3 @@
1
1
  module HandshakeService
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -0,0 +1,34 @@
1
+ # NOTE: only doing this in development as some production environments (Heroku)
2
+ # NOTE: are sensitive to local FS writes, and besides -- it's just not proper
3
+ # NOTE: to have a dev-mode tool do its thing in production.
4
+ if(Rails.env.development?)
5
+ task :set_annotation_options do
6
+ # You can override any of these by setting an environment variable of the
7
+ # same name.
8
+ Annotate.set_defaults({
9
+ 'position_in_routes' => "before",
10
+ 'position_in_class' => "before",
11
+ 'position_in_test' => "before",
12
+ 'position_in_fixture' => "before",
13
+ 'position_in_factory' => "before",
14
+ 'show_indexes' => "true",
15
+ 'simple_indexes' => "false",
16
+ 'model_dir' => "app/models",
17
+ 'include_version' => "false",
18
+ 'require' => "",
19
+ 'exclude_tests' => "false",
20
+ 'exclude_fixtures' => "false",
21
+ 'exclude_factories' => "false",
22
+ 'ignore_model_sub_dir' => "false",
23
+ 'skip_on_db_migrate' => "false",
24
+ 'format_bare' => "true",
25
+ 'format_rdoc' => "false",
26
+ 'format_markdown' => "false",
27
+ 'sort' => "false",
28
+ 'force' => "false",
29
+ 'trace' => "false",
30
+ })
31
+ end
32
+
33
+ Annotate.load_tasks
34
+ end
@@ -0,0 +1,327 @@
1
+ require 'librato/metrics'
2
+
3
+ # A collection of rake tasks to deploy applications to heroku. At the basic level, all that needs to be called
4
+ # in most cases is
5
+ #
6
+ # foreman run rake deploy:staging
7
+ #
8
+ # The foreman gem is used to include .env ENV variables, but if you have those defined elsewhere it can be excluded.
9
+ # Before deploying define the STAGING_APP_NAME ENV variables, etc.
10
+ #
11
+ # These rake tasks will automatically detect schema changes and deploy correctly based on that. To override
12
+ # use the 'rake deploy:staging:migrations' or 'rake deploy:staging:preboot' rake task options.
13
+ class RakeHerokuDeployer
14
+ def initialize app_env
15
+ @app_env = app_env
16
+ @app = ENV["#{app_env.to_s.upcase}_APP_NAME"]
17
+ @start_time = Time.now.to_i
18
+
19
+ if @app.blank?
20
+ puts "Please add #{app_env.to_s.upcase}_APP_NAME environment variable in order to deploy"
21
+ exit(1)
22
+ end
23
+ end
24
+
25
+ # Uses git to determine if there are any DB migrations to run
26
+ def auto_deploy
27
+ if schema_change_since_last_release?
28
+ puts "::::::: Schema Change Detected, Disabling Preboot :::::::::"
29
+ run_migrations
30
+ else
31
+ puts "::::::: No Schema Change, Preboot Enabled :::::::::"
32
+ deploy
33
+ end
34
+ end
35
+
36
+ def run_migrations
37
+ #start_deploy; turn_off_preboot; push; turn_app_off; backup; migrate; restart; run_data_migrations; turn_app_on; tag; stop_deploy;
38
+ start_deploy; turn_off_preboot; backup; push; migrate; restart; run_data_migrations; tag; stop_deploy;
39
+ end
40
+
41
+ def deploy
42
+ # turn_on_preboot; push; restart; tag;
43
+ start_deploy; turn_on_preboot; push; run_data_migrations; tag; stop_deploy;
44
+ #start_deploy; push; turn_app_off; run_data_migrations; turn_app_on; tag; stop_deploy;
45
+ end
46
+
47
+ def backup_deploy
48
+ backup; deploy;
49
+ end
50
+
51
+ def rollback
52
+ turn_app_off; push_previous; restart; turn_app_on;
53
+ end
54
+
55
+ private
56
+
57
+ # 1) Fetch remote heroku branch we are deploying to
58
+ # 2) Do a diff of our branch to the production one
59
+ # 3) See if any migrations were added
60
+ def schema_change_since_last_release?
61
+ remote_name = "#{@app}-deployer"
62
+ system("git remote add #{remote_name} git@heroku.com:#{@app}.git") # may already exist, don't error if so
63
+ exit(1) unless system("git fetch #{remote_name}")
64
+ diff = `git diff --name-only #{remote_name}/master`
65
+
66
+ if diff.blank? # If we get back an empty diff we either have an error or don't want to deploy anyways
67
+ puts 'No diff for deploying'
68
+ exit(0) # No need to fail, just exit. Also means nightly builds are green :).
69
+ end
70
+
71
+ exit(1) unless system("git remote remove #{remote_name}")
72
+ diff.include?("db/migrate/")
73
+ end
74
+
75
+ # Nice to see how long things run
76
+ def print_current_time
77
+ puts Time.now
78
+ end
79
+
80
+ def start_deploy
81
+ return unless ENV["NEPTUNE_API_KEY"].present?
82
+ puts 'Turning off the neptune API while deploy is happening...'
83
+ puts 'curl -X GET "https://www.neptune.io/api/v1/maintenance/<api_key>/on'
84
+ puts `curl -X GET 'https://www.neptune.io/api/v1/maintenance/#{ENV["NEPTUNE_API_KEY"]}/on'`
85
+ end
86
+
87
+ def stop_deploy
88
+ return unless ENV["NEPTUNE_API_KEY"].present?
89
+ puts 'Turning on the neptune API since deploy is finished...'
90
+ puts 'curl -X GET "https://www.neptune.io/api/v1/maintenance/<api_key>/off'
91
+ puts `curl -X GET 'https://www.neptune.io/api/v1/maintenance/#{ENV["NEPTUNE_API_KEY"]}/off'`
92
+ end
93
+
94
+ def turn_on_preboot
95
+ puts 'Turning on preboot...'
96
+ puts `heroku features:enable -a #{@app} preboot`
97
+ print_current_time
98
+ end
99
+
100
+ def turn_off_preboot
101
+ puts 'Turning off preboot...'
102
+ puts `heroku features:disable -a #{@app} preboot`
103
+ print_current_time
104
+ end
105
+
106
+ def push
107
+ current_branch = `git rev-parse --abbrev-ref HEAD`.chomp
108
+ branch_to_branch = (current_branch.length > 0) ? "#{current_branch}:master" : ""
109
+ puts 'Deploying site to Heroku ...'
110
+ puts "git push git@heroku.com:#{@app}.git #{branch_to_branch}"
111
+ puts `git push git@heroku.com:#{@app}.git #{branch_to_branch}`
112
+ print_current_time
113
+ end
114
+
115
+ def restart
116
+ puts 'Restarting app servers ...'
117
+ Bundler.with_clean_env { puts `heroku restart --app #{@app}` }
118
+ print_current_time
119
+ end
120
+
121
+ def tag
122
+ return unless @app_env == :production
123
+
124
+ release_name = "#{@app}_release-#{Time.now.utc.strftime("%Y%m%d%H%M%S")}"
125
+ puts "Tagging release as '#{release_name}'"
126
+ puts `git tag -a #{release_name} -m 'Tagged release'`
127
+ puts `git push --tags git@heroku.com:#{@app}.git`
128
+ print_current_time
129
+ end
130
+
131
+ def backup
132
+ puts 'Backing up the database...'
133
+ puts "heroku pgbackups:capture --expire --app #{@app}'"
134
+ puts `heroku pgbackups:capture --expire --app #{@app}`
135
+ print_current_time
136
+ end
137
+
138
+ def migrate
139
+ puts 'Running database migrations ...'
140
+ Bundler.with_clean_env { puts `heroku run 'bundle exec rake db:migrate LOG_LEVEL=info' --app #{@app}` }
141
+ print_current_time
142
+ end
143
+
144
+ def run_data_migrations
145
+ run_custom_command_cleanly('rake data:migrate', true)
146
+ end
147
+
148
+ def run_custom_command_cleanly(command, detached = false, log_level = 'info')
149
+ Bundler.with_clean_env { puts `heroku run#{detached ? ':detached' : ''} '#{command} LOG_LEVEL=#{log_level}' --app #{@app}` }
150
+ print_current_time
151
+ end
152
+
153
+ def turn_app_off
154
+ puts 'Putting the app into maintenance mode ...'
155
+ Bundler.with_clean_env { puts `heroku maintenance:on --app #{@app}` }
156
+ print_current_time
157
+ end
158
+
159
+ def turn_app_on
160
+ puts 'Taking the app out of maintenance mode ...'
161
+ Bundler.with_clean_env { puts `heroku maintenance:off --app #{@app}` }
162
+ print_current_time
163
+ end
164
+
165
+ def push_previous
166
+ prefix = "#{@app}_release-"
167
+ releases = `git tag`.split("\n").select { |t| t[0..prefix.length-1] == prefix }.sort
168
+ current_release = releases.last
169
+ previous_release = releases[-2] if releases.length >= 2
170
+ if previous_release
171
+ puts "Rolling back to '#{previous_release}' ..."
172
+
173
+ puts "Checking out '#{previous_release}' in a new branch on local git repo ..."
174
+ puts `git checkout #{previous_release}`
175
+ puts `git checkout -b #{previous_release}`
176
+
177
+ puts "Removing tagged version '#{previous_release}' (now transformed in branch) ..."
178
+ puts `git tag -d #{previous_release}`
179
+ puts `git push git@heroku.com:#{@app}.git :refs/tags/#{previous_release}`
180
+
181
+ puts "Pushing '#{previous_release}' to Heroku master ..."
182
+ puts `git push git@heroku.com:#{@app}.git +#{previous_release}:master --force`
183
+
184
+ puts "Deleting rollbacked release '#{current_release}' ..."
185
+ puts `git tag -d #{current_release}`
186
+ puts `git push git@heroku.com:#{@app}.git :refs/tags/#{current_release}`
187
+
188
+ puts "Retagging release '#{previous_release}' in case to repeat this process (other rollbacks)..."
189
+ puts `git tag -a #{previous_release} -m 'Tagged release'`
190
+ puts `git push --tags git@heroku.com:#{@app}.git`
191
+
192
+ puts "Turning local repo checked out on master ..."
193
+ puts `git checkout master`
194
+ puts 'All done!'
195
+ else
196
+ puts "No release tags found - can't roll back!"
197
+ puts releases
198
+ end
199
+ end
200
+ end
201
+
202
+ namespace :deploy do
203
+ namespace :staging do
204
+ task :migrations do
205
+ deployer = RakeHerokuDeployer.new(:staging)
206
+ deployer.run_migrations
207
+ end
208
+
209
+ task :backup_deploy do
210
+ deployer = RakeHerokuDeployer.new(:staging)
211
+ deployer.backup_deploy
212
+ end
213
+
214
+ task :rollback do
215
+ deployer = RakeHerokuDeployer.new(:staging)
216
+ deployer.rollback
217
+ end
218
+
219
+ task :preboot do
220
+ deployer = RakeHerokuDeployer.new(:staging)
221
+ deployer.deploy
222
+ end
223
+ end
224
+
225
+ task :staging do
226
+ deployer = RakeHerokuDeployer.new(:staging)
227
+ deployer.auto_deploy
228
+ end
229
+
230
+ namespace :demo do
231
+ task :migrations do
232
+ deployer = RakeHerokuDeployer.new(:demo)
233
+ deployer.run_migrations
234
+ end
235
+
236
+ task :backup_deploy do
237
+ deployer = RakeHerokuDeployer.new(:demo)
238
+ deployer.backup_deploy
239
+ end
240
+
241
+ task :rollback do
242
+ deployer = RakeHerokuDeployer.new(:demo)
243
+ deployer.rollback
244
+ end
245
+
246
+ task :preboot do
247
+ deployer = RakeHerokuDeployer.new(:demo)
248
+ deployer.deploy
249
+ end
250
+ end
251
+
252
+ task :demo do
253
+ deployer = RakeHerokuDeployer.new(:demo)
254
+ deployer.auto_deploy
255
+ end
256
+
257
+ namespace :production do
258
+ task :migrations do
259
+ deployer = RakeHerokuDeployer.new(:production)
260
+ deployer.run_migrations
261
+ end
262
+
263
+ task :backup_deploy do
264
+ deployer = RakeHerokuDeployer.new(:production)
265
+ deployer.backup_deploy
266
+ end
267
+
268
+ task :rollback do
269
+ deployer = RakeHerokuDeployer.new(:production)
270
+ deployer.rollback
271
+ end
272
+
273
+ task :preboot do
274
+ deployer = RakeHerokuDeployer.new(:production)
275
+ deployer.deploy
276
+ end
277
+ end
278
+
279
+ task :production do
280
+ deployer = RakeHerokuDeployer.new(:production)
281
+ deployer.auto_deploy
282
+ end
283
+
284
+ task :all do
285
+ deployer = RakeHerokuDeployer.new(:staging)
286
+ deployer2 = RakeHerokuDeployer.new(:demo)
287
+ deployer3 = RakeHerokuDeployer.new(:production)
288
+ deployer.auto_deploy
289
+ deployer2.auto_deploy
290
+ deployer3.auto_deploy
291
+ end
292
+
293
+ namespace :all do
294
+ task :migrations do
295
+ deployer = RakeHerokuDeployer.new(:staging)
296
+ deployer2 = RakeHerokuDeployer.new(:demo)
297
+ deployer3 = RakeHerokuDeployer.new(:production)
298
+ deployer.run_migrations
299
+ deployer2.run_migrations
300
+ deployer3.run_migrations
301
+ end
302
+
303
+ task :backup_deploy do
304
+ deployer = RakeHerokuDeployer.new(:staging)
305
+ deployer2 = RakeHerokuDeployer.new(:demo)
306
+ deployer3 = RakeHerokuDeployer.new(:production)
307
+ deployer.backup_deploy
308
+ deployer2.backup_deploy
309
+ deployer3.backup_deploy
310
+ end
311
+
312
+ task :preboot do
313
+ deployer = RakeHerokuDeployer.new(:staging)
314
+ deployer2 = RakeHerokuDeployer.new(:demo)
315
+ deployer3 = RakeHerokuDeployer.new(:production)
316
+ deployer.deploy
317
+ deployer2.deploy
318
+ deployer3.deploy
319
+ end
320
+ end
321
+
322
+ # A Helper method to see what the output is
323
+ task :detect_schema_change do
324
+ deployer = RakeHerokuDeployer.new(:staging)
325
+ puts deployer.schema_change_since_last_release?
326
+ end
327
+ end
@@ -0,0 +1,85 @@
1
+ # Run with: rake environment elasticsearch:reindex
2
+ # Begins by creating the index using tire:import:model command. This will create the "official" index name, e.g. "things" each time.
3
+ # Then we rename it to, e.g. "things_20121001052916" and alias "things" to it.
4
+ # Assumes usage of the elasticsearch-ruby libraries
5
+ # TODO: Assumes you have a library called ElasticsearchAdminHelper defined with the right methods. Move that helper into this gem
6
+
7
+ namespace :elasticsearch do
8
+ desc 'Reindexes all ActiveRecord model indices'
9
+ task "reindex:all" => :environment do
10
+ Rails.application.eager_load!
11
+ include ElasticsearchAdminHelper
12
+
13
+ ActiveRecord::Base.descendants.each do |model_class|
14
+ next unless model_class.respond_to? :__elasticsearch__
15
+ reindex_model(model_class)
16
+ end
17
+
18
+ puts 'All indices reindexed'
19
+ end
20
+
21
+ desc 'Deletes indices and then reindexes all ActiveRecord model indices assuming none exist yet'
22
+ task "reindex:all:fresh" => :environment do
23
+ return unless Rails.env.development? or Rails.env.test?
24
+
25
+ Rails.application.eager_load!
26
+ include ElasticsearchAdminHelper
27
+
28
+ # If we don't create the temporary indices, then mass emails (for example) will try
29
+ # to query users for recipient count and fail
30
+ ActiveRecord::Base.descendants.each do |model_class|
31
+ next unless model_class.respond_to? :__elasticsearch__
32
+ delete_index(model_class.index_name)
33
+ create_temporary_index(model_class)
34
+ end
35
+
36
+ ActiveRecord::Base.descendants.each do |model_class|
37
+ next unless model_class.respond_to? :__elasticsearch__
38
+ reindex_model(model_class, true)
39
+ end
40
+
41
+ puts 'All indices created, aliased and ready'
42
+ end
43
+
44
+ desc 'Deletes indices and then reindexes all ActiveRecord model indices assuming none exist yet. Is used for testing where aliases are not used'
45
+ task "tests:prepare" => :environment do
46
+ return unless Rails.env.development? or Rails.env.test?
47
+
48
+ Rails.application.eager_load!
49
+ include ElasticsearchAdminHelper
50
+
51
+ # If we don't create the temporary indices, then mass emails (for example) will try
52
+ # to query users for recipient count and fail
53
+ ActiveRecord::Base.descendants.each do |model_class|
54
+ next unless model_class.respond_to? :__elasticsearch__
55
+ delete_index(model_class.index_name)
56
+ create_temporary_index(model_class)
57
+ end
58
+
59
+ puts 'All indices created, aliased and ready'
60
+ end
61
+
62
+ Dir.foreach("#{Rails.root}/app/models") do |item|
63
+ next if item == '.' or item == '..' or not item
64
+ name = item.split(".")[0].pluralize
65
+
66
+ desc "Reindexes #{name} using aliases"
67
+ task "reindex:#{name}" => :environment do
68
+ Rails.application.eager_load!
69
+ include ElasticsearchAdminHelper
70
+
71
+ klass = Kernel.const_get(name.classify)
72
+ reindex_model(klass)
73
+ end
74
+
75
+ desc "Reindexes #{name} using aliases, and deletes the old one first" # because Tire tries to create an index for us sometimes
76
+ task "reindex:#{name}:delete_old_first" => :environment do
77
+ Rails.application.eager_load!
78
+ include ElasticsearchAdminHelper
79
+
80
+ klass = Kernel.const_get(name.classify)
81
+ reindex_model(klass, true)
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,16 @@
1
+ # A simple collection of convenient rake tasks for heroku deployed applications
2
+ namespace :heroku do
3
+ namespace :maintenance do
4
+ task :on do
5
+ app = ENV['APPLICATION_NAME']
6
+ puts `heroku maintenance:on -a #{app}`
7
+ puts `heroku ps:scale worker=0 urgent=0 clock=0 -a #{app}`
8
+ end
9
+
10
+ task :off do
11
+ app = ENV['APPLICATION_NAME']
12
+ puts `heroku maintenance:off -a #{app}`
13
+ puts `heroku ps:scale worker=2 urgent=2 clock=1 -a #{app}`
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,34 @@
1
+ # Simple helpers to find invalid records and print why they are invalid. May
2
+ # take a while to run depending on size of data
3
+ namespace :invalids do
4
+ Dir.foreach("#{Rails.root}/app/models") do |item|
5
+ next if item == '.' or item == '..' or not item
6
+ name = item.split(".")[0].pluralize
7
+
8
+ desc "Finds invalid records for #{name} scaffold"
9
+ task "find:#{name}" => :environment do
10
+ Rails.application.eager_load!
11
+ klass = Kernel.const_get(name.classify)
12
+
13
+ invalids = []
14
+ index = 0
15
+ klass.find_each do |obj|
16
+ index += 1
17
+
18
+ if index % 1000 == 0
19
+ ap "invalids at index #{index}"
20
+ ap invalids
21
+ end
22
+
23
+ next if obj.valid?
24
+ invalids << { id: obj.id, errors: obj.errors }
25
+ end
26
+
27
+ ap "Invalids at end:"
28
+ ap invalids
29
+
30
+ # This is used for log based alerts
31
+ ap "LOG NOTIFIER: INVALID RECORDS EXIST" if invalids.count > 0
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,23 @@
1
+ # Finds missing rspec files and generates them for you. May take a while to run, depending
2
+ # on the number of scaffolds in the project.
3
+ namespace :rspec_generator do
4
+ desc 'Generate rspec specs for all scaffolds that are missing specs'
5
+ task :generate => :environment do
6
+ Rails.application.eager_load!
7
+
8
+ # Iterate over all 'normal' active record classes. By normal
9
+ # I mean that rails includes habtm join tables in the list
10
+ # which we don't want.
11
+ ActiveRecord::Base.descendants.each do |model_class|
12
+ next if model_class.name.starts_with?("HABTM_")
13
+ generate_for_model(model_class)
14
+ end
15
+ end
16
+
17
+ def generate_for_model(model_class)
18
+ underscore_name = model_class.name.underscore
19
+ puts "Generating missing specs for #{underscore_name}"
20
+ system("rails g rspec:scaffold #{underscore_name} -s --view-specs=false --controller-specs=false --request-specs=true")
21
+ system("rails g rspec:model #{underscore_name} -s")
22
+ end
23
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: handshake_service
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Ringwelski
@@ -71,6 +71,12 @@ files:
71
71
  - handshake_service.gemspec
72
72
  - lib/handshake_service.rb
73
73
  - lib/handshake_service/version.rb
74
+ - lib/tasks/auto_annotate_models.rake
75
+ - lib/tasks/deploy.rake
76
+ - lib/tasks/elasticsearch.rake
77
+ - lib/tasks/heroku.rake
78
+ - lib/tasks/invalids.rake
79
+ - lib/tasks/rspec_generator.rake
74
80
  homepage: https://github.com/strydercorp/handshake_service
75
81
  licenses:
76
82
  - MIT