Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex Evanczuk committed May 9, 2022
1 parent a91d62a commit ebbcfc3
Show file tree
Hide file tree
Showing 36 changed files with 2,570 additions and 1 deletion.
43 changes: 43 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: CI

on: [push, pull_request]

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
ruby:
- 2.7
# See comment comes from https://github.com/ruby/setup-ruby#matrix-of-ruby-versions
# Due to https://github.com/actions/runner/issues/849, we have to use quotes for '3.0'
- '3.0'
- 3.1
- head
env:
BUNDLE_GEMFILE: Gemfile
name: "Tests: Ruby ${{ matrix.ruby }}"
steps:
- uses: actions/checkout@5126516654c75f76bca1de45dd82a3006d8890f9
- name: Set up Ruby ${{ matrix.ruby }}
uses: ruby/setup-ruby@bd94d6a504586da892a5753afdd1480096ed30df
with:
ruby-version: ${{ matrix.ruby }}
- name: Run tests
run: |
gem install bundler
bundle install --jobs 4 --retry 3
bundle exec rspec
static-type-checking:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@5126516654c75f76bca1de45dd82a3006d8890f9
- name: Set up Ruby
uses: ruby/setup-ruby@bd94d6a504586da892a5753afdd1480096ed30df
with:
ruby-version: head
- name: Run static type checks
run: |
gem install bundler
bundle install --jobs 4 --retry 3
bundle exec srb tc
21 changes: 21 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Publish Gem

on:
push:
branches:
- "main"
tags:
- v*
jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@5126516654c75f76bca1de45dd82a3006d8890f9

- name: Release Gem
if: contains(github.ref, 'refs/tags/v')
uses: cadwallion/publish-rubygems-action@8f9e0538302643309e4e43bf48cd34173ca48cfc
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
RUBYGEMS_API_KEY: ${{secrets.RUBYGEMS_API_KEY}}
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/.bundle/
/.yardoc
/_yardoc/
/coverage/
/doc/
/pkg/
/spec/reports/
/tmp/

# rspec failure tracking
.rspec_status
3 changes: 3 additions & 0 deletions .rspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
--format documentation
--color
--require spec_helper
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
See https://github.com/bigrails/code_ownership/releases
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
source 'https://rubygems.org'

gemspec
96 changes: 96 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
PATH
remote: .
specs:
code_ownership (1.23.0)
bigrails-teams
parse_packwerk
sorbet-runtime

GEM
remote: https://rubygems.org/
specs:
ast (2.4.2)
bigrails-teams (0.1.0)
sorbet-runtime
coderay (1.1.3)
diff-lcs (1.4.4)
method_source (1.0.0)
parse_packwerk (0.10.0)
sorbet-runtime
parser (3.1.2.0)
ast (~> 2.4.1)
pry (0.14.1)
coderay (~> 1.1)
method_source (~> 1.0)
rake (13.0.6)
rbi (0.0.14)
ast
parser (>= 2.6.4.0)
sorbet-runtime (>= 0.5.9204)
unparser
rspec (3.10.0)
rspec-core (~> 3.10.0)
rspec-expectations (~> 3.10.0)
rspec-mocks (~> 3.10.0)
rspec-core (3.10.1)
rspec-support (~> 3.10.0)
rspec-expectations (3.10.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
rspec-mocks (3.10.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
rspec-support (3.10.2)
sorbet (0.5.9889)
sorbet-static (= 0.5.9889)
sorbet-runtime (0.5.9889)
sorbet-static (0.5.9889-universal-darwin-14)
sorbet-static (0.5.9889-universal-darwin-15)
sorbet-static (0.5.9889-universal-darwin-16)
sorbet-static (0.5.9889-universal-darwin-17)
sorbet-static (0.5.9889-universal-darwin-18)
sorbet-static (0.5.9889-universal-darwin-19)
sorbet-static (0.5.9889-universal-darwin-20)
sorbet-static (0.5.9889-universal-darwin-21)
sorbet-static (0.5.9889-x86_64-linux)
spoom (1.1.11)
sorbet (>= 0.5.9204)
sorbet-runtime (>= 0.5.9204)
thor (>= 0.19.2)
tapioca (0.7.2)
bundler (>= 1.17.3)
pry (>= 0.12.2)
rbi (~> 0.0.0, >= 0.0.14)
sorbet-runtime (>= 0.5.9204)
sorbet-static (>= 0.5.9204)
spoom (~> 1.1.0, >= 1.1.11)
thor (>= 1.2.0)
yard-sorbet
thor (1.2.1)
unparser (0.6.4)
diff-lcs (~> 1.3)
parser (>= 3.1.0)
webrick (1.7.0)
yard (0.9.27)
webrick (~> 1.7.0)
yard-sorbet (0.6.1)
sorbet-runtime (>= 0.5)
yard (>= 0.9)

PLATFORMS
arm64-darwin-20
arm64-darwin-21
ruby
x86_64-darwin-20
x86_64-linux

DEPENDENCIES
code_ownership!
pry
rake
rspec (~> 3.0)
sorbet
tapioca

BUNDLED WITH
2.3.9
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2022 Gusto

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
102 changes: 101 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,101 @@
# code_ownership
# CodeOwnership
This gem helps engineering teams declare ownership of code.

Check out `lib/code_ownership.rb` to see the public API.

Check out `code_ownership_spec.rb` to see examples of how code ownership is used.

## Usage: Declaring Ownership
There are three ways to declare code ownership using this gem.
### Package-Based Ownership
Package based ownership integrates [`packwerk`](https://github.com/Shopify/packwerk) and has ownership defined per package. To define that all files within a package are owned by one team, configure your `package.yml` like this:
```yml
enforce_dependency: true
enforce_privacy: true
metadata:
owner: Team
```
### Glob-Based Ownership
In your team's configured YML (see [`bigrails-teams`](https://github.com/bigrails/bigrails-teams)), you can set `owned_globs` to be a glob of files your team owns. For example, in `my_team.yml`:
```yml
name: My Team
owned_globs:
- app/services/stuff_belonging_to_my_team/**/**
- app/controllers/other_stuff_belonging_to_my_team/**/**
```
### File-Annotation Based Ownership
File annotations are a last resort if there is no clear home for your code. File annotations go at the top of your file, and look like this:
```ruby
# @team MyTeam
```
## Usage: Reading CodeOwnership
### `for_file`
`CodeOwnership.for_file`, given a relative path to a file returns a `Teams::Team` if there is a team that owns the file, `nil` otherwise.

```ruby
CodeOwnership.for_file('path/to/file/relative/to/application/root.rb')
```

Contributor note: If you are making updates to this method or the methods getting used here, please benchmark the performance of the new implementation against the current for both `for_files` and `for_file` (with 1, 100, 1000 files).

See `code_ownership_spec.rb` for examples.

### `for_backtrace`
`CodeOwnership.for_backtrace` can be given a backtrace and will either return `nil`, or a `Teams::Team`.

```ruby
CodeOwnership.for_backtrace(exception.backtrace)
```

This will go through the backtrace, and return the first found owner of the files associated with frames within the backtrace.

See `code_ownership_spec.rb` for an example.

### `for_class`

`CodeOwnership.for_class` can be given a class and will either return `nil`, or a `Teams::Team`.

```ruby
CodeOwnership.for_class(MyClass.name)
```

Under the hood, this finds the file where the class is defined and returns the owner of that file.

See `code_ownership_spec.rb` for an example.

## Usage: Generating a `CODEOWNERS` file

A `CODEOWNERS` file defines who owns specific files or paths in a repository. When you run `bin/codeownership validate`, a `.github/CODEOWNERS` file will automatically be generated and updated.

## Proper Configuration & Validation
CodeOwnership comes with a validation function to ensure the following things are true:
1) Only one mechanism is defining file ownership. That is -- you can't have a file annotation on a file owned via package-based or glob-based ownership. This helps make ownership behavior more clear by avoiding concerns about precedence.
2) All teams referenced as an owner for any file or package is a valid team (i.e. it's in the list of `Teams.all`).
3) All files have ownership. You can specify in `unowned_globs` to represent a TODO list of files to add ownership to.
3) The `.github/CODEOWNERS` file is up to date. This is automatically corrected and staged unless specified otherwise with `bin/codeownership validate --skip-autocorrect --skip-stage`. You can turn this validation off by setting `skip_codeowners_validation: true` in `code_ownership.yml`.

