Skip to content

Commit 2309355

Browse files
authored
Update codeowners-rs and new for_file --verbose option (#129)
* providng a for-file verbose option * extracting ForFileOutputBuilder for clarity * bump version
1 parent 7e6d720 commit 2309355

File tree

9 files changed

+152
-27
lines changed

9 files changed

+152
-27
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/code_ownership/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ rb-sys = { version = "0.9.111", features = [
1717
magnus = { version = "0.7.1" }
1818
serde = { version = "1.0.219", features = ["derive"] }
1919
serde_magnus = "0.9.0"
20-
codeowners = { git = "https://github.com/rubyatscale/codeowners-rs.git", tag = "v0.2.7" }
20+
codeowners = { git = "https://github.com/rubyatscale/codeowners-rs.git", tag = "v0.2.14" }
2121

2222
[dev-dependencies]
2323
rb-sys = { version = "0.9.117", features = [

ext/code_ownership/src/lib.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use serde_magnus::serialize;
99
pub struct Team {
1010
pub team_name: String,
1111
pub team_config_yml: String,
12+
pub reasons: Vec<String>,
1213
}
1314

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

23-
match runner::team_for_file(&run_config, &file_path) {
24-
Ok(Some(team_rs)) => {
24+
match runner::file_owner_for_file(&run_config, &file_path) {
25+
Ok(owner) => {
26+
if let Some(owner) = owner {
2527
let team = Team {
26-
team_name: team_rs.name,
27-
team_config_yml: team_rs.path.to_string_lossy().to_string(),
28+
team_name: owner.team.name,
29+
team_config_yml: owner.team_config_file_path.to_string(),
30+
reasons: owner
31+
.sources
32+
.iter()
33+
.map(|source| source.to_string())
34+
.collect(),
2835
};
2936
let serialized: Value = serialize(&team)?;
3037
Ok(Some(serialized))
38+
} else {
39+
Ok(None)
40+
}
3141
}
32-
Ok(None) => Ok(None),
3342
Err(e) => Err(Error::new(
3443
magnus::exception::runtime_error(),
3544
e.to_string(),

lib/code_ownership.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
require 'code_ownership/private/file_path_finder'
1212
require 'code_ownership/private/file_path_team_cache'
1313
require 'code_ownership/private/team_finder'
14+
require 'code_ownership/private/for_file_output_builder'
1415
require 'code_ownership/cli'
1516

1617
begin
@@ -44,6 +45,11 @@ def for_file(file)
4445
Private::TeamFinder.for_file(file)
4546
end
4647

48+
sig { params(file: String).returns(T.nilable(T::Hash[Symbol, String])) }
49+
def for_file_verbose(file)
50+
::RustCodeOwners.for_file(file)
51+
end
52+
4753
sig { params(team: T.any(CodeTeams::Team, String)).returns(T::Array[String]) }
4854
def for_team(team)
4955
team = T.must(CodeTeams.find(team)) if team.is_a?(String)

lib/code_ownership/cli.rb

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ def self.for_file(argv)
9595
options[:json] = true
9696
end
9797

98+
opts.on('--verbose', 'Output verbose information') do
99+
options[:verbose] = true
100+
end
101+
98102
opts.on('--help', 'Shows this prompt') do
99103
puts opts
100104
exit
@@ -107,24 +111,7 @@ def self.for_file(argv)
107111
raise "Please pass in one file. Use `#{EXECUTABLE} for_file --help` for more info"
108112
end
109113

110-
team = CodeOwnership.for_file(files.first)
111-
112-
team_name = team&.name || 'Unowned'
113-
team_yml = team&.config_yml || 'Unowned'
114-
115-
if options[:json]
116-
json = {
117-
team_name: team_name,
118-
team_yml: team_yml
119-
}
120-
121-
puts json.to_json
122-
else
123-
puts <<~MSG
124-
Team: #{team_name}
125-
Team YML: #{team_yml}
126-
MSG
127-
end
114+
puts CodeOwnership::Private::ForFileOutputBuilder.build(file_path: files.first, json: !!options[:json], verbose: !!options[:verbose])
128115
end
129116

130117
def self.for_team(argv)
58.4 KB
Binary file not shown.
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# frozen_string_literal: true
2+
3+
# typed: strict
4+
5+
module CodeOwnership
6+
module Private
7+
class ForFileOutputBuilder
8+
extend T::Sig
9+
private_class_method :new
10+
11+
sig { params(file_path: String, json: T::Boolean, verbose: T::Boolean).void }
12+
def initialize(file_path:, json:, verbose:)
13+
@file_path = file_path
14+
@json = json
15+
@verbose = verbose
16+
end
17+
18+
sig { params(file_path: String, json: T::Boolean, verbose: T::Boolean).returns(String) }
19+
def self.build(file_path:, json:, verbose:)
20+
new(file_path: file_path, json: json, verbose: verbose).build
21+
end
22+
23+
UNOWNED_OUTPUT = T.let(
24+
{
25+
team_name: 'Unowned',
26+
team_yml: 'Unowned'
27+
},
28+
T::Hash[Symbol, T.untyped]
29+
)
30+
31+
sig { returns(String) }
32+
def build
33+
result_hash = @verbose ? build_verbose : build_terse
34+
35+
return result_hash.to_json if @json
36+
37+
build_message_for(result_hash)
38+
end
39+
40+
private
41+
42+
sig { returns(T::Hash[Symbol, T.untyped]) }
43+
def build_verbose
44+
result = CodeOwnership.for_file_verbose(@file_path)
45+
return UNOWNED_OUTPUT if result.nil?
46+
47+
{
48+
team_name: result[:team_name],
49+
team_yml: result[:team_config_yml],
50+
description: result[:reasons]
51+
}
52+
end
53+
54+
sig { returns(T::Hash[Symbol, T.untyped]) }
55+
def build_terse
56+
team = CodeOwnership.for_file(@file_path)
57+
58+
if team.nil?
59+
UNOWNED_OUTPUT
60+
else
61+
{
62+
team_name: team.name,
63+
team_yml: team.config_yml
64+
}
65+
end
66+
end
67+
68+
sig { params(result_hash: T::Hash[Symbol, T.untyped]).returns(String) }
69+
def build_message_for(result_hash)
70+
messages = ["Team: #{result_hash[:team_name]}", "Team YML: #{result_hash[:team_yml]}"]
71+
description_list = T.let(Array(result_hash[:description]), T::Array[String])
72+
messages << build_description_message(description_list) unless description_list.empty?
73+
messages.last << "\n"
74+
messages.join("\n")
75+
end
76+
77+
sig { params(reasons: T::Array[String]).returns(String) }
78+
def build_description_message(reasons)
79+
"Description:\n- #{reasons.join("\n-")}"
80+
end
81+
end
82+
end
83+
end

lib/code_ownership/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# frozen_string_literal: true
22

33
module CodeOwnership
4-
VERSION = '2.0.0-1'
4+
VERSION = '2.0.0-2'
55
end

spec/lib/code_ownership/cli_spec.rb

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,20 @@ def initialize
176176
end
177177
end
178178

179+
context 'when run with --verbose' do
180+
let(:argv) { ['for_file', 'app/services/my_file.rb', '--verbose'] }
181+
182+
it 'outputs the team info in human readable format' do
183+
expect(CodeOwnership::Cli).to receive(:puts).with(<<~MSG)
184+
Team: My Team
185+
Team YML: config/teams/my_team.yml
186+
Description:
187+
- Owner specified in Team YML as an owned_glob `app/**/*.rb`
188+
MSG
189+
subject
190+
end
191+
end
192+
179193
context 'when run with no files' do
180194
let(:argv) { ['for_file'] }
181195

@@ -205,6 +219,19 @@ def initialize
205219
expect(CodeOwnership::Cli).to receive(:puts).with(json.to_json)
206220
subject
207221
end
222+
223+
context 'when run with --verbose' do
224+
let(:argv) { ['for_file', '--json', '--verbose', 'app/services/my_file.rb'] }
225+
it 'outputs JSONified information to the console' do
226+
json = {
227+
team_name: 'My Team',
228+
team_yml: 'config/teams/my_team.yml',
229+
description: ['Owner specified in Team YML as an owned_glob `app/**/*.rb`']
230+
}
231+
expect(CodeOwnership::Cli).to receive(:puts).with(json.to_json)
232+
subject
233+
end
234+
end
208235
end
209236

210237
context 'when run with no files' do
@@ -235,6 +262,19 @@ def initialize
235262
MSG
236263
subject
237264
end
265+
266+
context 'when run with --verbose' do
267+
let(:argv) { ['for_file', 'app/services/unowned.rb', '--verbose'] }
268+
269+
it 'prints Unowned' do
270+
allow(CodeOwnership).to receive(:for_file_verbose).and_return(nil)
271+
expect(CodeOwnership::Cli).to receive(:puts).with(<<~MSG)
272+
Team: Unowned
273+
Team YML: Unowned
274+
MSG
275+
subject
276+
end
277+
end
238278
end
239279

240280
context 'with --help' do

0 commit comments

Comments
 (0)