ownership 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []