Skip to content
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

Adhere to stdout/stderr conventions #22878

Open
Tracked by #22945
jasonkarns opened this issue Oct 3, 2020 · 2 comments
Open
Tracked by #22945

Adhere to stdout/stderr conventions #22878

jasonkarns opened this issue Oct 3, 2020 · 2 comments

Comments

@jasonkarns
Copy link

jasonkarns commented Oct 3, 2020

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:

  1. 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.

  2. 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.

  3. 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

  1. dotnet ef migrations list should print only the migration names to STDOUT; build output should go to STDERR
  2. 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 😸 )
  3. 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.
    1. (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.)

Original thread: dotnet/sdk#7289 (comment)

@Nosamdaman
Copy link

Nosamdaman commented Sep 12, 2022

+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.

@Pilchard123
Copy link

Pilchard123 commented Feb 26, 2024

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).

Another +1 here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants