diff --git a/Gemfile.lock b/Gemfile.lock index 9ea70e0..e678869 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,10 +1,11 @@ PATH remote: . specs: - pack_stats (0.0.2) + pack_stats (0.0.3) code_ownership code_teams dogapi + packs parse_packwerk rubocop-packs sorbet-runtime @@ -18,9 +19,9 @@ GEM minitest (>= 5.1) tzinfo (~> 2.0) ast (2.4.2) - code_ownership (1.29.1) + code_ownership (1.29.2) code_teams (~> 1.0) - parse_packwerk + packs sorbet-runtime code_teams (1.0.0) sorbet-runtime @@ -36,8 +37,10 @@ GEM minitest (5.16.3) multi_json (1.15.0) netrc (0.11.0) + packs (0.0.5) + sorbet-runtime parallel (1.22.1) - parse_packwerk (0.16.0) + parse_packwerk (0.18.0) sorbet-runtime parser (3.1.1.0) ast (~> 2.4.1) @@ -76,10 +79,11 @@ GEM rubocop-ast (>= 1.19.1, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.24.0) + rubocop-ast (1.24.1) parser (>= 3.1.1.0) - rubocop-packs (0.0.30) + rubocop-packs (0.0.33) activesupport + packs parse_packwerk rubocop rubocop-sorbet diff --git a/README.md b/README.md index 7dc8fff..1d5745b 100644 --- a/README.md +++ b/README.md @@ -38,13 +38,6 @@ PackStats.report_to_datadog!( # Example: [Pathname.new("./gems")] # componentized_source_code_locations: componentized_source_code_locations, - # - # A file is determined to be packaged if it exists in any of these directories. - # This is an array of `Pathname`. `Pathname` can be relative or absolute paths. - # - # Example: [Pathname.new("./packs")] - # - packaged_source_code_locations: packaged_source_code_locations, ) ``` diff --git a/lib/pack_stats.rb b/lib/pack_stats.rb index 455deff..9fb47cb 100644 --- a/lib/pack_stats.rb +++ b/lib/pack_stats.rb @@ -7,6 +7,7 @@ require 'code_teams' require 'code_ownership' require 'pathname' +require 'packs' require 'pack_stats/private' require 'pack_stats/private/source_code_file' require 'pack_stats/private/datadog_reporter' @@ -27,23 +28,17 @@ module PackStats ].freeze, T::Array[Pathname] ) - DEFAULT_PACKAGED_SOURCE_CODE_LOCATIONS = T.let( - [ - Pathname.new('packs'), - Pathname.new('packages'), - ].freeze, T::Array[Pathname] - ) - sig do params( datadog_client: Dogapi::Client, app_name: String, source_code_pathnames: T::Array[Pathname], componentized_source_code_locations: T::Array[Pathname], - packaged_source_code_locations: T::Array[Pathname], report_time: Time, verbose: T::Boolean, # See note on get_metrics + packaged_source_code_locations: T.nilable(T::Array[Pathname]), + # See note on get_metrics use_gusto_legacy_names: T::Boolean ).void end @@ -52,16 +47,15 @@ def self.report_to_datadog!( app_name:, source_code_pathnames:, componentized_source_code_locations: DEFAULT_COMPONENTIZED_SOURCE_CODE_LOCATIONS, - packaged_source_code_locations: DEFAULT_PACKAGED_SOURCE_CODE_LOCATIONS, report_time: Time.now, # rubocop:disable Rails/TimeZone verbose: false, + packaged_source_code_locations: [], use_gusto_legacy_names: false ) all_metrics = self.get_metrics( source_code_pathnames: source_code_pathnames, componentized_source_code_locations: componentized_source_code_locations, - packaged_source_code_locations: packaged_source_code_locations, app_name: app_name, use_gusto_legacy_names: use_gusto_legacy_names, ) @@ -88,8 +82,9 @@ def self.report_to_datadog!( params( source_code_pathnames: T::Array[Pathname], componentized_source_code_locations: T::Array[Pathname], - packaged_source_code_locations: T::Array[Pathname], app_name: String, + # This field is deprecated + packaged_source_code_locations: T.nilable(T::Array[Pathname]), # It is not recommended to set this to true. # Gusto uses this to preserve historical trends in Dashboards as the names of # things changed, but new dashboards can use names that better match current tooling conventions. @@ -100,15 +95,14 @@ def self.report_to_datadog!( def self.get_metrics( source_code_pathnames:, componentized_source_code_locations:, - packaged_source_code_locations:, app_name:, + packaged_source_code_locations: [], use_gusto_legacy_names: false ) all_metrics = Private::DatadogReporter.get_metrics( source_code_files: source_code_files( source_code_pathnames: source_code_pathnames, componentized_source_code_locations: componentized_source_code_locations, - packaged_source_code_locations: packaged_source_code_locations ), app_name: app_name ) @@ -124,18 +118,21 @@ def self.get_metrics( params( source_code_pathnames: T::Array[Pathname], componentized_source_code_locations: T::Array[Pathname], - packaged_source_code_locations: T::Array[Pathname] ).returns(T::Array[Private::SourceCodeFile]) end def self.source_code_files( source_code_pathnames:, - componentized_source_code_locations:, - packaged_source_code_locations: + componentized_source_code_locations: ) # Sorbet has the wrong signatures for `Pathname#find`, whoops! componentized_file_set = Set.new(componentized_source_code_locations.select(&:exist?).flat_map { |pathname| T.unsafe(pathname).find.to_a }) - packaged_file_set = Set.new(packaged_source_code_locations.select(&:exist?).flat_map { |pathname| T.unsafe(pathname).find.to_a }) + + packaged_file_set = Packs.all.flat_map do |pack| + pack.relative_path.find.to_a + end + + packaged_file_set = Set.new(packaged_file_set) source_code_pathnames.map do |pathname| componentized_file = componentized_file_set.include?(pathname) diff --git a/lib/pack_stats/private.rb b/lib/pack_stats/private.rb index 1ab4c92..918131d 100644 --- a/lib/pack_stats/private.rb +++ b/lib/pack_stats/private.rb @@ -48,6 +48,13 @@ def self.convert_metrics_to_legacy(metrics) new_metric end end + + sig { params(package: ParsePackwerk::Package).returns(T.nilable(String) )} + def self.package_owner(package) + pack = Packs.find(package.name) + return nil if pack.nil? + CodeOwnership.for_package(pack)&.name + end end private_constant :Private diff --git a/lib/pack_stats/private/metrics.rb b/lib/pack_stats/private/metrics.rb index 8f16afc..644756c 100644 --- a/lib/pack_stats/private/metrics.rb +++ b/lib/pack_stats/private/metrics.rb @@ -17,7 +17,7 @@ def self.tags_for_package(package, app_name) [ Tag.new(key: 'package', value: humanized_package_name(package.name)), Tag.new(key: 'app', value: app_name), - *Metrics.tags_for_team(CodeOwnership.for_package(package)&.name), + *Metrics.tags_for_team(Private.package_owner(package)), ] end diff --git a/lib/pack_stats/private/metrics/packages.rb b/lib/pack_stats/private/metrics/packages.rb index 5eb02b4..00c9fe4 100644 --- a/lib/pack_stats/private/metrics/packages.rb +++ b/lib/pack_stats/private/metrics/packages.rb @@ -63,7 +63,7 @@ def self.get_package_metrics(packages, app_name) raise StandardError, "Could not find matching package #{to_package_name}" end - tags = package_tags + [Tag.for('to_package', Metrics.humanized_package_name(to_package_name))] + Metrics.tags_for_to_team(CodeOwnership.for_package(to_package)&.name) + tags = package_tags + [Tag.for('to_package', Metrics.humanized_package_name(to_package_name))] + Metrics.tags_for_to_team(Private.package_owner(to_package)) all_metrics << GaugeMetric.for('by_package.outbound_dependency_violations.per_package.count', Metrics.file_count(violations.select(&:dependency?)), tags) all_metrics << GaugeMetric.for('by_package.outbound_privacy_violations.per_package.count', Metrics.file_count(violations.select(&:privacy?)), tags) end @@ -89,7 +89,8 @@ def self.get_package_metrics(packages, app_name) raise StandardError, "Could not find matching package #{explicit_dependency}" end - tags = package_tags + [Tag.for('to_package', Metrics.humanized_package_name(explicit_dependency))] + Metrics.tags_for_to_team(CodeOwnership.for_package(to_package)&.name) + owner = Private.package_owner(to_package) + tags = package_tags + [Tag.for('to_package', Metrics.humanized_package_name(explicit_dependency))] + Metrics.tags_for_to_team(owner) all_metrics << GaugeMetric.for('by_package.outbound_explicit_dependencies.per_package.count', 1, tags) end diff --git a/lib/pack_stats/private/metrics/packages_by_team.rb b/lib/pack_stats/private/metrics/packages_by_team.rb index 8533184..42f5fd6 100644 --- a/lib/pack_stats/private/metrics/packages_by_team.rb +++ b/lib/pack_stats/private/metrics/packages_by_team.rb @@ -17,7 +17,8 @@ def self.get_package_metrics_by_team(all_packages, app_name) all_metrics = T.let([], T::Array[GaugeMetric]) app_level_tag = Tag.for('app', app_name) - all_packages.group_by { |package| CodeOwnership.for_package(package)&.name }.each do |team_name, packages_by_team| + + all_packages.group_by { |package| Private.package_owner(package) }.each do |team_name, packages_by_team| # We look at `all_packages` because we care about ALL inbound violations across all teams inbound_violations_by_package = all_packages.flat_map(&:violations).group_by(&:to_package_name) @@ -51,7 +52,7 @@ def self.get_package_metrics_by_team(all_packages, app_name) raise StandardError, "Could not find matching package #{violation.to_package_name}" end - CodeOwnership.for_package(to_package)&.name + Private.package_owner(to_package) end grouped_outbound_violations.each do |to_team_name, violations| diff --git a/pack_stats.gemspec b/pack_stats.gemspec index 44abed0..867de95 100644 --- a/pack_stats.gemspec +++ b/pack_stats.gemspec @@ -1,6 +1,6 @@ Gem::Specification.new do |spec| spec.name = 'pack_stats' - spec.version = '0.0.2' + spec.version = '0.0.3' spec.authors = ['Gusto Engineers'] spec.email = ['dev@gusto.com'] @@ -29,6 +29,7 @@ Gem::Specification.new do |spec| spec.add_dependency 'code_teams' spec.add_dependency 'code_ownership' spec.add_dependency 'dogapi' + spec.add_dependency 'packs' spec.add_dependency 'parse_packwerk' spec.add_dependency 'sorbet-runtime' spec.add_dependency 'rubocop-packs' diff --git a/sorbet/rbi/gems/code_ownership@1.28.0.rbi b/sorbet/rbi/gems/code_ownership@1.28.0.rbi deleted file mode 100644 index 340e7e9..0000000 --- a/sorbet/rbi/gems/code_ownership@1.28.0.rbi +++ /dev/null @@ -1,337 +0,0 @@ -# typed: true - -# DO NOT EDIT MANUALLY -# This is an autogenerated file for types exported from the `code_ownership` gem. -# Please instead update this file by running `bin/tapioca gem code_ownership`. - -module CodeOwnership - extend ::CodeOwnership - - requires_ancestor { Kernel } - - sig do - params( - backtrace: T.nilable(T::Array[::String]), - excluded_teams: T::Array[::CodeTeams::Team] - ).returns(T.nilable(::CodeTeams::Team)) - end - def for_backtrace(backtrace, excluded_teams: T.unsafe(nil)); end - - sig { params(klass: T.nilable(T.any(::Class, ::Module))).returns(T.nilable(::CodeTeams::Team)) } - def for_class(klass); end - - sig { params(file: ::String).returns(T.nilable(::CodeTeams::Team)) } - def for_file(file); end - - sig { params(package: ::ParsePackwerk::Package).returns(T.nilable(::CodeTeams::Team)) } - def for_package(package); end - - sig { params(files: T::Array[::String], autocorrect: T::Boolean, stage_changes: T::Boolean).void } - def validate!(files: T.unsafe(nil), autocorrect: T.unsafe(nil), stage_changes: T.unsafe(nil)); end - - class << self - sig { void } - def bust_caches!; end - - sig { params(filename: ::String).void } - def remove_file_annotation!(filename); end - end -end - -class CodeOwnership::Cli - class << self - def for_file(argv); end - def run!(argv); end - - private - - def validate!(argv); end - end -end - -class CodeOwnership::InvalidCodeOwnershipConfigurationError < ::StandardError; end - -module CodeOwnership::Private - class << self - sig { void } - def bust_caches!; end - - sig { returns(::CodeOwnership::Private::Configuration) } - def configuration; end - - sig { returns(::CodeOwnership::Private::OwnershipMappers::FileAnnotations) } - def file_annotations_mapper; end - - sig { params(files: T::Array[::String]).returns(T::Hash[::String, T::Array[::String]]) } - def files_by_mapper(files); end - - sig { params(team_name: ::String, location_of_reference: ::String).returns(::CodeTeams::Team) } - def find_team!(team_name, location_of_reference); end - - sig { returns(T::Array[::CodeOwnership::Private::OwnershipMappers::Interface]) } - def mappers; end - - sig { params(klass: T.nilable(T.any(::Class, ::Module))).returns(T.nilable(::String)) } - def path_from_klass(klass); end - - sig { returns(T::Array[::String]) } - def tracked_files; end - - sig { params(files: T::Array[::String], autocorrect: T::Boolean, stage_changes: T::Boolean).void } - def validate!(files:, autocorrect: T.unsafe(nil), stage_changes: T.unsafe(nil)); end - end -end - -class CodeOwnership::Private::Configuration < ::T::Struct - const :js_package_paths, T::Array[::String] - const :owned_globs, T::Array[::String] - const :skip_codeowners_validation, T::Boolean - const :unowned_globs, T::Array[::String] - - class << self - sig { returns(::CodeOwnership::Private::Configuration) } - def fetch; end - - def inherited(s); end - - sig { params(config_hash: T::Hash[T.untyped, T.untyped]).returns(T::Array[::String]) } - def js_package_paths(config_hash); end - end -end - -CodeOwnership::Private::Configuration::DEFAULT_JS_PACKAGE_PATHS = T.let(T.unsafe(nil), Array) -module CodeOwnership::Private::OwnershipMappers; end - -class CodeOwnership::Private::OwnershipMappers::FileAnnotations - include ::CodeOwnership::Private::OwnershipMappers::Interface - - sig { override.void } - def bust_caches!; end - - sig { override.returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) } - def codeowners_lines_to_owners; end - - sig { override.returns(::String) } - def description; end - - sig { params(filename: ::String).returns(T.nilable(::CodeTeams::Team)) } - def file_annotation_based_owner(filename); end - - sig { override.params(file: ::String).returns(T.nilable(::CodeTeams::Team)) } - def map_file_to_owner(file); end - - sig { override.params(files: T::Array[::String]).returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) } - def map_files_to_owners(files); end - - sig { params(filename: ::String).void } - def remove_file_annotation!(filename); end -end - -CodeOwnership::Private::OwnershipMappers::FileAnnotations::TEAM_PATTERN = T.let(T.unsafe(nil), Regexp) - -module CodeOwnership::Private::OwnershipMappers::Interface - interface! - - sig { abstract.void } - def bust_caches!; end - - sig { abstract.returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) } - def codeowners_lines_to_owners; end - - sig { abstract.returns(::String) } - def description; end - - sig { abstract.params(file: ::String).returns(T.nilable(::CodeTeams::Team)) } - def map_file_to_owner(file); end - - sig { abstract.params(files: T::Array[::String]).returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) } - def map_files_to_owners(files); end -end - -class CodeOwnership::Private::OwnershipMappers::JsPackageOwnership - include ::CodeOwnership::Private::OwnershipMappers::Interface - - sig { override.void } - def bust_caches!; end - - sig { override.returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) } - def codeowners_lines_to_owners; end - - sig { override.returns(::String) } - def description; end - - sig { override.params(file: ::String).returns(T.nilable(::CodeTeams::Team)) } - def map_file_to_owner(file); end - - sig { override.params(files: T::Array[::String]).returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) } - def map_files_to_owners(files); end - - sig { params(package: ::CodeOwnership::Private::ParseJsPackages::Package).returns(T.nilable(::CodeTeams::Team)) } - def owner_for_package(package); end - - private - - sig { params(file: ::String).returns(T.nilable(::CodeOwnership::Private::ParseJsPackages::Package)) } - def map_file_to_relevant_package(file); end -end - -class CodeOwnership::Private::OwnershipMappers::PackageOwnership - include ::CodeOwnership::Private::OwnershipMappers::Interface - - sig { override.void } - def bust_caches!; end - - sig { override.returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) } - def codeowners_lines_to_owners; end - - sig { override.returns(::String) } - def description; end - - sig { override.params(file: ::String).returns(T.nilable(::CodeTeams::Team)) } - def map_file_to_owner(file); end - - sig { override.params(files: T::Array[::String]).returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) } - def map_files_to_owners(files); end - - sig { params(package: ::ParsePackwerk::Package).returns(T.nilable(::CodeTeams::Team)) } - def owner_for_package(package); end - - private - - sig { params(file: ::String).returns(T.nilable(::ParsePackwerk::Package)) } - def map_file_to_relevant_package(file); end -end - -class CodeOwnership::Private::OwnershipMappers::TeamGlobs - include ::CodeOwnership::Private::OwnershipMappers::Interface - - sig { override.void } - def bust_caches!; end - - sig { override.returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) } - def codeowners_lines_to_owners; end - - sig { override.returns(::String) } - def description; end - - sig { override.params(file: ::String).returns(T.nilable(::CodeTeams::Team)) } - def map_file_to_owner(file); end - - sig { override.params(files: T::Array[::String]).returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) } - def map_files_to_owners(files); end -end - -module CodeOwnership::Private::ParseJsPackages - class << self - sig { returns(T::Array[::CodeOwnership::Private::ParseJsPackages::Package]) } - def all; end - end -end - -CodeOwnership::Private::ParseJsPackages::METADATA = T.let(T.unsafe(nil), String) -CodeOwnership::Private::ParseJsPackages::PACKAGE_JSON_NAME = T.let(T.unsafe(nil), String) - -class CodeOwnership::Private::ParseJsPackages::Package < ::T::Struct - const :metadata, T::Hash[::String, T.untyped] - const :name, ::String - - sig { returns(::Pathname) } - def directory; end - - class << self - sig { params(pathname: ::Pathname).returns(::CodeOwnership::Private::ParseJsPackages::Package) } - def from(pathname); end - - def inherited(s); end - end -end - -CodeOwnership::Private::ParseJsPackages::ROOT_PACKAGE_NAME = T.let(T.unsafe(nil), String) -module CodeOwnership::Private::TeamPlugins; end - -class CodeOwnership::Private::TeamPlugins::Github < ::CodeTeams::Plugin - sig { returns(::CodeOwnership::Private::TeamPlugins::Github::GithubStruct) } - def github; end -end - -class CodeOwnership::Private::TeamPlugins::Github::GithubStruct < ::Struct - def do_not_add_to_codeowners_file; end - def do_not_add_to_codeowners_file=(_); end - def team; end - def team=(_); end - - class << self - def [](*_arg0); end - def inspect; end - def members; end - def new(*_arg0); end - end -end - -class CodeOwnership::Private::TeamPlugins::Ownership < ::CodeTeams::Plugin - sig { returns(T::Array[::String]) } - def owned_globs; end -end - -module CodeOwnership::Private::Validations; end - -class CodeOwnership::Private::Validations::FilesHaveOwners - include ::CodeOwnership::Private::Validations::Interface - - sig do - override - .params( - files: T::Array[::String], - autocorrect: T::Boolean, - stage_changes: T::Boolean - ).returns(T::Array[::String]) - end - def validation_errors(files:, autocorrect: T.unsafe(nil), stage_changes: T.unsafe(nil)); end -end - -class CodeOwnership::Private::Validations::FilesHaveUniqueOwners - include ::CodeOwnership::Private::Validations::Interface - - sig do - override - .params( - files: T::Array[::String], - autocorrect: T::Boolean, - stage_changes: T::Boolean - ).returns(T::Array[::String]) - end - def validation_errors(files:, autocorrect: T.unsafe(nil), stage_changes: T.unsafe(nil)); end -end - -class CodeOwnership::Private::Validations::GithubCodeownersUpToDate - include ::CodeOwnership::Private::Validations::Interface - - sig do - override - .params( - files: T::Array[::String], - autocorrect: T::Boolean, - stage_changes: T::Boolean - ).returns(T::Array[::String]) - end - def validation_errors(files:, autocorrect: T.unsafe(nil), stage_changes: T.unsafe(nil)); end - - private - - sig { returns(T::Array[::String]) } - def codeowners_file_lines; end -end - -module CodeOwnership::Private::Validations::Interface - interface! - - sig do - abstract - .params( - files: T::Array[::String], - autocorrect: T::Boolean, - stage_changes: T::Boolean - ).returns(T::Array[::String]) - end - def validation_errors(files:, autocorrect: T.unsafe(nil), stage_changes: T.unsafe(nil)); end -end diff --git a/sorbet/rbi/gems/code_ownership@1.29.2.rbi b/sorbet/rbi/gems/code_ownership@1.29.2.rbi new file mode 100644 index 0000000..c2bbe34 --- /dev/null +++ b/sorbet/rbi/gems/code_ownership@1.29.2.rbi @@ -0,0 +1,525 @@ +# typed: true + +# DO NOT EDIT MANUALLY +# This is an autogenerated file for types exported from the `code_ownership` gem. +# Please instead update this file by running `bin/tapioca gem code_ownership`. + +# source://code_ownership//lib/code_ownership/cli.rb#7 +module CodeOwnership + extend ::CodeOwnership + + requires_ancestor { Kernel } + + # Given a backtrace from either `Exception#backtrace` or `caller`, find the + # first line that corresponds to a file with assigned ownership + # + # source://code_ownership//lib/code_ownership.rb#95 + sig do + params( + backtrace: T.nilable(T::Array[::String]), + excluded_teams: T::Array[::CodeTeams::Team] + ).returns(T.nilable(::CodeTeams::Team)) + end + def for_backtrace(backtrace, excluded_teams: T.unsafe(nil)); end + + # source://code_ownership//lib/code_ownership.rb#127 + sig { params(klass: T.nilable(T.any(::Class, ::Module))).returns(T.nilable(::CodeTeams::Team)) } + def for_class(klass); end + + # source://code_ownership//lib/code_ownership.rb#21 + sig { params(file: ::String).returns(T.nilable(::CodeTeams::Team)) } + def for_file(file); end + + # source://code_ownership//lib/code_ownership.rb#144 + sig { params(package: ::Packs::Pack).returns(T.nilable(::CodeTeams::Team)) } + def for_package(package); end + + # source://code_ownership//lib/code_ownership.rb#39 + sig { params(team: T.any(::CodeTeams::Team, ::String)).returns(::String) } + def for_team(team); end + + # source://code_ownership//lib/code_ownership.rb#83 + sig { params(files: T::Array[::String], autocorrect: T::Boolean, stage_changes: T::Boolean).void } + def validate!(files: T.unsafe(nil), autocorrect: T.unsafe(nil), stage_changes: T.unsafe(nil)); end + + class << self + # Generally, you should not ever need to do this, because once your ruby process loads, cached content should not change. + # Namely, the set of files, packages, and directories which are tracked for ownership should not change. + # The primary reason this is helpful is for clients of CodeOwnership who want to test their code, and each test context + # has different ownership and tracked files. + # + # source://code_ownership//lib/code_ownership.rb#153 + sig { void } + def bust_caches!; end + + # source://code_ownership//lib/code_ownership.rb#72 + sig { params(filename: ::String).void } + def remove_file_annotation!(filename); end + end +end + +# source://code_ownership//lib/code_ownership/cli.rb#8 +class CodeOwnership::Cli + class << self + # For now, this just returns team ownership + # Later, this could also return code ownership errors about that file. + # + # source://code_ownership//lib/code_ownership/cli.rb#76 + def for_file(argv); end + + # source://code_ownership//lib/code_ownership/cli.rb#123 + def for_team(argv); end + + # source://code_ownership//lib/code_ownership/cli.rb#9 + def run!(argv); end + + private + + # source://code_ownership//lib/code_ownership/cli.rb#33 + def validate!(argv); end + end +end + +# source://code_ownership//lib/code_ownership.rb#68 +class CodeOwnership::InvalidCodeOwnershipConfigurationError < ::StandardError; end + +# source://code_ownership//lib/code_ownership/private/configuration.rb#4 +module CodeOwnership::Private + class << self + # source://code_ownership//lib/code_ownership/private.rb#30 + sig { void } + def bust_caches!; end + + # source://code_ownership//lib/code_ownership/private.rb#24 + sig { returns(::CodeOwnership::Private::Configuration) } + def configuration; end + + # source://code_ownership//lib/code_ownership/private.rb#69 + sig { returns(::CodeOwnership::Private::OwnershipMappers::FileAnnotations) } + def file_annotations_mapper; end + + # source://code_ownership//lib/code_ownership/private.rb#106 + sig { params(files: T::Array[::String]).returns(T::Hash[::String, T::Array[::String]]) } + def files_by_mapper(files); end + + # source://code_ownership//lib/code_ownership/private.rb#96 + sig { params(team_name: ::String, location_of_reference: ::String).returns(::CodeTeams::Team) } + def find_team!(team_name, location_of_reference); end + + # source://code_ownership//lib/code_ownership/private.rb#59 + sig { returns(T::Array[::CodeOwnership::Private::OwnershipMappers::Interface]) } + def mappers; end + + # Returns a string version of the relative path to a Rails constant, + # or nil if it can't find something + # + # source://code_ownership//lib/code_ownership/private.rb#77 + sig { params(klass: T.nilable(T.any(::Class, ::Module))).returns(T.nilable(::String)) } + def path_from_klass(klass); end + + # The output of this function is string pathnames relative to the root. + # + # source://code_ownership//lib/code_ownership/private.rb#90 + sig { returns(T::Array[::String]) } + def tracked_files; end + + # source://code_ownership//lib/code_ownership/private.rb#37 + sig { params(files: T::Array[::String], autocorrect: T::Boolean, stage_changes: T::Boolean).void } + def validate!(files:, autocorrect: T.unsafe(nil), stage_changes: T.unsafe(nil)); end + end +end + +# source://code_ownership//lib/code_ownership/private/configuration.rb#5 +class CodeOwnership::Private::Configuration < ::T::Struct + const :js_package_paths, T::Array[::String] + const :owned_globs, T::Array[::String] + const :skip_codeowners_validation, T::Boolean + const :unowned_globs, T::Array[::String] + + class << self + # source://code_ownership//lib/code_ownership/private/configuration.rb#15 + sig { returns(::CodeOwnership::Private::Configuration) } + def fetch; end + + # source://sorbet-runtime/0.5.9924/lib/types/struct.rb#13 + def inherited(s); end + + # source://code_ownership//lib/code_ownership/private/configuration.rb#27 + sig { params(config_hash: T::Hash[T.untyped, T.untyped]).returns(T::Array[::String]) } + def js_package_paths(config_hash); end + end +end + +# source://code_ownership//lib/code_ownership/private/configuration.rb#7 +CodeOwnership::Private::Configuration::DEFAULT_JS_PACKAGE_PATHS = T.let(T.unsafe(nil), Array) + +# source://code_ownership//lib/code_ownership/private/ownership_mappers/interface.rb#7 +module CodeOwnership::Private::OwnershipMappers; end + +# Calculate, cache, and return a mapping of file names (relative to the root +# of the repository) to team name. +# +# Example: +# +# { +# 'app/models/company.rb' => Team.find('Setup & Onboarding'), +# ... +# } +# +# source://code_ownership//lib/code_ownership/private/ownership_mappers/file_annotations.rb#17 +class CodeOwnership::Private::OwnershipMappers::FileAnnotations + include ::CodeOwnership::Private::OwnershipMappers::Interface + + # source://code_ownership//lib/code_ownership/private/ownership_mappers/file_annotations.rb#113 + sig { override.void } + def bust_caches!; end + + # source://code_ownership//lib/code_ownership/private/ownership_mappers/file_annotations.rb#102 + sig { override.returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) } + def codeowners_lines_to_owners; end + + # source://code_ownership//lib/code_ownership/private/ownership_mappers/file_annotations.rb#108 + sig { override.returns(::String) } + def description; end + + # source://code_ownership//lib/code_ownership/private/ownership_mappers/file_annotations.rb#50 + sig { params(filename: ::String).returns(T.nilable(::CodeTeams::Team)) } + def file_annotation_based_owner(filename); end + + # source://code_ownership//lib/code_ownership/private/ownership_mappers/file_annotations.rb#29 + sig { override.params(file: ::String).returns(T.nilable(::CodeTeams::Team)) } + def map_file_to_owner(file); end + + # source://code_ownership//lib/code_ownership/private/ownership_mappers/file_annotations.rb#38 + sig { override.params(files: T::Array[::String]).returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) } + def map_files_to_owners(files); end + + # source://code_ownership//lib/code_ownership/private/ownership_mappers/file_annotations.rb#86 + sig { params(filename: ::String).void } + def remove_file_annotation!(filename); end +end + +# source://code_ownership//lib/code_ownership/private/ownership_mappers/file_annotations.rb#23 +CodeOwnership::Private::OwnershipMappers::FileAnnotations::TEAM_PATTERN = T.let(T.unsafe(nil), Regexp) + +# @abstract Subclasses must implement the `abstract` methods below. +# +# source://code_ownership//lib/code_ownership/private/ownership_mappers/interface.rb#8 +module CodeOwnership::Private::OwnershipMappers::Interface + interface! + + # @abstract + # + # source://code_ownership//lib/code_ownership/private/ownership_mappers/interface.rb#45 + sig { abstract.void } + def bust_caches!; end + + # @abstract + # + # source://code_ownership//lib/code_ownership/private/ownership_mappers/interface.rb#37 + sig { abstract.returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) } + def codeowners_lines_to_owners; end + + # @abstract + # + # source://code_ownership//lib/code_ownership/private/ownership_mappers/interface.rb#41 + sig { abstract.returns(::String) } + def description; end + + # This should be fast when run with ONE file + # + # @abstract + # + # source://code_ownership//lib/code_ownership/private/ownership_mappers/interface.rb#21 + sig { abstract.params(file: ::String).returns(T.nilable(::CodeTeams::Team)) } + def map_file_to_owner(file); end + + # This should be fast when run with MANY files + # + # @abstract + # + # source://code_ownership//lib/code_ownership/private/ownership_mappers/interface.rb#31 + sig { abstract.params(files: T::Array[::String]).returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) } + def map_files_to_owners(files); end +end + +# source://code_ownership//lib/code_ownership/private/ownership_mappers/js_package_ownership.rb#8 +class CodeOwnership::Private::OwnershipMappers::JsPackageOwnership + include ::CodeOwnership::Private::OwnershipMappers::Interface + + # source://code_ownership//lib/code_ownership/private/ownership_mappers/js_package_ownership.rb#80 + sig { override.void } + def bust_caches!; end + + # Package ownership ignores the passed in files when generating code owners lines. + # This is because Package ownership knows that the fastest way to find code owners for package based ownership + # is to simply iterate over the packages and grab the owner, rather than iterating over each file just to get what package it is in + # In theory this means that we may generate code owners lines that cover files that are not in the passed in argument, + # but in practice this is not of consequence because in reality we never really want to generate code owners for only a + # subset of files, but rather we want code ownership for all files. + # + # source://code_ownership//lib/code_ownership/private/ownership_mappers/js_package_ownership.rb#54 + sig { override.returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) } + def codeowners_lines_to_owners; end + + # source://code_ownership//lib/code_ownership/private/ownership_mappers/js_package_ownership.rb#64 + sig { override.returns(::String) } + def description; end + + # source://code_ownership//lib/code_ownership/private/ownership_mappers/js_package_ownership.rb#18 + sig { override.params(file: ::String).returns(T.nilable(::CodeTeams::Team)) } + def map_file_to_owner(file); end + + # source://code_ownership//lib/code_ownership/private/ownership_mappers/js_package_ownership.rb#31 + sig { override.params(files: T::Array[::String]).returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) } + def map_files_to_owners(files); end + + # source://code_ownership//lib/code_ownership/private/ownership_mappers/js_package_ownership.rb#69 + sig { params(package: ::CodeOwnership::Private::ParseJsPackages::Package).returns(T.nilable(::CodeTeams::Team)) } + def owner_for_package(package); end + + private + + # takes a file and finds the relevant `package.json` file by walking up the directory + # structure. Example, given `packages/a/b/c.rb`, this looks for `packages/a/b/package.json`, `packages/a/package.json`, + # `packages/package.json`, and `package.json` in that order, stopping at the first file to actually exist. + # We do additional caching so that we don't have to check for file existence every time + # + # source://code_ownership//lib/code_ownership/private/ownership_mappers/js_package_ownership.rb#91 + sig { params(file: ::String).returns(T.nilable(::CodeOwnership::Private::ParseJsPackages::Package)) } + def map_file_to_relevant_package(file); end +end + +# source://code_ownership//lib/code_ownership/private/ownership_mappers/package_ownership.rb#8 +class CodeOwnership::Private::OwnershipMappers::PackageOwnership + include ::CodeOwnership::Private::OwnershipMappers::Interface + + # source://code_ownership//lib/code_ownership/private/ownership_mappers/package_ownership.rb#80 + sig { override.void } + def bust_caches!; end + + # Package ownership ignores the passed in files when generating code owners lines. + # This is because Package ownership knows that the fastest way to find code owners for package based ownership + # is to simply iterate over the packages and grab the owner, rather than iterating over each file just to get what package it is in + # In theory this means that we may generate code owners lines that cover files that are not in the passed in argument, + # but in practice this is not of consequence because in reality we never really want to generate code owners for only a + # subset of files, but rather we want code ownership for all files. + # + # source://code_ownership//lib/code_ownership/private/ownership_mappers/package_ownership.rb#54 + sig { override.returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) } + def codeowners_lines_to_owners; end + + # source://code_ownership//lib/code_ownership/private/ownership_mappers/package_ownership.rb#64 + sig { override.returns(::String) } + def description; end + + # source://code_ownership//lib/code_ownership/private/ownership_mappers/package_ownership.rb#18 + sig { override.params(file: ::String).returns(T.nilable(::CodeTeams::Team)) } + def map_file_to_owner(file); end + + # source://code_ownership//lib/code_ownership/private/ownership_mappers/package_ownership.rb#31 + sig { override.params(files: T::Array[::String]).returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) } + def map_files_to_owners(files); end + + # source://code_ownership//lib/code_ownership/private/ownership_mappers/package_ownership.rb#69 + sig { params(package: ::Packs::Pack).returns(T.nilable(::CodeTeams::Team)) } + def owner_for_package(package); end +end + +# source://code_ownership//lib/code_ownership/private/ownership_mappers/team_globs.rb#8 +class CodeOwnership::Private::OwnershipMappers::TeamGlobs + include ::CodeOwnership::Private::OwnershipMappers::Interface + + # source://code_ownership//lib/code_ownership/private/ownership_mappers/team_globs.rb#56 + sig { override.void } + def bust_caches!; end + + # source://code_ownership//lib/code_ownership/private/ownership_mappers/team_globs.rb#45 + sig { override.returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) } + def codeowners_lines_to_owners; end + + # source://code_ownership//lib/code_ownership/private/ownership_mappers/team_globs.rb#62 + sig { override.returns(::String) } + def description; end + + # source://code_ownership//lib/code_ownership/private/ownership_mappers/team_globs.rb#38 + sig { override.params(file: ::String).returns(T.nilable(::CodeTeams::Team)) } + def map_file_to_owner(file); end + + # source://code_ownership//lib/code_ownership/private/ownership_mappers/team_globs.rb#22 + sig { override.params(files: T::Array[::String]).returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) } + def map_files_to_owners(files); end +end + +# Modeled off of ParsePackwerk +# +# source://code_ownership//lib/code_ownership/private/parse_js_packages.rb#8 +module CodeOwnership::Private::ParseJsPackages + class << self + # source://code_ownership//lib/code_ownership/private/parse_js_packages.rb#57 + sig { returns(T::Array[::CodeOwnership::Private::ParseJsPackages::Package]) } + def all; end + end +end + +# source://code_ownership//lib/code_ownership/private/parse_js_packages.rb#13 +CodeOwnership::Private::ParseJsPackages::METADATA = T.let(T.unsafe(nil), String) + +# source://code_ownership//lib/code_ownership/private/parse_js_packages.rb#12 +CodeOwnership::Private::ParseJsPackages::PACKAGE_JSON_NAME = T.let(T.unsafe(nil), String) + +# source://code_ownership//lib/code_ownership/private/parse_js_packages.rb#15 +class CodeOwnership::Private::ParseJsPackages::Package < ::T::Struct + const :metadata, T::Hash[::String, T.untyped] + const :name, ::String + + # source://code_ownership//lib/code_ownership/private/parse_js_packages.rb#48 + sig { returns(::Pathname) } + def directory; end + + class << self + # source://code_ownership//lib/code_ownership/private/parse_js_packages.rb#22 + sig { params(pathname: ::Pathname).returns(::CodeOwnership::Private::ParseJsPackages::Package) } + def from(pathname); end + + # source://sorbet-runtime/0.5.9924/lib/types/struct.rb#13 + def inherited(s); end + end +end + +# source://code_ownership//lib/code_ownership/private/parse_js_packages.rb#11 +CodeOwnership::Private::ParseJsPackages::ROOT_PACKAGE_NAME = T.let(T.unsafe(nil), String) + +# source://code_ownership//lib/code_ownership/private/team_plugins/ownership.rb#5 +module CodeOwnership::Private::TeamPlugins; end + +# source://code_ownership//lib/code_ownership/private/team_plugins/github.rb#6 +class CodeOwnership::Private::TeamPlugins::Github < ::CodeTeams::Plugin + # source://code_ownership//lib/code_ownership/private/team_plugins/github.rb#13 + sig { returns(::CodeOwnership::Private::TeamPlugins::Github::GithubStruct) } + def github; end +end + +# source://code_ownership//lib/code_ownership/private/team_plugins/github.rb#10 +class CodeOwnership::Private::TeamPlugins::Github::GithubStruct < ::Struct + # Returns the value of attribute do_not_add_to_codeowners_file + # + # @return [Object] the current value of do_not_add_to_codeowners_file + def do_not_add_to_codeowners_file; end + + # Sets the attribute do_not_add_to_codeowners_file + # + # @param value [Object] the value to set the attribute do_not_add_to_codeowners_file to. + # @return [Object] the newly set value + # + # source://code_ownership//lib/code_ownership/private/team_plugins/github.rb#10 + def do_not_add_to_codeowners_file=(_); end + + # Returns the value of attribute team + # + # @return [Object] the current value of team + def team; end + + # Sets the attribute team + # + # @param value [Object] the value to set the attribute team to. + # @return [Object] the newly set value + # + # source://code_ownership//lib/code_ownership/private/team_plugins/github.rb#10 + def team=(_); end + + class << self + def [](*_arg0); end + def inspect; end + def members; end + def new(*_arg0); end + end +end + +# source://code_ownership//lib/code_ownership/private/team_plugins/ownership.rb#6 +class CodeOwnership::Private::TeamPlugins::Ownership < ::CodeTeams::Plugin + # source://code_ownership//lib/code_ownership/private/team_plugins/ownership.rb#11 + sig { returns(T::Array[::String]) } + def owned_globs; end +end + +# source://code_ownership//lib/code_ownership/private/validations/interface.rb#5 +module CodeOwnership::Private::Validations; end + +# source://code_ownership//lib/code_ownership/private/validations/files_have_owners.rb#6 +class CodeOwnership::Private::Validations::FilesHaveOwners + include ::CodeOwnership::Private::Validations::Interface + + # source://code_ownership//lib/code_ownership/private/validations/files_have_owners.rb#12 + sig do + override + .params( + files: T::Array[::String], + autocorrect: T::Boolean, + stage_changes: T::Boolean + ).returns(T::Array[::String]) + end + def validation_errors(files:, autocorrect: T.unsafe(nil), stage_changes: T.unsafe(nil)); end +end + +# source://code_ownership//lib/code_ownership/private/validations/files_have_unique_owners.rb#6 +class CodeOwnership::Private::Validations::FilesHaveUniqueOwners + include ::CodeOwnership::Private::Validations::Interface + + # source://code_ownership//lib/code_ownership/private/validations/files_have_unique_owners.rb#12 + sig do + override + .params( + files: T::Array[::String], + autocorrect: T::Boolean, + stage_changes: T::Boolean + ).returns(T::Array[::String]) + end + def validation_errors(files:, autocorrect: T.unsafe(nil), stage_changes: T.unsafe(nil)); end +end + +# source://code_ownership//lib/code_ownership/private/validations/github_codeowners_up_to_date.rb#6 +class CodeOwnership::Private::Validations::GithubCodeownersUpToDate + include ::CodeOwnership::Private::Validations::Interface + + # source://code_ownership//lib/code_ownership/private/validations/github_codeowners_up_to_date.rb#12 + sig do + override + .params( + files: T::Array[::String], + autocorrect: T::Boolean, + stage_changes: T::Boolean + ).returns(T::Array[::String]) + end + def validation_errors(files:, autocorrect: T.unsafe(nil), stage_changes: T.unsafe(nil)); end + + private + + # Generate the contents of a CODEOWNERS file that GitHub can use to + # automatically assign reviewers + # https://help.github.com/articles/about-codeowners/ + # + # source://code_ownership//lib/code_ownership/private/validations/github_codeowners_up_to_date.rb#100 + sig { returns(T::Array[::String]) } + def codeowners_file_lines; end +end + +# @abstract Subclasses must implement the `abstract` methods below. +# +# source://code_ownership//lib/code_ownership/private/validations/interface.rb#6 +module CodeOwnership::Private::Validations::Interface + interface! + + # @abstract + # + # source://code_ownership//lib/code_ownership/private/validations/interface.rb#13 + sig do + abstract + .params( + files: T::Array[::String], + autocorrect: T::Boolean, + stage_changes: T::Boolean + ).returns(T::Array[::String]) + end + def validation_errors(files:, autocorrect: T.unsafe(nil), stage_changes: T.unsafe(nil)); end +end diff --git a/sorbet/rbi/gems/packs@0.0.5.rbi b/sorbet/rbi/gems/packs@0.0.5.rbi new file mode 100644 index 0000000..71c2005 --- /dev/null +++ b/sorbet/rbi/gems/packs@0.0.5.rbi @@ -0,0 +1,111 @@ +# typed: true + +# DO NOT EDIT MANUALLY +# This is an autogenerated file for types exported from the `packs` gem. +# Please instead update this file by running `bin/tapioca gem packs`. + +# source://packs//lib/packs/pack.rb#3 +module Packs + class << self + # source://packs//lib/packs.rb#16 + sig { returns(T::Array[::Packs::Pack]) } + def all; end + + # source://packs//lib/packs.rb#34 + sig { void } + def bust_cache!; end + + # source://packs//lib/packs.rb#41 + sig { returns(::Packs::Private::Configuration) } + def config; end + + # @yield [config] + # + # source://packs//lib/packs.rb#47 + sig { params(blk: T.proc.params(arg0: ::Packs::Private::Configuration).void).void } + def configure(&blk); end + + # source://packs//lib/packs.rb#21 + sig { params(name: ::String).returns(T.nilable(::Packs::Pack)) } + def find(name); end + + # source://packs//lib/packs.rb#26 + sig { params(file_path: T.any(::Pathname, ::String)).returns(T.nilable(::Packs::Pack)) } + def for_file(file_path); end + + private + + # source://packs//lib/packs.rb#73 + sig { returns(T::Array[::Pathname]) } + def package_glob_patterns; end + + # source://packs//lib/packs.rb#59 + sig { returns(T::Hash[::String, ::Packs::Pack]) } + def packs_by_name; end + end +end + +# source://packs//lib/packs.rb#10 +Packs::PACKAGE_FILE = T.let(T.unsafe(nil), String) + +# source://packs//lib/packs/pack.rb#4 +class Packs::Pack < ::T::Struct + const :name, ::String + const :path, ::Pathname + const :raw_hash, T::Hash[T.untyped, T.untyped] + const :relative_path, ::Pathname + + # source://packs//lib/packs/pack.rb#34 + sig { returns(::String) } + def last_name; end + + # source://packs//lib/packs/pack.rb#39 + sig { returns(T::Hash[T.untyped, T.untyped]) } + def metadata; end + + # source://packs//lib/packs/pack.rb#28 + sig { params(relative: T::Boolean).returns(::Pathname) } + def yml(relative: T.unsafe(nil)); end + + class << self + # source://packs//lib/packs/pack.rb#13 + sig { params(package_yml_absolute_path: ::Pathname).returns(::Packs::Pack) } + def from(package_yml_absolute_path); end + + # source://sorbet-runtime/0.5.9924/lib/types/struct.rb#13 + def inherited(s); end + end +end + +# source://packs//lib/packs/private/configuration.rb#4 +module Packs::Private + class << self + # source://packs//lib/packs/private.rb#10 + sig { returns(::Pathname) } + def root; end + end +end + +# source://packs//lib/packs/private/configuration.rb#5 +class Packs::Private::Configuration < ::T::Struct + prop :pack_paths, T::Array[::String] + + class << self + # source://packs//lib/packs/private/configuration.rb#17 + sig { returns(::Packs::Private::Configuration) } + def fetch; end + + # source://sorbet-runtime/0.5.9924/lib/types/struct.rb#13 + def inherited(s); end + + # source://packs//lib/packs/private/configuration.rb#26 + sig { params(config_hash: T::Hash[T.untyped, T.untyped]).returns(T::Array[::String]) } + def pack_paths(config_hash); end + end +end + +# source://packs//lib/packs/private/configuration.rb#7 +Packs::Private::Configuration::CONFIGURATION_PATHNAME = T.let(T.unsafe(nil), Pathname) + +# source://packs//lib/packs/private/configuration.rb#9 +Packs::Private::Configuration::DEFAULT_PACK_PATHS = T.let(T.unsafe(nil), Array) diff --git a/spec/pack_stats_legacy_api_spec.rb b/spec/pack_stats_legacy_api_spec.rb index 5a46436..cb54924 100644 --- a/spec/pack_stats_legacy_api_spec.rb +++ b/spec/pack_stats_legacy_api_spec.rb @@ -49,16 +49,21 @@ module PackStats # rubocop:disable RSpec/DescribedClassModuleWrapping app_name: 'MyApp', source_code_pathnames: Pathname.glob('**/**.rb'), componentized_source_code_locations: [Pathname.new('components')], - packaged_source_code_locations: [Pathname.new('packs')], use_gusto_legacy_names: true, ) end let(:metrics) { subject } before do + Packs.bust_cache! CodeTeams.bust_caches! CodeOwnership.bust_caches! write_package_yml('.') + write_file('packs.yml', <<~YML) + pack_paths: + - packs/* + - packs/*/* + YML end context 'in empty app' do diff --git a/spec/pack_stats_spec.rb b/spec/pack_stats_spec.rb index 9bed421..f80468c 100644 --- a/spec/pack_stats_spec.rb +++ b/spec/pack_stats_spec.rb @@ -45,15 +45,19 @@ module PackStats # rubocop:disable RSpec/DescribedClassModuleWrapping app_name: 'MyApp', source_code_pathnames: Pathname.glob('**/**.rb'), componentized_source_code_locations: [Pathname.new('components')], - packaged_source_code_locations: [Pathname.new('packs')], ) end let(:metrics) { subject } before do + Packs.bust_cache! CodeTeams.bust_caches! CodeOwnership.bust_caches! write_package_yml('.') + write_file('packs.yml', <<~YML) + pack_paths: + - packs/* + YML end context 'in empty app' do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 2efb7d9..6553701 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -3,6 +3,7 @@ require 'bundler/setup' require 'pack_stats' require 'pry' +require 'packs/rspec/support' RSpec.configure do |config| # Enable flags like --only-failures and --next-failure @@ -14,22 +15,6 @@ config.expect_with :rspec do |c| c.syntax = :expect end - - config.around do |example| - prefix = [File.basename($0), Process.pid].join('-') # rubocop:disable Style/SpecialGlobalVars - tmpdir = Dir.mktmpdir(prefix) - Dir.chdir(tmpdir) do - example.run - end - ensure - FileUtils.rm_rf(tmpdir) - end -end - -def write_file(path, content = '') - pathname = Pathname.new(path) - FileUtils.mkdir_p(pathname.dirname) - pathname.write(content) end def sorbet_double(stubbed_class, attr_map = {}) @@ -97,39 +82,10 @@ def sorbet_double(stubbed_class, attr_map = {}) end def write_package_yml( - pack_name, - dependencies: [], - enforce_dependencies: true, - enforce_privacy: true, - protections: {}, - global_namespaces: [], - visible_to: [], - owner: nil + name ) - defaults = { - 'prevent_this_package_from_violating_its_stated_dependencies' => 'fail_on_new', - 'prevent_other_packages_from_using_this_packages_internals' => 'fail_on_new', - 'prevent_this_package_from_exposing_an_untyped_api' => 'fail_on_new', - 'prevent_this_package_from_creating_other_namespaces' => 'fail_on_new', - } - protections_with_defaults = defaults.merge(protections) - metadata = { 'protections' => protections_with_defaults } - - if owner - metadata.merge({ 'owner' => owner }) - end - - if global_namespaces - metadata.merge({ 'global_namespaces' => global_namespaces }) - end - - package = ParsePackwerk::Package.new( - name: pack_name, - dependencies: dependencies, - enforce_dependencies: enforce_dependencies, - enforce_privacy: enforce_privacy, - metadata: metadata - ) - - ParsePackwerk.write_package_yml!(package) + write_pack(name, { + 'enforce_dependencies' => true, + 'enforce_privacy' => true, + }) end