ownership 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 38e0f9794b246e9f4d788f460db5aeb663f6f45e
4
+ data.tar.gz: a7d3477d27cbd3aa0cddd55269246922d198a919
5
+ SHA512:
6
+ metadata.gz: c57c183a32991967c30aba4a926d4c1ef2076b8100d4ae7aa09e32e3ea395214fe3d833209263fd399547105c3ab9484676eeba0f9ee5577889f1b60524b6146
7
+ data.tar.gz: d3df7b1a97faacd87fb05248001358244466c656a2fc9fa2fb2638a670729f9cd60ac42468d207afe1f0c68f6ff9471bec0bb992559056bb1ee787ac9999218d
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ *.lock
@@ -0,0 +1,3 @@
1
+ ## 0.1.0
2
+
3
+ - First release
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in ownership.gemspec
4
+ gemspec
@@ -0,0 +1,139 @@
1
+ # Ownership
2
+
3
+ Code ownership for your Rails app
4
+
5
+ :tangerine: Battle-tested at [Instacart](https://www.instacart.com/opensource)
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application’s Gemfile:
10
+
11
+ ```ruby
12
+ gem 'ownership'
13
+ ```
14
+
15
+ ## Getting Started
16
+
17
+ Ownership provides the ability to specify owners for different parts of the codebase. **We highly recommend owners are teams rather than individuals.** You can then use this information however you’d like, like routing errors to the correct team.
18
+
19
+ ## Specifying Ownership
20
+
21
+ ### Controllers
22
+
23
+ ```ruby
24
+ class OrdersController < ApplicationController
25
+ owner :logistics
26
+ end
27
+ ```
28
+
29
+ You can use any options that `before_action` supports.
30
+
31
+ ```ruby
32
+ class OrdersController < ApplicationController
33
+ owner :logistics, only: [:index]
34
+ owner :customers, except: [:index]
35
+ end
36
+ ```
37
+
38
+ ### Jobs
39
+
40
+ ```ruby
41
+ class SomeJob < ApplicationJob
42
+ owner :logistics
43
+ end
44
+ ```
45
+
46
+ ### Anywhere
47
+
48
+ ```ruby
49
+ owner :logistics do
50
+ # code
51
+ end
52
+ ```
53
+
54
+ ### Default
55
+
56
+ You can set a default owner with:
57
+
58
+ ```ruby
59
+ Ownership.default_owner = :logistics
60
+ ```
61
+
62
+ ## Integrations
63
+
64
+ There are a few built-in integrations with other gems.
65
+
66
+ ### Marginalia
67
+
68
+ [Marginalia](https://github.com/basecamp/marginalia) adds comments to ActiveRecord queries. If installed, the owner is added.
69
+
70
+ ```sql
71
+ SELECT ...
72
+ /*application:MyApp,controller:posts,action:index,owner:logistics*/
73
+ ```
74
+
75
+ This can be useful when looking at the most time-consuming queries on your database.
76
+
77
+ ### Rollbar
78
+
79
+ [Rollbar](https://github.com/rollbar/rollbar-gem) tracks exceptions. This integration makes it easy to send exceptions to different projects based on the owner. We recommend having a project for each team.
80
+
81
+ ```ruby
82
+ Ownership::Rollbar.access_token = {
83
+ logistics: "token1",
84
+ customers: "token2"
85
+ }
86
+ ```
87
+
88
+ Also works with a proc
89
+
90
+ ```ruby
91
+ Ownership::Rollbar.access_token = -> (owner) { ENV["#{owner.to_s.upcase}_ROLLBAR_ACCESS_TOKEN"] }
92
+ ```
93
+
94
+ ## Custom Integrations
95
+
96
+ You can define a custom block of code to run with:
97
+
98
+ ```ruby
99
+ Ownership.around_change = proc do |owner, block|
100
+ puts "New owner: #{owner}"
101
+ block.call
102
+ puts "Done"
103
+ end
104
+ ```
105
+
106
+ Please don’t hesitate to [submit a pull request](https://github.com/ankane/ownership/pulls) if you create an integration that others can use.
107
+
108
+ Exceptions that bubble up from an `owner` block have the owner, which your exception reporting library can use.
109
+
110
+ ```ruby
111
+ begin
112
+ owner :logistics do
113
+ raise "error"
114
+ end
115
+ rescue => e
116
+ puts e.owner # :logistics
117
+ end
118
+ ```
119
+
120
+ ## Other Useful Tools
121
+
122
+ - [GitHub Code Owners](https://github.com/blog/2392-introducing-code-owners) for code reviews
123
+
124
+ ## Thanks
125
+
126
+ Thanks to [Nick Elser](https://github.com/nickelser) for creating this pattern.
127
+
128
+ ## History
129
+
130
+ View the [changelog](https://github.com/ankane/ownership/blob/master/CHANGELOG.md).
131
+
132
+ ## Contributing
133
+
134
+ Everyone is encouraged to help improve this project. Here are a few ways you can help:
135
+
136
+ - [Report bugs](https://github.com/ankane/ownership/issues)
137
+ - Fix bugs and [submit pull requests](https://github.com/ankane/ownership/pulls)
138
+ - Write, clarify, or fix documentation
139
+ - Suggest or add new features
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ t.warning = false
9
+ end
10
+
11
+ task default: :test
@@ -0,0 +1,38 @@
1
+ require "ownership/global_methods"
2
+ require "ownership/rollbar"
3
+ require "ownership/version"
4
+
5
+ module Ownership
6
+ class << self
7
+ attr_accessor :default_owner
8
+ attr_accessor :around_change
9
+
10
+ def owner
11
+ Thread.current[:ownership_owner] || default_owner
12
+ end
13
+ end
14
+ end
15
+
16
+ Object.send :include, Ownership::GlobalMethods
17
+
18
+ if defined?(ActiveSupport)
19
+ ActiveSupport.on_load(:action_controller) do
20
+ require "ownership/controller_methods"
21
+ include Ownership::ControllerMethods
22
+ end
23
+
24
+ ActiveSupport.on_load(:active_record) do
25
+ require "ownership/marginalia" if defined?(Marginalia)
26
+ end
27
+
28
+ ActiveSupport.on_load(:active_job) do
29
+ require "ownership/job_methods"
30
+ include Ownership::JobMethods
31
+ end
32
+ else
33
+ require "ownership/marginalia" if defined?(Marginalia)
34
+ end
35
+
36
+ class Exception
37
+ attr_accessor :owner
38
+ end
@@ -0,0 +1,15 @@
1
+ require "active_support/concern"
2
+
3
+ module Ownership
4
+ module ControllerMethods
5
+ extend ActiveSupport::Concern
6
+
7
+ class_methods do
8
+ def owner(owner, options = {})
9
+ around_action options do |_, block|
10
+ owner(owner) { block.call }
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,26 @@
1
+ module Ownership
2
+ module GlobalMethods
3
+ def owner(owner, &block)
4
+ raise ArgumentError, "Missing block" unless block_given?
5
+
6
+ previous_value = Thread.current[:ownership_owner]
7
+ begin
8
+ Thread.current[:ownership_owner] = owner
9
+
10
+ begin
11
+ # callbacks
12
+ if Ownership.around_change
13
+ Ownership.around_change.call(owner, block)
14
+ else
15
+ block.call
16
+ end
17
+ rescue Exception => e
18
+ e.owner = owner
19
+ raise
20
+ end
21
+ ensure
22
+ Thread.current[:ownership_owner] = previous_value
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,15 @@
1
+ require "active_support/concern"
2
+
3
+ module Ownership
4
+ module JobMethods
5
+ extend ActiveSupport::Concern
6
+
7
+ class_methods do
8
+ def owner(*args)
9
+ around_perform do |_, block|
10
+ owner(*args) { block.call }
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ module Marginalia
2
+ module Comment
3
+ def self.owner
4
+ Ownership.owner
5
+ end
6
+ end
7
+ end
8
+
9
+ Marginalia::Comment.components << :owner
@@ -0,0 +1,48 @@
1
+ module Ownership
2
+ module Rollbar
3
+ class << self
4
+ attr_reader :access_token
5
+
6
+ def access_token=(access_token)
7
+ @access_token = access_token
8
+ @configure ||= configure # just once
9
+ access_token
10
+ end
11
+
12
+ private
13
+
14
+ def owner_access_token(owner)
15
+ access_token.respond_to?(:call) ? access_token.call(owner) : access_token[owner]
16
+ end
17
+
18
+ def configure
19
+ ::Rollbar.configure do |config|
20
+ config.before_process << proc do |options|
21
+ options[:scope][:ownership_owner] = Ownership.owner if Ownership.owner
22
+ end
23
+
24
+ config.transform << proc do |options|
25
+ # clean up payload
26
+ options[:payload]["data"].delete(:ownership_owner)
27
+
28
+ owner = options[:exception].owner if options[:exception].respond_to?(:owner)
29
+ unless owner
30
+ owner = options[:scope][:ownership_owner] if options[:scope].is_a?(Hash)
31
+ owner ||= Ownership.default_owner
32
+ end
33
+
34
+ if owner
35
+ access_token = owner_access_token(owner)
36
+ if access_token
37
+ options[:payload]["access_token"] = access_token
38
+ else
39
+ warn "[ownership] Missing Rollbar access token for owner: #{owner}"
40
+ end
41
+ end
42
+ end
43
+ end
44
+ true
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,3 @@
1
+ module Ownership
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,27 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "ownership/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ownership"
8
+ spec.version = Ownership::VERSION
9
+ spec.authors = ["Andrew Kane"]
10
+ spec.email = ["andrew@chartkick.com"]
11
+
12
+ spec.summary = "Code ownership for your Rails app"
13
+ spec.homepage = "https://github.com/ankane/ownership"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
16
+ f.match(%r{^(test|spec|features)/})
17
+ end
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler"
23
+ spec.add_development_dependency "rake"
24
+ spec.add_development_dependency "minitest"
25
+ spec.add_development_dependency "activejob"
26
+ spec.add_development_dependency "marginalia"
27
+ end
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ownership
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Andrew Kane
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-11-06 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: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: activejob
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: marginalia
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
+ description:
84
+ email:
85
+ - andrew@chartkick.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - CHANGELOG.md
92
+ - Gemfile
93
+ - README.md
94
+ - Rakefile
95
+ - lib/ownership.rb
96
+ - lib/ownership/controller_methods.rb
97
+ - lib/ownership/global_methods.rb
98
+ - lib/ownership/job_methods.rb
99
+ - lib/ownership/marginalia.rb
100
+ - lib/ownership/rollbar.rb
101
+ - lib/ownership/version.rb
102
+ - ownership.gemspec
103
+ homepage: https://github.com/ankane/ownership
104
+ licenses: []
105
+ metadata: {}
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ requirements: []
121
+ rubyforge_project:
122
+ rubygems_version: 2.6.13
123
+ signing_key:
124
+ specification_version: 4
125
+ summary: Code ownership for your Rails app
126
+ test_files: []