Skip to content

Commit

Permalink
Merge pull request #1 from nbulaj/0.1.1
Browse files Browse the repository at this point in the history
0.2
  • Loading branch information
nbulaj authored Oct 19, 2016
2 parents fa5fbf2 + e9aff7e commit 475d197
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 32 deletions.
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

Manage and continuously rebuild your ElasticSearch indexes with [Chewy](https://github.com/toptal/chewy/) and [Capistrano](https://github.com/capistrano/capistrano) v3.

`Capistrano::Chewy` gem adds automatic conditionally reset only modified Chewy indexes to your deploy flow so you do not have to build them manually.
`Capistrano::Chewy` gem adds automatic conditionally reset of only modified Chewy indexes and the removal of deleted index files to your deploy flow so you do not have to do it manually.
Moreover, it adds the possibility of manual index management with the base Chewy tasks on the remote server.

## Requirements
Expand Down Expand Up @@ -38,14 +38,22 @@ Or install it yourself as:
$ gem install capistrano-chewy
```

If you want to use the latest version from the `master`, then add the following line to your Gemfile:

```ruby
gem 'capistrano-chewy', git: 'https://github.com/nbulaj/capistrano-chewy.git'
```

## Usage

Require it in your `Capfile`:

```ruby
# Capfile

...
require 'capistrano/chewy'
...
```

then you can use `cap -T` to list `Capistrano::Chewy` tasks:
Expand All @@ -58,7 +66,7 @@ cap deploy:chewy:update # Updates data to all the indexes
cap deploy:chewy:update[indexes] # Updates data to the specified indexes
```

By default `Capistrano::Chewy` adds `deploy:chewy:rebuild` task after `deploy:updated`.
By default `Capistrano::Chewy` adds `deploy:chewy:rebuild` task after `deploy:updated` and `deploy:reverted`.
If you want to change it, then you need to disable default gem hooks by setting `chewy_default_hooks` to `false` in your deployment config and manually define the order of the tasks.

## Configuration
Expand All @@ -71,8 +79,8 @@ set :chewy_conditionally_reset, false # Reset only modified Chewy indexes, true
set :chewy_path, 'app/my_indexes' # Path to Chewy indexes, 'app/chewy' by default
set :chewy_env, :chewy_production # Environment variable for Chewy, equal to RAILS_ENV by default
set :chewy_role, :web # Chewy role, :app by default
set :chewy_skip, true # Skip processing Chewy indexes during deploy, false by default
set :chewy_default_hooks, false # Add default capistrano-chewy hooks to your deploy flow, true by default
set :chewy_delete_removed_indexes, false # Delete indexes which files have been deleted, true by default
```

## Contributing
Expand Down
4 changes: 2 additions & 2 deletions capistrano3-postgres.gemspec → capistrano-chewy.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ Gem::Specification.new do |spec|
spec.name = 'capistrano-chewy'
spec.version = CapistranoChewy.gem_version
spec.authors = ['Nikita Bulai']
spec.date = '2016-10-18'
spec.email = ['bulainikita@gmail.com']
spec.date = '2016-10-19'
spec.email = ['bulajnikita@gmail.com']
spec.summary = 'Manage and continuously rebuild your ElasticSearch indexes with Chewy and Capistrano'
spec.description = 'Manage and continuously rebuild your ElasticSearch indexes with Chewy and Capistrano v3.'
spec.homepage = 'https://github.com/nbulaj/capistrano-chewy'
Expand Down
6 changes: 5 additions & 1 deletion lib/capistrano-chewy/diff_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,18 @@ def initialize
@changed = []
@added = []
end

def empty?
[@removed, @changed, @added].all?(&:empty?)
end
end

CHANGED_FILE_PATTERN = /Files\s+.+\s+and\s+(.+)\s+differ/i
NEW_OR_REMOVED_FILE_PATTERN = /Only in (.+):\s+(.+)/i

class << self
def parse(diff, current_path, release_path)
raise ArgumentError, 'current_path can not be the same as release_path!' if current_path == release_path
return Result.new if current_path == release_path

diff.split("\n").each_with_object(Result.new) do |line, result|
# File was changed
Expand Down
2 changes: 1 addition & 1 deletion lib/capistrano-chewy/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ def self.gem_version

module VERSION
MAJOR = 0
MINOR = 1
MINOR = 2
TINY = 0

STRING = [MAJOR, MINOR, TINY].compact.join('.')
Expand Down
53 changes: 30 additions & 23 deletions lib/capistrano/tasks/chewy.rake
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
namespace :load do
task :defaults do
set :chewy_default_hooks, -> { true }
set :chewy_conditionally_reset, -> { true }
set :chewy_path, -> { 'app/chewy' }
set :chewy_env, -> { fetch(:rails_env, fetch(:stage)) }
set :chewy_role, -> { :app }
set :chewy_skip, -> { false }
set :chewy_default_hooks, -> { true }
set :chewy_delete_removed_indexes, -> { true }
end
end

Expand All @@ -17,7 +17,8 @@ namespace :deploy do
namespace :chewy do
# Adds default Capistrano::Chewy hooks to the deploy flow
task :add_default_hooks do
after 'deploy:updated', 'deploy:chewy:rebuild'
after :'deploy:updated', 'deploy:chewy:rebuild'
after :'deploy:reverted', 'deploy:chewy:rebuild'
end

# Default Chewy rake tasks
Expand Down Expand Up @@ -60,11 +61,6 @@ namespace :deploy do
desc 'Reset Chewy indexes if they have been added, changed or removed'
task :rebuild do
on roles fetch(:chewy_role) do
if fetch(:chewy_skip)
info 'Skipping task according to the deploy settings'
exit 0
end

info "Checking Chewy directory (#{fetch(:chewy_path)})"

chewy_path = File.join(release_path, fetch(:chewy_path))
Expand All @@ -91,11 +87,6 @@ namespace :deploy do
desc 'Runs smart Chewy indexes rebuilding (only for changed files)'
task :rebuilding do
on roles fetch(:chewy_role) do
if fetch(:chewy_skip)
info 'Skipping task according to the deploy settings'
exit 0
end

chewy_path = fetch(:chewy_path)
info "Checking changes in #{chewy_path}"

Expand All @@ -107,25 +98,41 @@ namespace :deploy do
# -Z, --ignore-trailing-space ignore white space at line end
# -B, --ignore-blank-lines ignore changes where lines are all blank
#
indexes_diff = capture(:diff, "-qZEB #{chewy_release_path} #{chewy_current_path}", raise_on_non_zero_exit: false)
diff_args = "-qZEB #{chewy_release_path} #{chewy_current_path}"
indexes_diff = capture :diff, diff_args, raise_on_non_zero_exit: false
changes = ::CapistranoChewy::DiffParser.parse(indexes_diff, chewy_current_path, chewy_release_path)

# If diff is empty then indices have not changed
if indexes_diff.nil? || indexes_diff.strip.empty?
if changes.empty?
info 'Skipping `deploy:chewy:rebuilding` (nothing changed in the Chewy path)'
exit 0
else
within release_path do
with rails_env: fetch(:chewy_env) do
changes = ::CapistranoChewy::DiffParser.parse(indexes_diff, chewy_current_path, chewy_release_path)
indexes_to_reset = changes.changed.concat(changes.added)
indexes_to_delete = changes.removed

# Reset indexes that were changed or added
indexes_to_reset = changes.changed.concat(changes.added)
# Reset indexes which have been modified or added
if indexes_to_reset.any?
indexes = indexes_to_reset.map { |file| File.basename(file, '_index.rb') }.join(',')

if indexes_to_reset.any?
indexes = indexes_to_reset.map { |file| File.basename(file).gsub('_index.rb', '') }.join(',')
within release_path do
with rails_env: fetch(:chewy_env) do
info "Modified or new indexes: #{indexes}"
execute :rake, "chewy:reset[#{indexes}]"
end
end
end

# Delete indexes which have been removed
if indexes_to_delete.any? && fetch(:chewy_delete_removed_indexes)
indexes = indexes_to_delete.map { |file| File.basename(file, '.rb').camelize }.uniq
runner_code = "[#{indexes.join(', ')}].each(&:delete)"

# TODO: destroy removed indexes?
# Removed index files exists only in the old (current) release
within current_path do
with rails_env: fetch(:chewy_env) do
info "Removing indexes: #{indexes.join(',')}"
execute :rails, "runner '#{runner_code}'"
end
end
end
end
Expand Down
15 changes: 13 additions & 2 deletions spec/diff_parser_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
let(:current_path) { '/project/1/app/chewy' }
let(:release_path) { '/project/2/app/chewy' }

# TODO: make a real diff
let(:full_diff) do
"Files #{current_path}/accounts_index.rb and #{release_path}/accounts_index.rb differ\n" \
"Files #{current_path}/posts_index.rb and #{release_path}/posts_index.rb differ\n" \
Expand All @@ -20,6 +21,8 @@
expect(result.changed).to eq(["#{release_path}/accounts_index.rb", "#{release_path}/posts_index.rb", "#{release_path}/comments_index.rb"])
expect(result.added).to eq(["#{release_path}/applications_index.rb"])
expect(result.removed).to eq(["#{current_path}/users_index.rb"])

expect(result.empty?).to be_falsey
end
end

Expand All @@ -30,12 +33,20 @@
expect(result.changed).to be_empty
expect(result.added).to be_empty
expect(result.removed).to be_empty

expect(result.empty?).to be_truthy
end
end

context 'with the same directories' do
it 'raises an error' do
expect { described_class.parse('', current_path, current_path) }.to raise_error(ArgumentError)
it 'returns blank result' do
result = described_class.parse('', current_path, current_path)

expect(result.changed).to be_empty
expect(result.added).to be_empty
expect(result.removed).to be_empty

expect(result.empty?).to be_truthy
end
end
end
Expand Down

0 comments on commit 475d197

Please sign in to comment.