CodeOwnership also allows you to specify which globs and file extensions should be considered ownable.

Here is an example `config/code_ownership.yml`.
```yml
owned_globs:
- '{app,components,config,frontend,lib,packs,spec}/**/*.{rb,rake,js,jsx,ts,tsx}'
unowned_globs:
- db/**/*
- app/services/some_file1.rb
- app/services/some_file2.rb
- frontend/javascripts/**/__generated__/**/*
```
You can call the validation function with the Ruby API
```ruby
CodeOwnership.validate!
```
or the CLI
```
bin/codeownership validate
```
## Development
Please add to `CHANGELOG.md` and this `README.md` when you make make changes.
5 changes: 5 additions & 0 deletions bin/codeownership
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env ruby
# typed: strict

require 'code_ownership'
CodeOwnership::Cli.run!(ARGV)
38 changes: 38 additions & 0 deletions code_ownership.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
Gem::Specification.new do |spec|
spec.name = "code_ownership"
spec.version = '1.23.0'
spec.authors = ['Gusto Engineers']
spec.email = ['[email protected]']
spec.summary = 'A gem to help engineering teams declare ownership of code'
spec.description = 'A gem to help engineering teams declare ownership of code'
spec.homepage = 'https://github.com/bigrails/code_ownership'
spec.license = 'MIT'

if spec.respond_to?(:metadata)
spec.metadata['homepage_uri'] = spec.homepage
spec.metadata['source_code_uri'] = 'https://github.com/bigrails/code_ownership'
spec.metadata['changelog_uri'] = 'https://github.com/bigrails/code_ownership/releases'
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
else
raise 'RubyGems 2.0 or newer is required to protect against ' \
'public gem pushes.'
end
# https://guides.rubygems.org/make-your-own-gem/#adding-an-executable
# and
# https://bundler.io/blog/2015/03/20/moving-bins-to-exe.html
spec.executables = ['codeownership']

# Specify which files should be added to the gem when it is released.
spec.files = Dir['README.md', 'sorbet/**/*', 'lib/**/*', 'bin/**/*']
spec.require_paths = ['lib']

spec.add_dependency 'bigrails-teams'
spec.add_dependency 'parse_packwerk'
spec.add_dependency 'sorbet-runtime'

spec.add_development_dependency 'rake'
spec.add_development_dependency 'pry'
spec.add_development_dependency 'rspec', '~> 3.0'
spec.add_development_dependency 'sorbet'
spec.add_development_dependency 'tapioca'
end
2 changes: 2 additions & 0 deletions config/code_ownership.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
owned_globs:
- '{app,components,config,frontend,lib,packs,spec}/**/*.{rb,rake,js,jsx,ts,tsx}'
Loading

0 comments on commit ebbcfc3

Please sign in to comment.