-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
cmd/gofmt: change -d to exit 1 if diffs exist #46289
Comments
I could live with an alternative of a different flag to set the exit code, to avoid breaking existing things. i am sure there's someone out there who has gofmt in a script with |
@griesemer for notifications on this issue. |
If we guard the exit-status change with a flag, It would be nice if we could make the flag's syntax and semantics match whatever flag we add for #27005. |
I think changing the exit status of |
You could add the flag for now and put in a deprecation warning that in X releases the flag will be inverted and the default will be exit codes. In terms of breakage of CI systems, that is the behaviour I want, If i am enforcing gofmt on my code and you don't do it I want the CI to fall over. IMHO not doing that is the same as a compiler exiting 0 when the code failed to compile. (i do realise my feelings may be a tad towards the hardline side of this :) ) in all honesty though I'll take whichever implementation we can get. :) |
I don't think we can ever make the entire tool's default be using exit codes for "was the formating changed". It's entirely reasonable to use I'm also not sure that adding a deprecation or transition period will really help. Breaking a user's script in six months or in two years isn't much different, and I imagine most users will not even see the deprecation notices and remember all the scripts they need to update.
At least from what I've seen, nearly all uses of My intuition is that most scripts using
In that kind of scenario, the exit code is by default discarded via the subshell. That's how I've seen many people use
And for the cases where a script would break, I imagine it should be fairly easy to get the old behavior back, such as replacing All that said, I don't have a strong opinion on new flag versus changing |
By default, sure — but many shell style guides require explicit checks, and we probably don't want to break scripts that conform to that style either. |
FWIW, in my experience changes outside the runtime, compiler, and standard library receive comparatively little testing during the beta and RC. (I would expect most breakage to be reported after the release.) |
I prefer an explicit flag that's orthogonal to |
I would agree with @cespare diffs are only really used for when a human is looking, in CI I would want ideally two returns 1) the file that is failing and 2) the line number of the fail would be nice in the case of a few lines but once you get about 10 lines or so this matters less as at that point it's likely the whole files that is wrong. Still currently any implementation is preferable to none, so additional flag or not I'd just be happy for a non zero exit code. |
I personally don't mind too much whether this happens with I agree that we want to be consistent with whatever #27005 ends up doing. At the same time, I don't particularly feel like waiting a few more years for a flag that's trivial to implement and very much needed for CI :) If #27005 is expected to land on a flag design soon, like Either way, I want to help us reach a decision for 1.21. If we're sure we want a decision on #27005 first, then I'll try to help push that forward. |
Catching up on #27005, it seems like it's landing on So, if we wanted to be consistent, we could make If we prefer an explicit flag, like |
Retitled to reflect the above, and to better line up with other issues like #27005. |
To be clear, here's what I would propose: add a
The flag could be used without either of those files too, e.g. For the sake of symmetry, and for those wanting to format packages like |
#27005 is giving up a More confusingly, I think the proposal there is for I still lean towards adding a |
@mvdan says that we likely cannot change |
This proposal has been added to the active column of the proposals project |
Based on the discussion above, this proposal seems like a likely accept. The proposal is to change gofmt -d (which already exists) to exit 1 if it prints diffs. Gofmt should exit 2 for any other errors. |
Changing There are potentially some cases where a script may break or change behavior, particularly since CI scripts like GitHub Actions tend to stop at the first failing command via e.g. I skimmed a few results from https://github.com/search?q=%22gofmt+-d%22+path%3A**%2F.github%2Fworkflows%2F*.yml&type=code and I don't immediately see any that worries me. If anything, all the commands like |
No change in consensus, so accepted. 🎉 The proposal is to change gofmt -d (which already exists) to exit 1 if it prints diffs. Gofmt should exit 2 for any other errors. |
👏This is good news for users of pre-commit. Can |
First, I know that this has been asked many times before (#24230 #24427 #38551), and I was even on the other side of this argument for a long time.
The argument usually goes that, if you want to know if any files aren't gofmt-ed, you check that
gofmt -l
is empty, for example:And this works, if one can assume a POSIX-like shell.
However, in light of #42119, I think we should make "verify that many files comply with gofmt" a trivial command, without extra machinery like checking for non-empty output.
In that issue, we suggest a number of commands that we'd encourage people to run on CI, from
go test -race ./...
togo mod verify
andgo vet ./...
. You'll note that none of the commands require being wrapped with shell or extra commands to do their job, with two exceptions:go mod tidy
, where one needs to check if files likego.mod
andgo.sum
were modified on disk. cmd/go: add mod tidy -diff #27005 will fix that.gofmt
, which needs testing for empty output, hence this issue.Once
go mod tidy -check
is implemented,gofmt
will stand alone in that list as being the only command that most people should run on their CI, but which is non-portable or just not easy to use directly.--
So, as others have proposed before: I suggest a very simple fix, which is to make
gofmt -d
exit with a status code of 1 if any of the input files have a non-empty diff. Then, CI could simply rungofmt -d .
and get a good result: CI would fail if any files don't comply, and the diff will show exactly which ones and why.It's also arguably more consistent to behave this way, as the
diff
tool usually behaves this way too. For example, from GNU diffutils 3.7:If we think this change is too invasive, or could break too many users, we could also consider a separate flag like
-exitcode
, simialr togit diff --exit-code
. It's really not a big deal if the command run on CI gets a bit longer.I also don't think a solution should come from
go fmt
. I thinkgofmt
is simply superior for use in CI; it allows formatting files which are not part of Go packages, formatting many modules at once, and printing diffs.It's also worth noting I plan to expose this feature in
gofumpt
: mvdan/gofumpt#114cc @griesemer
cc @bcmills @jayconrod @stevetraut for "CI best practices"
cc @ryanm101 @stevenmatthewt @belm0 as previous posters
The text was updated successfully, but these errors were encountered: