avrolution 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a77bd13e1ee60023abd3c9dc39531d825108333c
4
+ data.tar.gz: 682db54c1f2ca910df08b53e5bc762a0783c198a
5
+ SHA512:
6
+ metadata.gz: 27c73ea125534233e30fef39bb25f58b82c260924071676fc38a64b88014ad31c5b9f7fb1ec7a534f0c6814750fe7d7f2ffba1982ac91de3b14168a6f89fc9db
7
+ data.tar.gz: 9f3474ebff5d9d979f392865bcacaf3b17a62b93dace4953f9ab189cdc261bfe1916fc0ece516d18bb8d972d2bc1fead891ecd7d3b7806344fd623d47b8080aa
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.overcommit.yml ADDED
@@ -0,0 +1,13 @@
1
+ PreCommit:
2
+ RuboCop:
3
+ enabled: true
4
+ required: false
5
+ on_warn: fail
6
+
7
+ HardTabs:
8
+ enabled: true
9
+ required: false
10
+
11
+ CommitMsg:
12
+ TrailingPeriod:
13
+ enabled: false
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,2 @@
1
+ inherit_gem:
2
+ salsify_rubocop: conf/rubocop.yml
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.3.4
4
+ before_install: gem install bundler -v 1.14.6
5
+ script:
6
+ - bundle exec rubocop
7
+ - bundle exec rspec
data/CHANGELOG.md ADDED
@@ -0,0 +1,4 @@
1
+ # avrolution
2
+
3
+ ## v0.1.0
4
+ - Add rake task to check the compatibility of schemas against a schema registry.
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # override the :github shortcut to be secure by using HTTPS
4
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}.git" }
5
+
6
+ # Specify your gem's dependencies in avrolution.gemspec
7
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Salsify, Inc
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
13
+ all 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
21
+ THE SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,122 @@
1
+ # avrolution
2
+
3
+ Support for the evolution of Avro schemas stored in a schema registry.
4
+
5
+ This gem provides utilities to help with the management of Avro JSON schemas in a
6
+ schema registry. The compatibility of Avro JSON schema files can be checked
7
+ against a registry. Expected compatibility breaks can also be declared.
8
+
9
+ ## Installation
10
+
11
+ Add this gem to your application's Gemfile, typically in a dev/test group:
12
+
13
+ ```ruby
14
+ group :development, :test do
15
+ gem 'avrolution'
16
+ end
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ $ bundle install
22
+
23
+ Or install it yourself as:
24
+
25
+ $ gem install avrolution
26
+
27
+ ## Configuration
28
+
29
+ The gem supports the following configuration:
30
+
31
+ * `root` - The directory to search for Avro JSON schemas (`.avsc`). This is also
32
+ the default location for the compatibility breaks file. In a Rails application,
33
+ `Avrolution.root` defaults to `Rails.root`.
34
+ * `compatibility_breaks_file` - The path to the compability breaks file. Defaults
35
+ to `#{Avrolution}.root/avro_compatibility_breaks.txt`.
36
+ * `compatibility_schema_registry_url` - The URL for the schema registry to use
37
+ for compatibility checking. `ENV['COMPATIBILITY_SCHEMA_REGISTRY_URL]` is used
38
+ as the default.
39
+ * `logger` - A logger used by the rake tasks in this gem. This does _NOT_ default
40
+ to `Rails.logger` in Rails applications.
41
+
42
+ ## Usage
43
+
44
+ ### Avro Compatibility Check Rake Task
45
+
46
+ There is a rake task to check the compatibility of all Avro JSON schemas under
47
+ `Avrolution.root` against a schema registry.
48
+
49
+ For Rails applications, the `avro:check_compatibility` task is automatically
50
+ defined via a Railtie.
51
+
52
+ This task does not require any arguments. It checks the
53
+ compatibility of all Avro JSON schemas found recursively under `Avrolution.root`
54
+ against the schema registry `Avroluion.compatibility_schema_registry_url` or
55
+ `ENV['COMPATIBILITY_SCHEMA_REGISTRY_URL]`.
56
+
57
+ ```bash
58
+ rake avro:check_compatibility
59
+ ```
60
+
61
+ If a schema is incompatible, then `Avrolution.compatibility_breaks_file` is also
62
+ consulted. If the schema is still incompatible with the last registered version
63
+ then the differences are displayed and the command to add a compatibility break
64
+ is printed.
65
+
66
+ For non-Rails projects, tasks can be defined as:
67
+
68
+ ```ruby
69
+ require 'avrolution/rake/check_compatibility_task'
70
+ Avrolution::Rake::CheckCompatibilityTask.define
71
+ ```
72
+
73
+ ### Avro Add Compatibility Break Rake Task
74
+
75
+ There is a rake task add an entry to the `Avrolution.compatibility_breaks_file`.
76
+
77
+ This rake task accepts the following arguments:
78
+ * `name` - The full name of the Avro schema.
79
+ * `fingerprint` - The Resolution fingerprint as a hex string.
80
+ * `with_compatibility` - Optional compatibility level to use for the check and
81
+ during registration.
82
+ * `after_compatibility` - Optional compatibility level to set after registration.
83
+
84
+ (The registration support will be available in a future version of this gem.)
85
+
86
+ ```bash
87
+ rake avro:add_compatibility_break name=com.salsify.alerts.example_value \
88
+ fingerprint=36a2035c15c1bbbfe895494697d1f760171d00ab4fd39d0616261bf6854374f9 \
89
+ with_compatibility=BACKWARD after_compatibility=FULL
90
+ ```
91
+
92
+ For Rails applications, the `avro:add_compatibility_break` task is automatically
93
+ defined via a Railtie.
94
+
95
+ For non-Rails projects tasks can be defined as:
96
+
97
+ ```ruby
98
+ require 'avrolution/rake/add_compatibility_break_task'
99
+ Avrolution::Rake::AddCompatibilityBreakTask.define
100
+ ```
101
+
102
+ ## Development
103
+
104
+ After checking out the repo, run `bin/setup` to install dependencies. Then,
105
+ run `rake spec` to run the tests. You can also run `bin/console` for an
106
+ interactive prompt that will allow you to experiment.
107
+
108
+ To install this gem onto your local machine, run `bundle exec rake install`.
109
+
110
+ To release a new version, update the version number in `version.rb`, and then
111
+ run `bundle exec rake release`, which will create a git tag for the version,
112
+ push git commits and tags, and push the `.gem` file to
113
+ [rubygems.org](https://rubygems.org).
114
+
115
+ ## Contributing
116
+
117
+ Bug reports and pull requests are welcome on GitHub at
118
+ https://github.com/salsify/avrolution.## License
119
+
120
+ The gem is available as open source under the terms of the
121
+ [MIT License](http://opensource.org/licenses/MIT).
122
+
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task default: :spec
@@ -0,0 +1,44 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'avrolution/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'avrolution'
8
+ spec.version = Avrolution::VERSION
9
+ spec.authors = ['Salsify, Inc']
10
+ spec.email = ['engineering@salsify.com']
11
+
12
+ spec.summary = 'Support for the evolution of Avro schemas stored in a schema registry.'
13
+ spec.description = spec.summary
14
+ spec.homepage = 'https://github.com/salsify/avrolution'
15
+
16
+ spec.license = 'MIT'
17
+
18
+ # Set 'allowed_push_post' to control where this gem can be published.
19
+ if spec.respond_to?(:metadata)
20
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
21
+ else
22
+ raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
23
+ end
24
+
25
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
+ spec.bindir = 'bin'
27
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
28
+ spec.require_paths = ['lib']
29
+
30
+ spec.add_development_dependency 'bundler', '~> 1.12'
31
+ spec.add_development_dependency 'rake', '~> 10.0'
32
+ spec.add_development_dependency 'rspec', '~> 3.4'
33
+ spec.add_development_dependency 'salsify_rubocop', '~> 0.47.2'
34
+ spec.add_development_dependency 'overcommit'
35
+ spec.add_development_dependency 'fakefs'
36
+ spec.add_development_dependency 'simplecov'
37
+
38
+ spec.add_runtime_dependency 'avro-salsify-fork', '1.9.0.5'
39
+ spec.add_runtime_dependency 'avromatic', '0.21.0.rc0' # TODO
40
+ spec.add_runtime_dependency 'diffy'
41
+ spec.add_runtime_dependency 'private_attr'
42
+ spec.add_runtime_dependency 'activesupport'
43
+ spec.add_runtime_dependency 'activemodel'
44
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'avrolution'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -v
5
+
6
+ bundle update
7
+
8
+ overcommit --install
@@ -0,0 +1,39 @@
1
+ require 'active_model'
2
+
3
+ module Avrolution
4
+ class CompatibilityBreak
5
+ include ActiveModel::Validations
6
+
7
+ ValidationError = Class.new(StandardError)
8
+
9
+ VALID_COMPATIBILITY_VALUES = %w(BACKWARD BACKWARD_TRANSITIVE FORWARD
10
+ FORWARD_TRANSITIVE FULL FULL_TRANSITIVE NONE).map(&:freeze).freeze
11
+ NONE = 'NONE'.freeze
12
+
13
+ attr_reader :name, :fingerprint, :with_compatibility, :after_compatibility
14
+
15
+ validates_presence_of :name, :fingerprint
16
+ validates_inclusion_of :with_compatibility, in: VALID_COMPATIBILITY_VALUES, allow_nil: true
17
+ validates_inclusion_of :after_compatibility, in: VALID_COMPATIBILITY_VALUES, allow_nil: true
18
+
19
+ def initialize(name, fingerprint, with_compatibility = NONE, after_compatibility = nil, *extra)
20
+ @name = name
21
+ @fingerprint = fingerprint
22
+ @with_compatibility = with_compatibility.upcase
23
+ @after_compatibility = after_compatibility.try(:upcase)
24
+ @extra = extra
25
+ end
26
+
27
+ def key
28
+ [name, fingerprint]
29
+ end
30
+
31
+ def validate!
32
+ raise ValidationError.new(errors.full_messages.join(', ')) unless valid?
33
+ end
34
+
35
+ def line
36
+ [name, fingerprint, with_compatibility, after_compatibility].compact.join(' ')
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,48 @@
1
+ module Avrolution
2
+ module CompatibilityBreaksFile
3
+
4
+ NONE = 'NONE'.freeze
5
+
6
+ class DuplicateEntryError < StandardError
7
+ def initialize(key)
8
+ super("duplicate entry for key #{key}")
9
+ end
10
+ end
11
+
12
+ def self.path
13
+ Avrolution.compatibility_breaks_file
14
+ end
15
+
16
+ def self.add(name:,
17
+ fingerprint:,
18
+ with_compatibility: NONE,
19
+ after_compatibility: nil,
20
+ logger: Avrolution.logger)
21
+
22
+ compatibility_break = Avrolution::CompatibilityBreak.new(name, fingerprint, with_compatibility, after_compatibility)
23
+ compatibility_break.validate!
24
+
25
+ compatibility_breaks = load
26
+ raise DuplicateEntryError.new([name, fingerprint]) if compatibility_breaks.key?(compatibility_break.key)
27
+
28
+ line = compatibility_break.line
29
+ File.write(path, "#{line}\n", mode: 'a')
30
+ logger.info("Added #{line.inspect} to #{path}")
31
+ end
32
+
33
+ def self.load
34
+ return {} unless File.exist?(path)
35
+
36
+ File.read(path).each_line.each_with_object({}) do |line, compatibility_breaks|
37
+ next if line.blank? || /^#/ =~ line.strip
38
+
39
+ compatibility_break = Avrolution::CompatibilityBreak.new(*line.strip.split(' '))
40
+ compatibility_break.validate!
41
+
42
+ raise DuplicateEntryError.new(compatibility_break.key) if compatibility_breaks.key?(compatibility_break.key)
43
+
44
+ compatibility_breaks[compatibility_break.key] = compatibility_break
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,108 @@
1
+ require 'private_attr'
2
+ require 'diffy'
3
+ require 'avromatic/schema_registry_patch'
4
+
5
+ module Avrolution
6
+ class CompatibilityCheck
7
+ extend PrivateAttr
8
+
9
+ attr_reader :incompatible_schemas
10
+
11
+ NONE = 'NONE'.freeze
12
+ FULL = 'FULL'.freeze
13
+ BACKWARD = 'BACKWARD'.freeze
14
+ FORWARD = 'FORWARD'.freeze
15
+
16
+ private_attr_reader :schema_registry, :compatibility_breaks,
17
+ :logger
18
+
19
+ def initialize(logger: Avrolution.logger)
20
+ @incompatible_schemas = []
21
+ @schema_registry = build_schema_registry
22
+ @compatibility_breaks = Avrolution::CompatibilityBreaksFile.load
23
+ @logger = logger
24
+ end
25
+
26
+ def call
27
+ check_schemas(Avrolution.root)
28
+ self
29
+ end
30
+
31
+ def success?
32
+ incompatible_schemas.empty?
33
+ end
34
+
35
+ private
36
+
37
+ def check_schemas(path)
38
+ Dir[File.join(path, '**/*.avsc')].each do |schema_file|
39
+ check_schema_compatibility(schema_file)
40
+ end
41
+ end
42
+
43
+ def check_schema_compatibility(file)
44
+ json = File.read(file)
45
+ schema = Avro::Schema.parse(json)
46
+ return unless schema.type_sym == :record
47
+
48
+ fullname = schema.fullname
49
+ fingerprint = schema.sha256_resolution_fingerprint.to_s(16)
50
+
51
+ logger.info("Checking compatibility: #{fullname}")
52
+ compatible = schema_registry.compatible?(fullname, schema, 'latest')
53
+
54
+ if compatible.nil?
55
+ # compatible is nil if the subject is not registered
56
+ logger.info("... New schema: #{fullname}")
57
+ elsif !compatible && !compatibility_fallback(schema, fullname, fingerprint)
58
+ incompatible_schemas << file
59
+ report_incompatibility(json, schema, fullname, fingerprint)
60
+ end
61
+ end
62
+
63
+ # For a schema that is incompatible with the latest registered schema,
64
+ # check if there is a compatibility break defined and check compatibility
65
+ # using the level defined by the break.
66
+ def compatibility_fallback(schema, fullname, fingerprint)
67
+ compatibility_break = compatibility_breaks[[fullname, fingerprint]]
68
+
69
+ if compatibility_break
70
+ logger.info("... Checking compatibility with level set to #{compatibility_break.with_compatibility}")
71
+ schema_registry.compatible?(fullname, schema, 'latest', with_compatibility: compatibility_break.with_compatibility)
72
+ else
73
+ false
74
+ end
75
+ end
76
+
77
+ def report_incompatibility(json, schema, fullname, fingerprint)
78
+ last_json = schema_registry.subject_version(fullname)['schema']
79
+ last_schema = Avro::Schema.parse(last_json)
80
+ backward = last_schema.read?(schema)
81
+ forward = schema.read?(last_schema)
82
+ compatibility_with_last = if backward && forward
83
+ FULL
84
+ elsif backward
85
+ BACKWARD
86
+ elsif forward
87
+ FORWARD
88
+ else
89
+ NONE
90
+ end
91
+
92
+ logger.info("... Compatibility with last version: #{compatibility_with_last}")
93
+ logger.info(Diffy::Diff.new(last_json, json, context: 3).to_s) unless compatibility_with_last == FULL
94
+
95
+ compatibility = schema_registry.subject_config(fullname)['compatibility'] || schema_registry.global_config['compatibility']
96
+ logger.info("... Current compatibility level: #{compatibility}")
97
+ logger.info(
98
+ "\n To allow a compatibility break, run:\n" \
99
+ " rake avro:add_compatibility_break name=#{fullname} fingerprint=#{fingerprint} with_compatibility=#{compatibility_with_last} [after_compatibility=<LEVEL>]\n"
100
+ )
101
+ end
102
+
103
+ def build_schema_registry
104
+ AvroTurf::ConfluentSchemaRegistry.new(Avrolution.compatibility_schema_registry_url,
105
+ logger: Avrolution.logger)
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,41 @@
1
+ module Avrolution
2
+
3
+ COMPATIBILITY_SCHEMA_REGISTRY_URL = 'COMPATIBILITY_SCHEMA_REGISTRY_URL'.freeze
4
+
5
+ class << self
6
+ # Root directory to search for schemas, and default location for
7
+ # compatibility breaks file
8
+ attr_writer :root
9
+
10
+ # Path to the compatibility breaks file. Defaults to
11
+ # #{Avrolution.root}/avro_compatibility_breaks.txt
12
+ attr_writer :compatibility_breaks_file
13
+
14
+ # The URL (including any Basic Auth) for the schema registry to use for
15
+ # compatibility checks
16
+ attr_writer :compatibility_schema_registry_url
17
+
18
+ attr_accessor :logger
19
+ end
20
+
21
+ self.logger = Avrolution::PassthruLogger.new($stdout)
22
+
23
+ def self.root
24
+ @root || raise('root must be set')
25
+ end
26
+
27
+ def self.compatibility_breaks_file
28
+ @compatibility_breaks_file ||= "#{root}/avro_compatibility_breaks.txt"
29
+ end
30
+
31
+ def self.compatibility_schema_registry_url
32
+ @compatibility_schema_registry_url ||= begin
33
+ raise 'compatibility_schema_registry_url must be set' unless ENV[COMPATIBILITY_SCHEMA_REGISTRY_URL]
34
+ ENV[COMPATIBILITY_SCHEMA_REGISTRY_URL]
35
+ end
36
+ end
37
+
38
+ def self.configure
39
+ yield self
40
+ end
41
+ end
@@ -0,0 +1,14 @@
1
+ module Avrolution
2
+ class Railtie < Rails::Railtie
3
+
4
+ initializer 'avrolution.configure' do
5
+ Avrolution.configure do |config|
6
+ config.root = Rails.root
7
+ end
8
+ end
9
+
10
+ rake_tasks do
11
+ load File.expand_path('../rake/rails_avrolution.rake', __FILE__)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,32 @@
1
+ require 'avrolution/rake/base_task'
2
+
3
+ module Avrolution
4
+ module Rake
5
+ class AddCompatibilityBreakTask < BaseTask
6
+
7
+ def initialize(*)
8
+ super
9
+ @name ||= :add_compatibility_break
10
+ @task_desc ||= 'Add an Avro schema compatibility break. Parameters: name, fingerprint, with_compatibility, after_compatibility'
11
+ end
12
+
13
+ private
14
+
15
+ def perform
16
+ compatibility_break_args = ENV.to_h.slice('name', 'fingerprint', 'with_compatibility', 'after_compatibility').symbolize_keys
17
+
18
+ missing_args = %i(name fingerprint).select do |arg|
19
+ compatibility_break_args[arg].blank?
20
+ end
21
+
22
+ if missing_args.any?
23
+ puts missing_args.map { |arg| "#{arg} can't be blank" }.join(', ')
24
+ puts 'Usage: rake avro:add_compatibility_break name=<name> fingerprint=<fingerprint> [with_compatibility=<default:NONE>] [after_compatibility=<compatibility>]'
25
+ exit(1)
26
+ end
27
+
28
+ Avrolution::CompatibilityBreaksFile.add(**compatibility_break_args)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,35 @@
1
+ module Avrolution
2
+ module Rake
3
+ class BaseTask < ::Rake::TaskLib
4
+
5
+ attr_accessor :name, :task_namespace, :task_desc, :dependencies
6
+
7
+ def self.define(**options, &block)
8
+ new(**options, &block).define
9
+ end
10
+
11
+ def initialize(name: nil, dependencies: [])
12
+ @name = name
13
+ @task_namespace = :avro
14
+ @dependencies = dependencies
15
+
16
+ yield self if block_given?
17
+ end
18
+
19
+ def define
20
+ namespace task_namespace do
21
+ desc task_desc
22
+ task(name.to_sym => dependencies) do
23
+ perform
24
+ end
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def perform
31
+ raise NotImplementedError
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,26 @@
1
+ require 'avrolution/rake/base_task'
2
+
3
+ module Avrolution
4
+ module Rake
5
+ class CheckCompatibilityTask < BaseTask
6
+
7
+ def initialize(*)
8
+ super
9
+ @name ||= :check_compatibility
10
+ @task_desc ||= 'Check that all Avro schemas are compatible with latest registered in production'
11
+ end
12
+
13
+ private
14
+
15
+ def perform
16
+ check = Avrolution::CompatibilityCheck.new.call
17
+ if check.success?
18
+ puts 'All schemas are compatible!'
19
+ else
20
+ puts "\nIncompatible schemas found: #{check.incompatible_schemas.join(', ')}"
21
+ exit(1)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,5 @@
1
+ require 'avrolution/rake/check_compatibility_task'
2
+ require 'avrolution/rake/add_compatibility_break_task'
3
+
4
+ Avrolution::Rake::AddCompatibilityBreakTask.define(dependencies: %i(environment))
5
+ Avrolution::Rake::CheckCompatibilityTask.define(dependencies: %i(environment))
@@ -0,0 +1,3 @@
1
+ module Avrolution
2
+ VERSION = '0.1.0'.freeze
3
+ end
data/lib/avrolution.rb ADDED
@@ -0,0 +1,19 @@
1
+ require 'avrolution/version'
2
+ require 'logger'
3
+
4
+ module Avrolution
5
+ class PassthruLogger < Logger
6
+ def initialize(*)
7
+ super
8
+ @formatter = ->(_severity, _time, _progname, msg) { "#{msg}\n" }
9
+ end
10
+ end
11
+ end
12
+
13
+ require 'active_support/core_ext/object/try'
14
+ require 'avrolution/configuration'
15
+ require 'avrolution/compatibility_break'
16
+ require 'avrolution/compatibility_breaks_file'
17
+ require 'avrolution/compatibility_check'
18
+
19
+ require 'avrolution/railtie' if defined?(Rails)
metadata ADDED
@@ -0,0 +1,253 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: avrolution
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Salsify, Inc
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-04-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.12'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.12'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
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.4'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.4'
55
+ - !ruby/object:Gem::Dependency
56
+ name: salsify_rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.47.2
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.47.2
69
+ - !ruby/object:Gem::Dependency
70
+ name: overcommit
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: fakefs
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: avro-salsify-fork
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '='
116
+ - !ruby/object:Gem::Version
117
+ version: 1.9.0.5
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '='
123
+ - !ruby/object:Gem::Version
124
+ version: 1.9.0.5
125
+ - !ruby/object:Gem::Dependency
126
+ name: avromatic
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '='
130
+ - !ruby/object:Gem::Version
131
+ version: 0.21.0.rc0
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - '='
137
+ - !ruby/object:Gem::Version
138
+ version: 0.21.0.rc0
139
+ - !ruby/object:Gem::Dependency
140
+ name: diffy
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: private_attr
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: activesupport
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :runtime
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: activemodel
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :runtime
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ description: Support for the evolution of Avro schemas stored in a schema registry.
196
+ email:
197
+ - engineering@salsify.com
198
+ executables:
199
+ - console
200
+ - setup
201
+ extensions: []
202
+ extra_rdoc_files: []
203
+ files:
204
+ - ".gitignore"
205
+ - ".overcommit.yml"
206
+ - ".rspec"
207
+ - ".rubocop.yml"
208
+ - ".travis.yml"
209
+ - CHANGELOG.md
210
+ - Gemfile
211
+ - LICENSE.txt
212
+ - README.md
213
+ - Rakefile
214
+ - avrolution.gemspec
215
+ - bin/console
216
+ - bin/setup
217
+ - lib/avrolution.rb
218
+ - lib/avrolution/compatibility_break.rb
219
+ - lib/avrolution/compatibility_breaks_file.rb
220
+ - lib/avrolution/compatibility_check.rb
221
+ - lib/avrolution/configuration.rb
222
+ - lib/avrolution/railtie.rb
223
+ - lib/avrolution/rake/add_compatibility_break_task.rb
224
+ - lib/avrolution/rake/base_task.rb
225
+ - lib/avrolution/rake/check_compatibility_task.rb
226
+ - lib/avrolution/rake/rails_avrolution.rake
227
+ - lib/avrolution/version.rb
228
+ homepage: https://github.com/salsify/avrolution
229
+ licenses:
230
+ - MIT
231
+ metadata:
232
+ allowed_push_host: https://rubygems.org
233
+ post_install_message:
234
+ rdoc_options: []
235
+ require_paths:
236
+ - lib
237
+ required_ruby_version: !ruby/object:Gem::Requirement
238
+ requirements:
239
+ - - ">="
240
+ - !ruby/object:Gem::Version
241
+ version: '0'
242
+ required_rubygems_version: !ruby/object:Gem::Requirement
243
+ requirements:
244
+ - - ">="
245
+ - !ruby/object:Gem::Version
246
+ version: '0'
247
+ requirements: []
248
+ rubyforge_project:
249
+ rubygems_version: 2.6.11
250
+ signing_key:
251
+ specification_version: 4
252
+ summary: Support for the evolution of Avro schemas stored in a schema registry.
253
+ test_files: []