A 100% Rust implementation of packwerk, a gradual modularization platform for Ruby.
- Currently can serve as a drop-in replacement on Gusto's extra-large Rails monolith
- This is a work in progress! Please see Verification for instructions on how to verify the output of
packs
is the same aspackwerk
.
- Currently ~10-20x as fast as the ruby implementation. See BENCHMARKS.md.
- Your mileage may vary!
- Other performance improvements are coming soon!
- Currently supports non-Rails apps through an experimental implementation
- Uses the same public API as
packwerk
, but has different behavior. - See EXPERIMENTAL_PARSER_USAGE.md for more info
Once installed and added to your $PATH
, just call pks
to see the CLI help message and documentation.
Welcome! Please see https://github.com/alexevanczuk/packs for more information!
Usage: pks [OPTIONS] <COMMAND>
Commands:
greet Just saying hi
create Create a new pack
check Look for violations in the codebase
check-contents Check file contents piped to stdin
update Update package_todo.yml files with the current violations
validate Look for validation errors in the codebase
add-dependency Add a dependency from one pack to another
check-unnecessary-dependencies Check for dependencies that when removed produce no violations.
lint-package-yml-files Lint package.yml files
expose-monkey-patches Expose monkey patches of the Ruby stdlib, gems your app uses, and your application itself
delete-cache `rm -rf` on your cache directory, default `tmp/cache/packwerk`
list-packs List packs based on configuration in packwerk.yml (for debugging purposes)
list-included-files List analyzed files based on configuration in packwerk.yml (for debugging purposes)
list-definitions List the constants that packs sees and where it sees them (for debugging purposes)
help Print this message or the help of the given subcommand(s)
Options:
--project-root <PROJECT_ROOT> Path for the root of the project [default: .]
-d, --debug Run with performance debug mode
-e, --experimental-parser Run with the experimental parser, which gets constant definitions directly from the AST
--no-cache Run without the cache (good for CI, testing)
-p, --print-files Print to console when files begin and finish processing (to identify files that panic when processing files concurrently)
-h, --help Print help
-V, --version Print version
See INSTALLATION.md
packwerk
has a VSCode Extension: https://github.com/rubyatscale/packwerk-vscode/tree/main
It also has a RubyMine Extension: https://github.com/vinted/packwerk-intellij
Using the extension with packs
is straightforward and results in a much more responsive experience.
Directions:
- Follow INSTALLATION.md instructions to install
packs
- Follow the configuration directions to configure the extension to use
packs
instead of the ruby gem by setting the executable topacks check
As packs
is still a work-in-progress, it's possible it will not produce the same results as the ruby implementation (see Not Yet Supported). If so, please file an issue – I'd love to try to support your use case!
Instructions:
- Follow the directions above to install
packs
- Run
packs update
- Confirm the output of
git diff
is empty - Please file an issue if it's not!
Me too! This is my first Rust project, so I'd love to have feedback, advice, and contributions!
Rust is a low-level language with high-level abstractions, a rich type system, with a focus on memory safety through innovative compile-time checks on memory usage.
If you're new to Rust, don't be intimidated! https://www.rust-lang.org has tons of great learning resources.
If you'd like to contribute but don't know where to start, please reach out! I'd love to help you get started.
- custom inflections
- custom load paths
- zeitwerk default namespaces
- extensible plugin system
There are still some known behavioral differences between packs
and packwerk
. If you find any, please file an issue!
package_paths
must not end in a slash, e.g.packs/*/
is not supported, butpacks/*
is.- A
**
inpackage_paths
is supported, but is not a substitute for a single*
, e.g.packs/**
is supported and will matchpacks/*/*/package.yml
, but will not matchpacks/*/package.yml
.packs/*
must be used to match that.
See BENCHMARKS.md
- Current (@gmcgibbon, @rafaelfranca), and Ex-Shopifolks (@exterm, @wildmaples) for open-sourcing and maintaining
packwerk
- Gusties, and the Ruby/Rails Modularity Slack Server, for continued feedback and support
- @mzruya for the initial implementation and Rust inspiration