capistrano-chewy 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 36801dffebe67a59da0de98084f1c2775d47371f
4
+ data.tar.gz: 50afbaef407413dd996110e7dc946690b8f63af9
5
+ SHA512:
6
+ metadata.gz: ee2759d696d557a1e858347dbc4c854b4d705de2447d31145c205e1ba7486cd2ff945839e461a1825254a88d6667850f46b1481d1e9bd5f85f02b15856574987
7
+ data.tar.gz: edf506dd5325071b2b06c28a3f9cac42d16bfea928029472117319da29551e8dda7b8c417ea5dc6ba41c16bf0450f0e866c6a88c8891d651cb1e73aa0a878971
data/.gitignore ADDED
@@ -0,0 +1,52 @@
1
+ *.gem
2
+ .idea
3
+ *.rbc
4
+ /.config
5
+ /coverage/
6
+ /InstalledFiles
7
+ /pkg/
8
+ /spec/reports/
9
+ /spec/examples.txt
10
+ /test/tmp/
11
+ /test/version_tmp/
12
+ /tmp/
13
+ Gemfile.lock
14
+
15
+ # Used by dotenv library to load environment variables.
16
+ # .env
17
+
18
+ ## Specific to RubyMotion:
19
+ .dat*
20
+ .repl_history
21
+ build/
22
+ *.bridgesupport
23
+ build-iPhoneOS/
24
+ build-iPhoneSimulator/
25
+
26
+ ## Specific to RubyMotion (use of CocoaPods):
27
+ #
28
+ # We recommend against adding the Pods directory to your .gitignore. However
29
+ # you should judge for yourself, the pros and cons are mentioned at:
30
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
31
+ #
32
+ # vendor/Pods/
33
+
34
+ ## Documentation cache and generated files:
35
+ /.yardoc/
36
+ /_yardoc/
37
+ /doc/
38
+ /rdoc/
39
+
40
+ ## Environment normalization:
41
+ /.bundle/
42
+ /vendor/bundle
43
+ /lib/bundler/man/
44
+
45
+ # for a library or gem, you might want to ignore these files since the code is
46
+ # intended to run in multiple environments; otherwise, check them in:
47
+ # Gemfile.lock
48
+ # .ruby-version
49
+ # .ruby-gemset
50
+
51
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
52
+ .rvmrc
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/.rubocop.yml ADDED
@@ -0,0 +1,12 @@
1
+ LineLength:
2
+ Max: 120
3
+ AllCops:
4
+ Exclude:
5
+ - 'spec/**/*'
6
+ DisplayCopNames: true
7
+ Rails:
8
+ Enabled: true
9
+ Documentation:
10
+ Enabled: false
11
+ Style/EndOfLine:
12
+ Enabled: false
data/.travis.yml ADDED
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ before_install: gem install bundler
3
+ bundler_args: --without yard guard benchmarks
4
+ script: "rake spec"
5
+ rvm:
6
+ - 2.2.4
7
+ - 2.3.1
8
+ - ruby-head
9
+ matrix:
10
+ allow_failures:
11
+ - rvm: ruby-head
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2016 Nikita Bulai
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,81 @@
1
+ # Capistrano::Chewy
2
+ [![Gem Version](https://badge.fury.io/rb/capistrano-chewy.svg)](http://badge.fury.io/rb/capistrano-chewy)
3
+ [![Build Status](https://travis-ci.org/nbulaj/capistrano-chewy.svg?branch=master)](https://travis-ci.org/nbulaj/capistrano-chewy)
4
+
5
+ Manage and continuously rebuild your ElasticSearch indexes with [Chewy](https://github.com/toptal/chewy/) and [Capistrano](https://github.com/capistrano/capistrano) v3.
6
+
7
+ `Capistrano::Chewy` gem adds automatic conditionally reset only modified Chewy indexes to your deploy flow so you do not have to build them manually.
8
+ Moreover, it adds the possibility of manual index management with the base Chewy tasks on the remote server.
9
+
10
+ ## Requirements
11
+
12
+ * Capistrano >= 3.0
13
+ * Chewy >= 0.4
14
+
15
+ ## Installation
16
+
17
+ Add this line to your application's Gemfile:
18
+
19
+ ```ruby
20
+ gem 'capistrano-chewy', require: false
21
+ ```
22
+
23
+ or:
24
+
25
+ ```ruby
26
+ gem 'capistrano-chewy', require: false, group: :development
27
+ ```
28
+
29
+ And then run bundler:
30
+
31
+ ```
32
+ $ bundle
33
+ ```
34
+
35
+ Or install it yourself as:
36
+
37
+ ```
38
+ $ gem install capistrano-chewy
39
+ ```
40
+
41
+ ## Usage
42
+
43
+ Require it in your `Capfile`:
44
+
45
+ ```ruby
46
+ # Capfile
47
+
48
+ require 'capistrano/chewy'
49
+ ```
50
+
51
+ then you can use `cap -T` to list `Capistrano::Chewy` tasks:
52
+
53
+ ```ruby
54
+ cap deploy:chewy:rebuild # Reset only modified Chewy indexes
55
+ cap deploy:chewy:reset # Destroy, recreate and import data to all the indexes
56
+ cap deploy:chewy:reset[indexes] # Destroy, recreate and import data to the specified indexes
57
+ cap deploy:chewy:update # Updates data to all the indexes
58
+ cap deploy:chewy:update[indexes] # Updates data to the specified indexes
59
+ ```
60
+
61
+ ## Configuration
62
+
63
+ You can setup the following:
64
+
65
+ ```ruby
66
+ # deploy.rb
67
+ set :chewy_conditionally_reset, false # Reset only modified Chewy indexes, true by default
68
+ set :chewy_path, 'app/my_indexes' # Path to Chewy indexes, 'app/chewy' by default
69
+ set :chewy_env, :chewy_production # Environment variable for Chewy, equal to RAILS_ENV by default
70
+ set :chewy_role, :web # Chewy role, :app by default
71
+ set :chewy_skip, true # Skip processing Chewy indexes during deploy, false by default
72
+ set :chewy_default_hooks, false # Add default capistrano-chewy hooks to your deploy flow, true by default
73
+ ```
74
+
75
+ ## Contributing
76
+
77
+ 1. Fork it ( http://github.com/nbulaj/capistrano-chewy/fork )
78
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
79
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
80
+ 4. Push to the branch (`git push origin my-new-feature`)
81
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'capistrano-chewy/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'capistrano-chewy'
8
+ spec.version = CapistranoChewy.gem_version
9
+ spec.authors = ['Nikita Bulai']
10
+ spec.date = '2016-10-18'
11
+ spec.email = ['bulainikita@gmail.com']
12
+ spec.summary = 'Manage and continuously rebuild your ElasticSearch indexes with Chewy and Capistrano'
13
+ spec.description = 'Manage and continuously rebuild your ElasticSearch indexes with Chewy and Capistrano v3.'
14
+ spec.homepage = 'https://github.com/nbulaj/capistrano-chewy'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files`.split($RS)
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_dependency 'capistrano', '~> 3.0'
23
+ spec.add_dependency 'chewy', '~> 0.4'
24
+
25
+ spec.add_development_dependency 'rspec', '~> 3.0'
26
+ end
@@ -0,0 +1,5 @@
1
+ require 'capistrano-chewy/version'
2
+ require 'capistrano-chewy/diff_parser'
3
+
4
+ module CapistranoChewy
5
+ end
@@ -0,0 +1,40 @@
1
+ module CapistranoChewy
2
+ class DiffParser
3
+ class Result
4
+ attr_reader :removed, :changed, :added
5
+
6
+ def initialize
7
+ @removed = []
8
+ @changed = []
9
+ @added = []
10
+ end
11
+ end
12
+
13
+ CHANGED_FILE_PATTERN = /Files\s+.+\s+and\s+(.+)\s+differ/i
14
+ NEW_OR_REMOVED_FILE_PATTERN = /Only in (.+):\s+(.+)/i
15
+
16
+ class << self
17
+ def parse(diff, current_path, release_path)
18
+ raise ArgumentError, 'current_path can not be the same as release_path!' if current_path == release_path
19
+
20
+ diff.split("\n").each_with_object(Result.new) do |line, result|
21
+ # File was changed
22
+ CHANGED_FILE_PATTERN.match(line) do |match|
23
+ result.changed << match[1]
24
+ next
25
+ end
26
+
27
+ # File was removed or added
28
+ NEW_OR_REMOVED_FILE_PATTERN.match(line) do |match|
29
+ # if file placed in current path, then it was removed from the release path
30
+ if match[1] == current_path.chomp(File::SEPARATOR)
31
+ result.removed << File.join(match[1], match[2])
32
+ else
33
+ result.added << File.join(match[1], match[2])
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,13 @@
1
+ module CapistranoChewy
2
+ def self.gem_version
3
+ Gem::Version.new VERSION::STRING
4
+ end
5
+
6
+ module VERSION
7
+ MAJOR = 0
8
+ MINOR = 1
9
+ TINY = 0
10
+
11
+ STRING = [MAJOR, MINOR, TINY].compact.join('.')
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ # Ensure deploy tasks are loaded before we run
2
+ require 'capistrano/deploy'
3
+ require 'capistrano-chewy'
4
+
5
+ load File.expand_path('../tasks/chewy.rake', __FILE__)
@@ -0,0 +1,135 @@
1
+ namespace :load do
2
+ task :defaults do
3
+ set :chewy_conditionally_reset, -> { true }
4
+ set :chewy_path, -> { 'app/chewy' }
5
+ set :chewy_env, -> { fetch(:rails_env, fetch(:stage)) }
6
+ set :chewy_role, -> { :app }
7
+ set :chewy_skip, -> { false }
8
+ set :chewy_default_hooks, -> { true }
9
+ end
10
+ end
11
+
12
+ namespace :deploy do
13
+ before :starting, :check_chewy_hooks do
14
+ invoke :'deploy:chewy:add_default_hooks' if fetch(:chewy_default_hooks)
15
+ end
16
+
17
+ namespace :chewy do
18
+ # Adds default Capistrano::Chewy hooks to the deploy flow
19
+ task :add_default_hooks do
20
+ after 'deploy:updated', 'deploy:chewy:rebuild'
21
+ end
22
+
23
+ # Default Chewy rake tasks
24
+ desc 'Destroy, recreate and import data to all or specified (pass with [one,two]) indexes'
25
+ task :reset do |_task, args|
26
+ indexes = args.extras
27
+
28
+ on roles fetch(:chewy_role) do
29
+ within release_path do
30
+ with rails_env: fetch(:chewy_env) do
31
+ if indexes.any?
32
+ execute :rake, "chewy:reset[#{indexes.join(',')}]"
33
+ else
34
+ # Simply chewy:reset / chewy:update for Chewy > 0.8.4
35
+ execute :rake, 'chewy:reset:all'
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ desc 'Updates data to all or specified (passed with [one,two]) indexes'
43
+ task :update do |_task, args|
44
+ indexes = args.extras
45
+
46
+ on roles fetch(:chewy_role) do
47
+ within release_path do
48
+ with rails_env: fetch(:chewy_env) do
49
+ if indexes.any?
50
+ execute :rake, "chewy:update[#{indexes.join(',')}]"
51
+ else
52
+ execute :rake, 'chewy:update:all'
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ # Smart rebuild of modified Chewy indexes
60
+ desc 'Reset Chewy indexes if they have been added, changed or removed'
61
+ task :rebuild do
62
+ on roles fetch(:chewy_role) do
63
+ if fetch(:chewy_skip)
64
+ info 'Skipping task according to the deploy settings'
65
+ exit 0
66
+ end
67
+
68
+ info "Checking Chewy directory (#{fetch(:chewy_path)})"
69
+
70
+ chewy_path = File.join(release_path, fetch(:chewy_path))
71
+ unless test("[ -d #{chewy_path} ]")
72
+ error "Directory #{chewy_path} doesn't exist!"
73
+ exit 1
74
+ end
75
+
76
+ if fetch(:chewy_conditionally_reset)
77
+ if test('diff -v')
78
+ info 'Running smart indexes reset...'
79
+ invoke :'deploy:chewy:rebuilding'
80
+ else
81
+ error "Can't check the difference between Chewy indexes - install 'diff' tool first!"
82
+ exit 1
83
+ end
84
+ else
85
+ info 'Running chewy:reset:all'
86
+ invoke :'deploy:chewy:reset:all'
87
+ end
88
+ end
89
+ end
90
+
91
+ desc 'Runs smart Chewy indexes rebuilding (only for changed files)'
92
+ task :rebuilding do
93
+ on roles fetch(:chewy_role) do
94
+ if fetch(:chewy_skip)
95
+ info 'Skipping task according to the deploy settings'
96
+ exit 0
97
+ end
98
+
99
+ chewy_path = fetch(:chewy_path)
100
+ info "Checking changes in #{chewy_path}"
101
+
102
+ chewy_release_path = File.join(release_path, chewy_path)
103
+ chewy_current_path = File.join(current_path, chewy_path)
104
+
105
+ # -q, --brief report only when files differ
106
+ # -E, --ignore-tab-expansion ignore changes due to tab expansion
107
+ # -Z, --ignore-trailing-space ignore white space at line end
108
+ # -B, --ignore-blank-lines ignore changes where lines are all blank
109
+ #
110
+ indexes_diff = capture(:diff, "-qZEB #{chewy_release_path} #{chewy_current_path}", raise_on_non_zero_exit: false)
111
+
112
+ # If diff is empty then indices have not changed
113
+ if indexes_diff.nil? || indexes_diff.strip.empty?
114
+ info 'Skipping `deploy:chewy:rebuilding` (nothing changed in the Chewy path)'
115
+ else
116
+ within release_path do
117
+ with rails_env: fetch(:chewy_env) do
118
+ changes = ::CapistranoChewy::DiffParser.parse(indexes_diff, chewy_current_path, chewy_release_path)
119
+
120
+ # Reset indexes that were changed or added
121
+ indexes_to_reset = changes.changed.concat(changes.added)
122
+
123
+ if indexes_to_reset.any?
124
+ indexes = indexes_to_reset.map { |file| File.basename(file).gsub('_index.rb', '') }.join(',')
125
+ execute :rake, "chewy:reset[#{indexes}]"
126
+ end
127
+
128
+ # TODO: destroy removed indexes?
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe CapistranoChewy::DiffParser do
4
+ let(:current_path) { '/project/1/app/chewy' }
5
+ let(:release_path) { '/project/2/app/chewy' }
6
+
7
+ let(:full_diff) do
8
+ "Files #{current_path}/accounts_index.rb and #{release_path}/accounts_index.rb differ\n" \
9
+ "Files #{current_path}/posts_index.rb and #{release_path}/posts_index.rb differ\n" \
10
+ "Only in #{release_path}: applications_index.rb\n" \
11
+ "Files #{current_path}/comments_index.rb and #{release_path}/comments_index.rb differ\n" \
12
+ "Only in #{current_path}: users_index.rb\n"
13
+ end
14
+
15
+ describe '#parse' do
16
+ context 'with difference between directories' do
17
+ it 'returns result object with removed, added and changed files' do
18
+ result = described_class.parse(full_diff, current_path, release_path)
19
+
20
+ expect(result.changed).to eq(["#{release_path}/accounts_index.rb", "#{release_path}/posts_index.rb", "#{release_path}/comments_index.rb"])
21
+ expect(result.added).to eq(["#{release_path}/applications_index.rb"])
22
+ expect(result.removed).to eq(["#{current_path}/users_index.rb"])
23
+ end
24
+ end
25
+
26
+ context 'without differences' do
27
+ it 'returns result object with removed, added and changed files' do
28
+ result = described_class.parse('', current_path, release_path)
29
+
30
+ expect(result.changed).to be_empty
31
+ expect(result.added).to be_empty
32
+ expect(result.removed).to be_empty
33
+ end
34
+ end
35
+
36
+ context 'with the same directories' do
37
+ it 'raises an error' do
38
+ expect { described_class.parse('', current_path, current_path) }.to raise_error(ArgumentError)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,8 @@
1
+ require 'bundler/setup'
2
+ Bundler.setup
3
+
4
+ require 'capistrano-chewy'
5
+
6
+ RSpec.configure do |config|
7
+ config.order = 'random'
8
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: capistrano-chewy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Nikita Bulai
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-10-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: capistrano
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: chewy
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.4'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ description: Manage and continuously rebuild your ElasticSearch indexes with Chewy
56
+ and Capistrano v3.
57
+ email:
58
+ - bulainikita@gmail.com
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ".gitignore"
64
+ - ".rspec"
65
+ - ".rubocop.yml"
66
+ - ".travis.yml"
67
+ - Gemfile
68
+ - LICENSE
69
+ - README.md
70
+ - Rakefile
71
+ - capistrano3-postgres.gemspec
72
+ - lib/capistrano-chewy.rb
73
+ - lib/capistrano-chewy/diff_parser.rb
74
+ - lib/capistrano-chewy/version.rb
75
+ - lib/capistrano/chewy.rb
76
+ - lib/capistrano/tasks/chewy.rake
77
+ - spec/diff_parser_spec.rb
78
+ - spec/spec_helper.rb
79
+ homepage: https://github.com/nbulaj/capistrano-chewy
80
+ licenses:
81
+ - MIT
82
+ metadata: {}
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ requirements: []
98
+ rubyforge_project:
99
+ rubygems_version: 2.6.3
100
+ signing_key:
101
+ specification_version: 4
102
+ summary: Manage and continuously rebuild your ElasticSearch indexes with Chewy and
103
+ Capistrano
104
+ test_files:
105
+ - spec/diff_parser_spec.rb
106
+ - spec/spec_helper.rb
107
+ has_rdoc: