-
Notifications
You must be signed in to change notification settings - Fork 102
cli ergonomics #172
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cli ergonomics #172
Conversation
|
||
let is_valid_file = self.fs.path_is_file(path) | ||
&& path | ||
.extension() | ||
.is_some_and(|ext| ext == "sql" || ext == "pg"); | ||
|
||
if self.fs.path_is_dir(path) || self.fs.path_is_symlink(path) || is_valid_file { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here is the relevant part in can_handle
/// Check whether a file is ignored in the top-level config `files.ignore`/`files.include` | ||
fn is_ignored(&self, path: &Path) -> bool { | ||
let file_name = path.file_name().and_then(|s| s.to_str()); | ||
// Never ignore PGLSP's config file regardless `include`/`ignore` | ||
(file_name != Some(ConfigName::pglsp_toml())) && | ||
// Apply top-level `include`/`ignore | ||
(self.is_ignored_by_top_level_config(path)) | ||
(self.is_ignored_by_top_level_config(path) || self.is_ignored_by_migration_config(path)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is_ignored
is called by is_path_ignored
and we add the new check here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very sweet!
use tempfile::TempDir; | ||
|
||
fn setup() -> TempDir { | ||
TempDir::new().expect("Failed to create temp dir") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tempfile is required to have proper test that work with canonicalize
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very cool!
pglsp.toml
Outdated
[migrations] | ||
migrations_dir = "migrations" | ||
after = 20230912094327 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tested it locally but removed the migrations dir again
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we remove it? or comment out the properties?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very beautiful PR and great description! Love it 😍
pglsp.toml
Outdated
[migrations] | ||
migrations_dir = "migrations" | ||
after = 20230912094327 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we remove it? or comment out the properties?
fn test_get_migration_non_migration_file() { | ||
let migrations_dir = PathBuf::from("/tmp/migrations"); | ||
let path = migrations_dir.join("not_a_migration.sql"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't fully understand what we're checking here – are we checking what happens if the .sql file is empty? or if it doesn't match the pattern?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it doesnt match the pattern since it doesnt contain a timestamp
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clarified it in the test name 👍
use tempfile::TempDir; | ||
|
||
fn setup() -> TempDir { | ||
TempDir::new().expect("Failed to create temp dir") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very cool!
.and_then(|os_str| os_str.to_str()) | ||
.and_then(|file_name| { | ||
let mut parts = file_name.splitn(2, '_'); | ||
let timestamp = parts.next()?.parse().ok()?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really liked the explanation in the PR description about how popular tools all use similar migrations formats. Should we add a comment somewhere here that we expect a <TimestampInMs>_<rest> format?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, added comments
@@ -56,7 +62,7 @@ impl CommandRunner for CheckCommandPayload { | |||
} | |||
|
|||
fn should_write(&self) -> bool { | |||
self.write || self.fix | |||
false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sanity check: did you just change this for debugging?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, I removed all the --fix
stuff because ware not fixing anything. its a leftover from biomes check
command.
pub struct MigrationsConfiguration { | ||
/// The directory where the migration files are stored | ||
#[partial(bpaf(long("migrations-dir")))] | ||
pub migrations_dir: String, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if we use bpaf-derive, but if we do, we could also parse into a PathBuf
.
Examples of that were hard to find, so maybe that's not the recommended way – I'm not sure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that would be preferred, but biome
s Merge
does not work with PathBuf
:(
/// Check whether a file is ignored in the top-level config `files.ignore`/`files.include` | ||
fn is_ignored(&self, path: &Path) -> bool { | ||
let file_name = path.file_name().and_then(|s| s.to_str()); | ||
// Never ignore PGLSP's config file regardless `include`/`ignore` | ||
(file_name != Some(ConfigName::pglsp_toml())) && | ||
// Apply top-level `include`/`ignore | ||
(self.is_ignored_by_top_level_config(path)) | ||
(self.is_ignored_by_top_level_config(path) || self.is_ignored_by_migration_config(path)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very sweet!
|
||
Some(&migration.timestamp <= ignore_before) | ||
}) | ||
.unwrap_or(false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if we pass a migrations_dir but no after
? Wouldn't the and_then
return None
, so the function would always return false
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, and we do not want to ignore any migration file if no after
is specified do we?
goal of this pr is to gear the cli towards the use case we want to support initially: running a check command on migration file(s).
after a discussion with @juleswritescode, this is the plan:
We will have one single
pgtoools check
command. by default, it will scan everything for sql files and lint it. it can be filtered by path, e.g.pgtools check supabase/migrations
to just lint the migration directory. We will have amigrations-dir
config option that will enable extra filtering features for files within the directory, primarily--after
and maybe--last-nth
. Furthermore, we will also have--staged
and--changed
to easily lint just the relevant migrations in a CI environment or a pre-commit hook. The existing--include
and--exclude
filters will continue to work.To enable
--after
, we will pass a--migrations-pattern
.how popular tools store migrations:
UPDATE: I removed
--migrations-pattern
again - we just try both and check if any yield an expected value. Addedmigration_dir
as well asafter
:)I initially tried to put it into
get_files_to_process
but that only looks at the inputs from the user and we need the traversal output to look at each file recursively. the right place for that iscan_handle
, which callsis_path_ignored
from the workspace. the downside of my approach is that we check ignore patterns also for files, whereas before we just checked it for directories and symlinks.... an alternative would be a new workspace api akais_migration_ignored
, but that would conflict withis_path_ignored
imo.