You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The problem is ef cli's unconventional stdout behavior which violates norms and expectations (coming from a *nix background, in particular). The downstream effects of this unconventional behavior are lack of interoperability with other tools and added friction when attempting to script the ef-cli.
Some example scenarios:
Attempting to iterate over all migrations: for m in $(dotnet ef migrations list); do
This command fails because the first two lines of output (on STDOUT) are Build started... and Build succeeded.. These lines are diagnostic output which should not be printed to STDOUT, but instead to STDERR. The only output on STDOUT from dotnet ef migrations list should be the actual list of migrations, such that the output can be piped or iterated over or consumed by other tooling.
Attempting to generate the migration script: dotnet ef migrations script > migrate.sql
This command likewise fails to produce the expected output because the first two lines of the output again are Build started... and Build succeeded.. I grant that this is a contrived example because, lo!, there exists the -o option! So some more background:
A new user to this command might naively run: dotnet ef migrations script, and what do they see printed to STDOUT, but the desired SQL! And given that there is so much output, they would likely only see the last 50 or so lines of the sql script. Assuming that the command prints the SQL to STDOUT (because it does), they go about redirecting the output to a file, because that is the normal behavior on the CLI. Then this user might attempt to run the captured sql script, and encounter a sql syntax error because, unbeknownst to them, the first 2 lines of the file are not SQL, but instead diagnostic output from the dotnet build.
But even aside from the first-time experience, there are still scenarios where it would be desirable to print the SQL script (and only the SQL script) to STDOUT. In particular, the generated script presently emits a BOM even though the file is UTF-8. (which is nonsensical, if common in .net tooling) Which means our enterprising developers who may use sql tools that choke on UTF-8 BOMs need to adjust the file before consuming it. A solution: dotnet ef migrations script | dos2unix > migrate.sql (or dotnet ef migrations script | strip-bom > migrate.sql. In this scenario, using the -o flag to capture the output is not sufficient.
Invalid options cause the CLI to print "help/usage" output (yay!) but exit with a zero status code (boo). dotnet ef database -pMyProj -c CtxA update
Eagle-eyes will notice that the -c/--context option is not a valid option to the database subcommand, but is instead only respected by the update sub-subcommand. Therefore the CLI "fails" by instead printing the CLI usage/help output. However, the CLI still exits with a zero (SUCCESS) status code. This scenario remained unnoticed on our CI server for weeks before anyone noticed that it was failing to fail correctly!!!
Expectation
dotnet ef migrations list should print only the migration names to STDOUT; build output should go to STDERR
dotnet ef migrations script should print only the migration SQL to STDOUT; build output should go to STDERR (and even better, should omit the BOM 😸 )
Commands that fail should exit with a nonzero exit status!!! This includes commands that fail to run at all because they receive an unknown option or flag.
(As a precautionary note: dotnet ef somecommand --help should still exit with a zero status code, because in that invocation, the user is explicitly requesting the help output. I've seen too many tools, when updated to exit nonzero when given unexpected arguments, suddenly start exiting nonzero whenever they print help/usage output. I hope that overcorrection doesn't happen here.)
+1 on the complaint about scripts outputting BOM. This breaks compatibility with most versions of psql that I've tested, requiring us to sanitize our scripts with dos2unix before sending them out.
What's particularly nasty about this is that psql will fail to read the START TRANSACTION line, then run the rest of the script without being in a transaction, leading to potential harm to the database.
I've just run headlong onto the stdout/stderr thing with dotnet ef migrations script as well. It feels very clunky having to write to a file and then read back out when being able to pipe is right there (but not really).
Problem
The problem is ef cli's unconventional stdout behavior which violates norms and expectations (coming from a *nix background, in particular). The downstream effects of this unconventional behavior are lack of interoperability with other tools and added friction when attempting to script the ef-cli.
Some example scenarios:
Attempting to iterate over all migrations:
for m in $(dotnet ef migrations list); do
This command fails because the first two lines of output (on
STDOUT
) areBuild started...
andBuild succeeded.
. These lines are diagnostic output which should not be printed to STDOUT, but instead to STDERR. The only output on STDOUT fromdotnet ef migrations list
should be the actual list of migrations, such that the output can be piped or iterated over or consumed by other tooling.Attempting to generate the migration script:
dotnet ef migrations script > migrate.sql
This command likewise fails to produce the expected output because the first two lines of the output again are
Build started...
andBuild succeeded.
. I grant that this is a contrived example because, lo!, there exists the-o
option! So some more background:A new user to this command might naively run:
dotnet ef migrations script
, and what do they see printed to STDOUT, but the desired SQL! And given that there is so much output, they would likely only see the last 50 or so lines of the sql script. Assuming that the command prints the SQL to STDOUT (because it does), they go about redirecting the output to a file, because that is the normal behavior on the CLI. Then this user might attempt to run the captured sql script, and encounter a sql syntax error because, unbeknownst to them, the first 2 lines of the file are not SQL, but instead diagnostic output from the dotnet build.But even aside from the first-time experience, there are still scenarios where it would be desirable to print the SQL script (and only the SQL script) to STDOUT. In particular, the generated script presently emits a BOM even though the file is UTF-8. (which is nonsensical, if common in .net tooling) Which means our enterprising developers who may use sql tools that choke on UTF-8 BOMs need to adjust the file before consuming it. A solution:
dotnet ef migrations script | dos2unix > migrate.sql
(ordotnet ef migrations script | strip-bom > migrate.sql
. In this scenario, using the-o
flag to capture the output is not sufficient.Invalid options cause the CLI to print "help/usage" output (yay!) but exit with a zero status code (boo).
dotnet ef database -pMyProj -c CtxA update
Eagle-eyes will notice that the -c/--context option is not a valid option to the
database
subcommand, but is instead only respected by theupdate
sub-subcommand. Therefore the CLI "fails" by instead printing the CLI usage/help output. However, the CLI still exits with a zero (SUCCESS) status code. This scenario remained unnoticed on our CI server for weeks before anyone noticed that it was failing to fail correctly!!!Expectation
dotnet ef migrations list
should print only the migration names to STDOUT; build output should go to STDERRdotnet ef migrations script
should print only the migration SQL to STDOUT; build output should go to STDERR (and even better, should omit the BOM 😸 )dotnet ef somecommand --help
should still exit with a zero status code, because in that invocation, the user is explicitly requesting the help output. I've seen too many tools, when updated to exit nonzero when given unexpected arguments, suddenly start exiting nonzero whenever they print help/usage output. I hope that overcorrection doesn't happen here.)Original thread: dotnet/sdk#7289 (comment)
The text was updated successfully, but these errors were encountered: