packs 0.0.6 → 0.0.23
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.
- checksums.yaml +4 -4
- data/README.md +120 -4
- data/bin/packs +10 -0
- data/bin/rubocop +29 -0
- data/bin/tapioca +29 -0
- data/lib/packs/cli.rb +164 -0
- data/lib/packs/code_ownership_post_processor.rb +58 -0
- data/lib/packs/configuration.rb +61 -0
- data/lib/packs/default_user_event_logger.rb +7 -0
- data/lib/packs/logging.rb +37 -0
- data/lib/packs/per_file_processor_interface.rb +18 -0
- data/lib/packs/private/file_move_operation.rb +80 -0
- data/lib/packs/private/interactive_cli/file_selector.rb +26 -0
- data/lib/packs/private/interactive_cli/pack_selector.rb +55 -0
- data/lib/packs/private/interactive_cli/team_selector.rb +58 -0
- data/lib/packs/private/interactive_cli/use_cases/add_dependency.rb +30 -0
- data/lib/packs/private/interactive_cli/use_cases/check.rb +25 -0
- data/lib/packs/private/interactive_cli/use_cases/create.rb +27 -0
- data/lib/packs/private/interactive_cli/use_cases/get_info.rb +37 -0
- data/lib/packs/private/interactive_cli/use_cases/interface.rb +34 -0
- data/lib/packs/private/interactive_cli/use_cases/lint_package_todo_yml_files.rb +25 -0
- data/lib/packs/private/interactive_cli/use_cases/lint_package_yml_files.rb +26 -0
- data/lib/packs/private/interactive_cli/use_cases/make_public.rb +30 -0
- data/lib/packs/private/interactive_cli/use_cases/move.rb +32 -0
- data/lib/packs/private/interactive_cli/use_cases/move_to_parent.rb +31 -0
- data/lib/packs/private/interactive_cli/use_cases/query.rb +51 -0
- data/lib/packs/private/interactive_cli/use_cases/rename.rb +25 -0
- data/lib/packs/private/interactive_cli/use_cases/update.rb +25 -0
- data/lib/packs/private/interactive_cli/use_cases/validate.rb +25 -0
- data/lib/packs/private/interactive_cli/use_cases/visualize.rb +44 -0
- data/lib/packs/private/interactive_cli.rb +52 -0
- data/lib/packs/private/pack_relationship_analyzer.rb +135 -0
- data/lib/packs/private/packwerk_wrapper/offenses_aggregator_formatter.rb +44 -0
- data/lib/packs/private/packwerk_wrapper.rb +70 -0
- data/lib/packs/private.rb +606 -4
- data/lib/packs/rubocop_post_processor.rb +30 -0
- data/lib/packs/user_event_logger.rb +199 -0
- data/lib/packs.rb +233 -53
- metadata +225 -14
- data/lib/packs/pack.rb +0 -48
- data/lib/packs/private/configuration.rb +0 -36
- data/lib/packs/rspec/fixture_helper.rb +0 -33
- data/lib/packs/rspec/support.rb +0 -21
@@ -0,0 +1,55 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
module Packs
|
4
|
+
module Private
|
5
|
+
module InteractiveCli
|
6
|
+
class PackSelector
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
sig { params(prompt: TTY::Prompt, question_text: String).returns(Packs::Pack) }
|
10
|
+
def self.single_pack_select(prompt, question_text: 'Please use space to select a pack')
|
11
|
+
packs = Packs.all.to_h { |t| [t.name, t] }
|
12
|
+
|
13
|
+
pack_selection = T.let(prompt.select(
|
14
|
+
question_text,
|
15
|
+
packs,
|
16
|
+
filter: true,
|
17
|
+
per_page: 10,
|
18
|
+
show_help: :always
|
19
|
+
), T.nilable(Packs::Pack))
|
20
|
+
|
21
|
+
while pack_selection.nil?
|
22
|
+
prompt.error(
|
23
|
+
'No packs were selected, please select a pack using the space key before pressing enter.'
|
24
|
+
)
|
25
|
+
|
26
|
+
pack_selection = single_pack_select(prompt, question_text: question_text)
|
27
|
+
end
|
28
|
+
|
29
|
+
pack_selection
|
30
|
+
end
|
31
|
+
|
32
|
+
sig { params(prompt: TTY::Prompt, question_text: String).returns(T::Array[Packs::Pack]) }
|
33
|
+
def self.single_or_all_pack_multi_select(prompt, question_text: 'Please use space to select one or more packs')
|
34
|
+
pack_selection = T.let(prompt.multi_select(
|
35
|
+
question_text,
|
36
|
+
Packs.all.to_h { |t| [t.name, t] },
|
37
|
+
filter: true,
|
38
|
+
per_page: 10,
|
39
|
+
show_help: :always
|
40
|
+
), T::Array[Packs::Pack])
|
41
|
+
|
42
|
+
while pack_selection.empty?
|
43
|
+
prompt.error(
|
44
|
+
'No packs were selected, please select one or more packs using the space key before pressing enter.'
|
45
|
+
)
|
46
|
+
|
47
|
+
pack_selection = single_or_all_pack_multi_select(prompt, question_text: question_text)
|
48
|
+
end
|
49
|
+
|
50
|
+
pack_selection
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
module Packs
|
4
|
+
module Private
|
5
|
+
module InteractiveCli
|
6
|
+
class TeamSelector
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
sig { params(prompt: TTY::Prompt, question_text: String).returns(T.nilable(CodeTeams::Team)) }
|
10
|
+
def self.single_select(prompt, question_text: 'Please use space to select a team owner')
|
11
|
+
teams = CodeTeams.all.sort_by(&:name).to_h { |t| [t.name, t] }
|
12
|
+
return nil if teams.count == 0
|
13
|
+
|
14
|
+
team_selection = T.let(prompt.select(
|
15
|
+
question_text,
|
16
|
+
teams,
|
17
|
+
filter: true,
|
18
|
+
per_page: 10,
|
19
|
+
show_help: :always
|
20
|
+
), T.nilable(CodeTeams::Team))
|
21
|
+
|
22
|
+
while team_selection.nil?
|
23
|
+
prompt.error(
|
24
|
+
'No owners were selected, please select an owner using the space key before pressing enter.'
|
25
|
+
)
|
26
|
+
|
27
|
+
team_selection = single_select(prompt, question_text: question_text)
|
28
|
+
end
|
29
|
+
|
30
|
+
team_selection
|
31
|
+
end
|
32
|
+
|
33
|
+
sig { params(prompt: TTY::Prompt, question_text: String).returns(T::Array[CodeTeams::Team]) }
|
34
|
+
def self.multi_select(prompt, question_text: 'Please use space to select team owners')
|
35
|
+
teams = CodeTeams.all.to_h { |t| [t.name, t] }
|
36
|
+
|
37
|
+
team_selection = T.let(prompt.multi_select(
|
38
|
+
question_text,
|
39
|
+
teams,
|
40
|
+
filter: true,
|
41
|
+
per_page: 10,
|
42
|
+
show_help: :always
|
43
|
+
), T::Array[CodeTeams::Team])
|
44
|
+
|
45
|
+
while team_selection.empty?
|
46
|
+
prompt.error(
|
47
|
+
'No owners were selected, please select one or more owners using the space key before pressing enter.'
|
48
|
+
)
|
49
|
+
|
50
|
+
team_selection = multi_select(prompt, question_text: question_text)
|
51
|
+
end
|
52
|
+
|
53
|
+
team_selection
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
module Packs
|
4
|
+
module Private
|
5
|
+
module InteractiveCli
|
6
|
+
module UseCases
|
7
|
+
class AddDependency
|
8
|
+
extend T::Sig
|
9
|
+
extend T::Helpers
|
10
|
+
include Interface
|
11
|
+
|
12
|
+
sig { override.params(prompt: TTY::Prompt).void }
|
13
|
+
def perform!(prompt)
|
14
|
+
dependent_pack = PackSelector.single_pack_select(prompt, question_text: 'Please select the pack you are adding a dependency to.')
|
15
|
+
dependency_pack = PackSelector.single_pack_select(prompt, question_text: "Please select the pack that #{dependent_pack.name} should depend on.")
|
16
|
+
Packs.add_dependency!(
|
17
|
+
pack_name: dependent_pack.name,
|
18
|
+
dependency_name: dependency_pack.name
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
sig { override.returns(String) }
|
23
|
+
def user_facing_name
|
24
|
+
'Add a dependency'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
module Packs
|
4
|
+
module Private
|
5
|
+
module InteractiveCli
|
6
|
+
module UseCases
|
7
|
+
class Check
|
8
|
+
extend T::Sig
|
9
|
+
extend T::Helpers
|
10
|
+
include Interface
|
11
|
+
|
12
|
+
sig { override.returns(String) }
|
13
|
+
def user_facing_name
|
14
|
+
'Run bin/packwerk check'
|
15
|
+
end
|
16
|
+
|
17
|
+
sig { override.params(prompt: TTY::Prompt).void }
|
18
|
+
def perform!(prompt)
|
19
|
+
system('bin/packwerk check')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
module Packs
|
4
|
+
module Private
|
5
|
+
module InteractiveCli
|
6
|
+
module UseCases
|
7
|
+
class Create
|
8
|
+
extend T::Sig
|
9
|
+
extend T::Helpers
|
10
|
+
include Interface
|
11
|
+
|
12
|
+
sig { override.params(prompt: TTY::Prompt).void }
|
13
|
+
def perform!(prompt)
|
14
|
+
pack_name = prompt.ask('What should the name of your pack be?', value: 'packs/')
|
15
|
+
team = TeamSelector.single_select(prompt)
|
16
|
+
Packs.create_pack!(pack_name: pack_name, team: team)
|
17
|
+
end
|
18
|
+
|
19
|
+
sig { override.returns(String) }
|
20
|
+
def user_facing_name
|
21
|
+
'Create a new pack'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
module Packs
|
4
|
+
module Private
|
5
|
+
module InteractiveCli
|
6
|
+
module UseCases
|
7
|
+
class GetInfo
|
8
|
+
extend T::Sig
|
9
|
+
extend T::Helpers
|
10
|
+
include Interface
|
11
|
+
|
12
|
+
sig { override.returns(String) }
|
13
|
+
def user_facing_name
|
14
|
+
'Get info on one or more packs'
|
15
|
+
end
|
16
|
+
|
17
|
+
sig { override.params(prompt: TTY::Prompt).void }
|
18
|
+
def perform!(prompt)
|
19
|
+
team_or_pack = prompt.select('Do you want info by team or by pack?', ['By team', 'By pack'])
|
20
|
+
if team_or_pack == 'By team'
|
21
|
+
teams = TeamSelector.multi_select(prompt)
|
22
|
+
selected_packs = Packs.all.select do |p|
|
23
|
+
teams.map(&:name).include?(CodeOwnership.for_package(p)&.name)
|
24
|
+
end
|
25
|
+
else
|
26
|
+
selected_packs = PackSelector.single_or_all_pack_multi_select(prompt, question_text: 'What pack(s) would you like info on?')
|
27
|
+
end
|
28
|
+
|
29
|
+
puts "You've selected #{selected_packs.count} packs. Wow! Here's all the info."
|
30
|
+
|
31
|
+
Private.get_info(packs: selected_packs)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
module Packs
|
4
|
+
module Private
|
5
|
+
module InteractiveCli
|
6
|
+
module UseCases
|
7
|
+
module Interface
|
8
|
+
extend T::Sig
|
9
|
+
extend T::Helpers
|
10
|
+
|
11
|
+
interface!
|
12
|
+
|
13
|
+
sig { params(base: Class).void }
|
14
|
+
def self.included(base)
|
15
|
+
@use_cases ||= T.let(@use_cases, T.nilable(T::Array[Class]))
|
16
|
+
@use_cases ||= []
|
17
|
+
@use_cases << base
|
18
|
+
end
|
19
|
+
|
20
|
+
sig { returns(T::Array[Interface]) }
|
21
|
+
def self.all
|
22
|
+
T.unsafe(@use_cases).map(&:new)
|
23
|
+
end
|
24
|
+
|
25
|
+
sig { abstract.params(prompt: TTY::Prompt).void }
|
26
|
+
def perform!(prompt); end
|
27
|
+
|
28
|
+
sig { abstract.returns(String) }
|
29
|
+
def user_facing_name; end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
module Packs
|
4
|
+
module Private
|
5
|
+
module InteractiveCli
|
6
|
+
module UseCases
|
7
|
+
class LintPackageYmlTodoFiles
|
8
|
+
extend T::Sig
|
9
|
+
extend T::Helpers
|
10
|
+
include Interface
|
11
|
+
|
12
|
+
sig { override.params(prompt: TTY::Prompt).void }
|
13
|
+
def perform!(prompt)
|
14
|
+
Private.lint_package_todo_yml_files!
|
15
|
+
end
|
16
|
+
|
17
|
+
sig { override.returns(String) }
|
18
|
+
def user_facing_name
|
19
|
+
'Lint .package_todo.yml files'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
module Packs
|
4
|
+
module Private
|
5
|
+
module InteractiveCli
|
6
|
+
module UseCases
|
7
|
+
class LintPackageYmlFiles
|
8
|
+
extend T::Sig
|
9
|
+
extend T::Helpers
|
10
|
+
include Interface
|
11
|
+
|
12
|
+
sig { override.params(prompt: TTY::Prompt).void }
|
13
|
+
def perform!(prompt)
|
14
|
+
packs = PackSelector.single_or_all_pack_multi_select(prompt, question_text: 'Please select the packs you want to lint package.yml files for')
|
15
|
+
Packs.lint_package_yml_files!(packs)
|
16
|
+
end
|
17
|
+
|
18
|
+
sig { override.returns(String) }
|
19
|
+
def user_facing_name
|
20
|
+
'Lint packs/*/package.yml for one or more packs'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
module Packs
|
4
|
+
module Private
|
5
|
+
module InteractiveCli
|
6
|
+
module UseCases
|
7
|
+
class MakePublic
|
8
|
+
extend T::Sig
|
9
|
+
extend T::Helpers
|
10
|
+
include Interface
|
11
|
+
|
12
|
+
sig { override.returns(String) }
|
13
|
+
def user_facing_name
|
14
|
+
'Make files or directories public'
|
15
|
+
end
|
16
|
+
|
17
|
+
sig { override.params(prompt: TTY::Prompt).void }
|
18
|
+
def perform!(prompt)
|
19
|
+
paths_relative_to_root = FileSelector.select(prompt)
|
20
|
+
|
21
|
+
Packs.make_public!(
|
22
|
+
paths_relative_to_root: paths_relative_to_root,
|
23
|
+
per_file_processors: [Packs::RubocopPostProcessor.new, Packs::CodeOwnershipPostProcessor.new]
|
24
|
+
)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
module Packs
|
4
|
+
module Private
|
5
|
+
module InteractiveCli
|
6
|
+
module UseCases
|
7
|
+
class Move
|
8
|
+
extend T::Sig
|
9
|
+
extend T::Helpers
|
10
|
+
include Interface
|
11
|
+
|
12
|
+
sig { override.params(prompt: TTY::Prompt).void }
|
13
|
+
def perform!(prompt)
|
14
|
+
pack = PackSelector.single_pack_select(prompt, question_text: 'Please select a destination pack')
|
15
|
+
paths_relative_to_root = FileSelector.select(prompt)
|
16
|
+
|
17
|
+
Packs.move_to_pack!(
|
18
|
+
pack_name: pack.name,
|
19
|
+
paths_relative_to_root: paths_relative_to_root,
|
20
|
+
per_file_processors: [Packs::RubocopPostProcessor.new, Packs::CodeOwnershipPostProcessor.new]
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
sig { override.returns(String) }
|
25
|
+
def user_facing_name
|
26
|
+
'Move files'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
module Packs
|
4
|
+
module Private
|
5
|
+
module InteractiveCli
|
6
|
+
module UseCases
|
7
|
+
class MoveToParent
|
8
|
+
extend T::Sig
|
9
|
+
extend T::Helpers
|
10
|
+
include Interface
|
11
|
+
|
12
|
+
sig { override.params(prompt: TTY::Prompt).void }
|
13
|
+
def perform!(prompt)
|
14
|
+
child_pack = PackSelector.single_pack_select(prompt, question_text: 'Please select the child pack that will be nested')
|
15
|
+
parent_pack = PackSelector.single_pack_select(prompt, question_text: 'Please select the pack that will be the parent')
|
16
|
+
Packs.move_to_parent!(
|
17
|
+
parent_name: parent_pack.name,
|
18
|
+
pack_name: child_pack.name,
|
19
|
+
per_file_processors: [Packs::RubocopPostProcessor.new, Packs::CodeOwnershipPostProcessor.new]
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
sig { override.returns(String) }
|
24
|
+
def user_facing_name
|
25
|
+
'Move a child pack to be nested under a parent pack'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
module Packs
|
4
|
+
module Private
|
5
|
+
module InteractiveCli
|
6
|
+
module UseCases
|
7
|
+
#
|
8
|
+
# We have not yet pulled QueryPackwerk into open source, so we cannot include it in this CLI yet
|
9
|
+
#
|
10
|
+
class Query
|
11
|
+
extend T::Sig
|
12
|
+
extend T::Helpers
|
13
|
+
include Interface
|
14
|
+
|
15
|
+
sig { override.returns(String) }
|
16
|
+
def user_facing_name
|
17
|
+
'Query violations about a pack'
|
18
|
+
end
|
19
|
+
|
20
|
+
sig { override.params(prompt: TTY::Prompt).void }
|
21
|
+
def perform!(prompt)
|
22
|
+
selection = prompt.select('For one pack or all packs?', ['One pack', 'All packs'])
|
23
|
+
if selection == 'All packs'
|
24
|
+
# Probably should just make `list_top_dependency_violations` take in an array of things
|
25
|
+
# Better yet we might just want to replace these functions with `QueryPackwerk`
|
26
|
+
selected_pack = nil
|
27
|
+
else
|
28
|
+
selected_pack = PackSelector.single_pack_select(prompt).name
|
29
|
+
end
|
30
|
+
|
31
|
+
limit = prompt.ask('Specify the limit of constants to analyze', default: 10, convert: :integer)
|
32
|
+
|
33
|
+
selection = prompt.select('Are you interested in dependency or privacy violations?', %w[Dependency Privacy], default: 'Privacy')
|
34
|
+
|
35
|
+
if selection == 'Dependency'
|
36
|
+
Packs.list_top_dependency_violations(
|
37
|
+
pack_name: selected_pack,
|
38
|
+
limit: limit
|
39
|
+
)
|
40
|
+
else
|
41
|
+
Packs.list_top_privacy_violations(
|
42
|
+
pack_name: selected_pack,
|
43
|
+
limit: limit
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
module Packs
|
4
|
+
module Private
|
5
|
+
module InteractiveCli
|
6
|
+
module UseCases
|
7
|
+
class Rename
|
8
|
+
extend T::Sig
|
9
|
+
extend T::Helpers
|
10
|
+
include Interface
|
11
|
+
|
12
|
+
sig { override.returns(String) }
|
13
|
+
def user_facing_name
|
14
|
+
'Rename a pack'
|
15
|
+
end
|
16
|
+
|
17
|
+
sig { override.params(prompt: TTY::Prompt).void }
|
18
|
+
def perform!(prompt)
|
19
|
+
prompt.warn(Private.rename_pack)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
module Packs
|
4
|
+
module Private
|
5
|
+
module InteractiveCli
|
6
|
+
module UseCases
|
7
|
+
class Update
|
8
|
+
extend T::Sig
|
9
|
+
extend T::Helpers
|
10
|
+
include Interface
|
11
|
+
|
12
|
+
sig { override.returns(String) }
|
13
|
+
def user_facing_name
|
14
|
+
'Run bin/packwerk update'
|
15
|
+
end
|
16
|
+
|
17
|
+
sig { override.params(prompt: TTY::Prompt).void }
|
18
|
+
def perform!(prompt)
|
19
|
+
system('bin/packwerk update')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
module Packs
|
4
|
+
module Private
|
5
|
+
module InteractiveCli
|
6
|
+
module UseCases
|
7
|
+
class Validate
|
8
|
+
extend T::Sig
|
9
|
+
extend T::Helpers
|
10
|
+
include Interface
|
11
|
+
|
12
|
+
sig { override.returns(String) }
|
13
|
+
def user_facing_name
|
14
|
+
'Run bin/packwerk validate (detects cycles)'
|
15
|
+
end
|
16
|
+
|
17
|
+
sig { override.params(prompt: TTY::Prompt).void }
|
18
|
+
def perform!(prompt)
|
19
|
+
system('bin/packwerk validate')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
require 'visualize_packs'
|
4
|
+
|
5
|
+
module Packs
|
6
|
+
module Private
|
7
|
+
module InteractiveCli
|
8
|
+
module UseCases
|
9
|
+
class Visualize
|
10
|
+
extend T::Sig
|
11
|
+
extend T::Helpers
|
12
|
+
include Interface
|
13
|
+
|
14
|
+
sig { override.params(prompt: TTY::Prompt).void }
|
15
|
+
def perform!(prompt)
|
16
|
+
teams_or_packs = prompt.select('Do you want the graph nodes to be teams or packs?', %w[Teams Packs])
|
17
|
+
|
18
|
+
if teams_or_packs == 'Teams'
|
19
|
+
teams = TeamSelector.multi_select(prompt)
|
20
|
+
VisualizePacks.team_graph!(teams)
|
21
|
+
else
|
22
|
+
by_name_or_by_owner = prompt.select('Do you select packs by name or by owner?', ['By name', 'By owner'])
|
23
|
+
if by_name_or_by_owner == 'By owner'
|
24
|
+
teams = TeamSelector.multi_select(prompt)
|
25
|
+
selected_packs = Packs.all.select do |p|
|
26
|
+
teams.map(&:name).include?(CodeOwnership.for_package(p)&.name)
|
27
|
+
end
|
28
|
+
else
|
29
|
+
selected_packs = PackSelector.single_or_all_pack_multi_select(prompt)
|
30
|
+
end
|
31
|
+
|
32
|
+
Private.visualize(packs: selected_packs)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
sig { override.returns(String) }
|
37
|
+
def user_facing_name
|
38
|
+
'Visualize pack relationships'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# typed: strict
|
2
|
+
|
3
|
+
# https://github.com/piotrmurach/tty-prompt
|
4
|
+
require 'tty-prompt'
|
5
|
+
|
6
|
+
require 'packs/private/interactive_cli/team_selector'
|
7
|
+
require 'packs/private/interactive_cli/pack_selector'
|
8
|
+
require 'packs/private/interactive_cli/file_selector'
|
9
|
+
require 'packs/private/interactive_cli/use_cases/interface'
|
10
|
+
require 'packs/private/interactive_cli/use_cases/create'
|
11
|
+
require 'packs/private/interactive_cli/use_cases/move'
|
12
|
+
require 'packs/private/interactive_cli/use_cases/add_dependency'
|
13
|
+
require 'packs/private/interactive_cli/use_cases/get_info'
|
14
|
+
require 'packs/private/interactive_cli/use_cases/query'
|
15
|
+
require 'packs/private/interactive_cli/use_cases/make_public'
|
16
|
+
require 'packs/private/interactive_cli/use_cases/move_to_parent'
|
17
|
+
require 'packs/private/interactive_cli/use_cases/rename'
|
18
|
+
require 'packs/private/interactive_cli/use_cases/check'
|
19
|
+
require 'packs/private/interactive_cli/use_cases/update'
|
20
|
+
require 'packs/private/interactive_cli/use_cases/validate'
|
21
|
+
require 'packs/private/interactive_cli/use_cases/lint_package_yml_files'
|
22
|
+
require 'packs/private/interactive_cli/use_cases/visualize'
|
23
|
+
|
24
|
+
module Packs
|
25
|
+
module Private
|
26
|
+
module InteractiveCli
|
27
|
+
extend T::Sig
|
28
|
+
|
29
|
+
sig { params(prompt: T.nilable(TTY::Prompt)).void }
|
30
|
+
def self.start!(prompt: nil)
|
31
|
+
prompt ||= TTY::Prompt.new(interrupt: lambda {
|
32
|
+
puts "\n\nGoodbye! I hope you have a good day."
|
33
|
+
exit 1 })
|
34
|
+
help_text = '(Press ↑/↓ arrow to move, Enter to select and letters to filter)'
|
35
|
+
choice = prompt.select('Hello! What would you like to do?',
|
36
|
+
cycle: true,
|
37
|
+
filter: true,
|
38
|
+
help: help_text,
|
39
|
+
show_help: :always,
|
40
|
+
per_page: 15) do |menu|
|
41
|
+
menu.enum '.'
|
42
|
+
|
43
|
+
UseCases::Interface.all.each do |use_case|
|
44
|
+
menu.choice use_case.user_facing_name, use_case
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
choice.perform!(prompt)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|