Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion ext/code_ownership/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ rb-sys = { version = "0.9.111", features = [
magnus = { version = "0.7.1" }
serde = { version = "1.0.219", features = ["derive"] }
serde_magnus = "0.9.0"
codeowners = { git = "https://github.com/rubyatscale/codeowners-rs.git", tag = "v0.2.7" }
codeowners = { git = "https://github.com/rubyatscale/codeowners-rs.git", tag = "v0.2.14" }

[dev-dependencies]
rb-sys = { version = "0.9.117", features = [
Expand Down
19 changes: 14 additions & 5 deletions ext/code_ownership/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use serde_magnus::serialize;
pub struct Team {
pub team_name: String,
pub team_config_yml: String,
pub reasons: Vec<String>,
}

fn for_team(team_name: String) -> Result<Value, Error> {
Expand All @@ -20,16 +21,24 @@ fn for_team(team_name: String) -> Result<Value, Error> {
fn for_file(file_path: String) -> Result<Option<Value>, Error> {
let run_config = build_run_config();

match runner::team_for_file(&run_config, &file_path) {
Ok(Some(team_rs)) => {
match runner::file_owner_for_file(&run_config, &file_path) {
Ok(owner) => {
if let Some(owner) = owner {
let team = Team {
team_name: team_rs.name,
team_config_yml: team_rs.path.to_string_lossy().to_string(),
team_name: owner.team.name,
team_config_yml: owner.team_config_file_path.to_string(),
reasons: owner
.sources
.iter()
.map(|source| source.to_string())
.collect(),
};
let serialized: Value = serialize(&team)?;
Ok(Some(serialized))
} else {
Ok(None)
}
}
Ok(None) => Ok(None),
Err(e) => Err(Error::new(
magnus::exception::runtime_error(),
e.to_string(),
Expand Down
6 changes: 6 additions & 0 deletions lib/code_ownership.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
require 'code_ownership/private/file_path_finder'
require 'code_ownership/private/file_path_team_cache'
require 'code_ownership/private/team_finder'
require 'code_ownership/private/for_file_output_builder'
require 'code_ownership/cli'

begin
Expand Down Expand Up @@ -44,6 +45,11 @@ def for_file(file)
Private::TeamFinder.for_file(file)
end

sig { params(file: String).returns(T.nilable(T::Hash[Symbol, String])) }
def for_file_verbose(file)
::RustCodeOwners.for_file(file)
end

sig { params(team: T.any(CodeTeams::Team, String)).returns(T::Array[String]) }
def for_team(team)
team = T.must(CodeTeams.find(team)) if team.is_a?(String)
Expand Down
23 changes: 5 additions & 18 deletions lib/code_ownership/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ def self.for_file(argv)
options[:json] = true
end

opts.on('--verbose', 'Output verbose information') do
options[:verbose] = true
end

opts.on('--help', 'Shows this prompt') do
puts opts
exit
Expand All @@ -107,24 +111,7 @@ def self.for_file(argv)
raise "Please pass in one file. Use `#{EXECUTABLE} for_file --help` for more info"
end

team = CodeOwnership.for_file(files.first)

team_name = team&.name || 'Unowned'
team_yml = team&.config_yml || 'Unowned'

if options[:json]
json = {
team_name: team_name,
team_yml: team_yml
}

puts json.to_json
else
puts <<~MSG
Team: #{team_name}
Team YML: #{team_yml}
MSG
end
puts CodeOwnership::Private::ForFileOutputBuilder.build(file_path: files.first, json: !!options[:json], verbose: !!options[:verbose])
end

def self.for_team(argv)
Expand Down
Binary file modified lib/code_ownership/code_ownership.bundle
Binary file not shown.
83 changes: 83 additions & 0 deletions lib/code_ownership/private/for_file_output_builder.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# frozen_string_literal: true

# typed: strict

module CodeOwnership
module Private
class ForFileOutputBuilder
extend T::Sig
private_class_method :new

sig { params(file_path: String, json: T::Boolean, verbose: T::Boolean).void }
def initialize(file_path:, json:, verbose:)
@file_path = file_path
@json = json
@verbose = verbose
end

sig { params(file_path: String, json: T::Boolean, verbose: T::Boolean).returns(String) }
def self.build(file_path:, json:, verbose:)
new(file_path: file_path, json: json, verbose: verbose).build
end

UNOWNED_OUTPUT = T.let(
{
team_name: 'Unowned',
team_yml: 'Unowned'
},
T::Hash[Symbol, T.untyped]
)

sig { returns(String) }
def build
result_hash = @verbose ? build_verbose : build_terse

return result_hash.to_json if @json

build_message_for(result_hash)
end

private

sig { returns(T::Hash[Symbol, T.untyped]) }
def build_verbose
result = CodeOwnership.for_file_verbose(@file_path)
return UNOWNED_OUTPUT if result.nil?

{
team_name: result[:team_name],
team_yml: result[:team_config_yml],
description: result[:reasons]
}
end

sig { returns(T::Hash[Symbol, T.untyped]) }
def build_terse
team = CodeOwnership.for_file(@file_path)

if team.nil?
UNOWNED_OUTPUT
else
{
team_name: team.name,
team_yml: team.config_yml
}
end
end

sig { params(result_hash: T::Hash[Symbol, T.untyped]).returns(String) }
def build_message_for(result_hash)
messages = ["Team: #{result_hash[:team_name]}", "Team YML: #{result_hash[:team_yml]}"]
description_list = T.let(Array(result_hash[:description]), T::Array[String])
messages << build_description_message(description_list) unless description_list.empty?
messages.last << "\n"
messages.join("\n")
end

sig { params(reasons: T::Array[String]).returns(String) }
def build_description_message(reasons)
"Description:\n- #{reasons.join("\n-")}"
end
end
end
end
2 changes: 1 addition & 1 deletion lib/code_ownership/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module CodeOwnership
VERSION = '2.0.0-1'
VERSION = '2.0.0-2'
end
40 changes: 40 additions & 0 deletions spec/lib/code_ownership/cli_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,20 @@ def initialize
end
end

context 'when run with --verbose' do
let(:argv) { ['for_file', 'app/services/my_file.rb', '--verbose'] }

it 'outputs the team info in human readable format' do
expect(CodeOwnership::Cli).to receive(:puts).with(<<~MSG)
Team: My Team
Team YML: config/teams/my_team.yml
Description:
- Owner specified in Team YML as an owned_glob `app/**/*.rb`
MSG
subject
end
end

context 'when run with no files' do
let(:argv) { ['for_file'] }

Expand Down Expand Up @@ -205,6 +219,19 @@ def initialize
expect(CodeOwnership::Cli).to receive(:puts).with(json.to_json)
subject
end

context 'when run with --verbose' do
let(:argv) { ['for_file', '--json', '--verbose', 'app/services/my_file.rb'] }
it 'outputs JSONified information to the console' do
json = {
team_name: 'My Team',
team_yml: 'config/teams/my_team.yml',
description: ['Owner specified in Team YML as an owned_glob `app/**/*.rb`']
}
expect(CodeOwnership::Cli).to receive(:puts).with(json.to_json)
subject
end
end
end

context 'when run with no files' do
Expand Down Expand Up @@ -235,6 +262,19 @@ def initialize
MSG
subject
end

context 'when run with --verbose' do
let(:argv) { ['for_file', 'app/services/unowned.rb', '--verbose'] }

it 'prints Unowned' do
allow(CodeOwnership).to receive(:for_file_verbose).and_return(nil)
expect(CodeOwnership::Cli).to receive(:puts).with(<<~MSG)
Team: Unowned
Team YML: Unowned
MSG
subject
end
end
end

context 'with --help' do
Expand Down
Loading