Skip to content

ci: detect more than one unformatted file in the gofmt check - #2695

Open
thanderoy wants to merge 2 commits into
supabase:masterfrom
thanderoy:ci/gofmt-check-multiple-files
Open

ci: detect more than one unformatted file in the gofmt check#2695
thanderoy wants to merge 2 commits into
supabase:masterfrom
thanderoy:ci/gofmt-check-multiple-files

Conversation

@thanderoy

@thanderoy thanderoy commented Aug 11, 2026

Copy link
Copy Markdown

What

The gofmt check in test.yml silently passes whenever more than one file is unformatted, so it has never enforced formatting in practice.

if [ ! -z $(gofmt -l .) ]

if [ ! -z $(gofmt -l .) ]

The command substitution is unquoted, so the file list word-splits into separate arguments to [:

unformatted files test expression [ exit step result
none [ ! -z ] 0 passes (correct)
one [ ! -z a.go ] 0 fails (correct)
two or more [ ! -z a.go b.go ] 2, binary operator expected passes

With two or more files, [ never evaluates the expression — it errors on the unexpected second operand and exits non-zero, the if takes the false branch, and the step exits 0. The failure is invisible in the log unless you read the set -x trace closely, because the step is green.

As of 2399fe5, five files on master are unformatted and pass CI:

internal/api/oauthserver/service.go
internal/api/provider/custom_oauth_claims_test.go
internal/api/provider/provider.go
internal/api/settings.go
internal/conf/confload/confload.go

How

Two commits, separable on purpose:

  1. ci: detect more than one unformatted file in the gofmt check - quotes the substitution so the list stays one word, and uses -n rather than ! -z.
  2. ci: run make format - the five files above, so the now-working check passes on this branch.

The check has to be fixed and the tree formatted in the same PR: fixing the check alone makes CI fail on the PR that fixes it.

Verified: gofmt -s -l . is empty, go build ./..., go vet ./... and staticcheck are clean, and the tests for the touched packages (internal/api/provider, internal/conf/...) pass.

Notes for review

  • I also added -s to the check. The check ran plain gofmt -l, while its own error message and the format make target both specify gofmt -s -w. It was checking something narrower than it asked for.
  • The second commit touches code I didn't write. It is make format output with no hand edits just struct field alignment, plus one binary expression spacing change in custom_oauth_claims_test.go. git diff -w on that commit is empty, and the diffstat is symmetric (37 insertions, 37 deletions). It should be reviewable at a glance, and is easy to drop and regenerate if it conflicts with anything in flight.
  • The same unquoted pattern doesn't appear elsewhere in .github/workflows/.

The gofmt check used an unquoted command substitution:

    if [ ! -z $(gofmt -l .) ]

With two or more unformatted files the expansion word-splits, so the
test becomes `[ ! -z a.go b.go ]`, which is not a valid expression.
`[` fails with "binary operator expected" and exits non-zero, the `if`
takes the false branch, and the step passes. The check therefore only
ever caught the case of exactly one unformatted file.

Quote the substitution so the file list stays a single word, and use
`-n` instead of `! -z`. Also pass `-s`, so the check enforces the same
thing its own error message and the `format` make target tell
contributors to run.

Five files on master are currently unformatted and pass CI. They are
reformatted in the following commit, without which this check would
fail on this very branch.
These five files are unformatted on master. The gofmt check could not
see them, because it only detected a single unformatted file at a time
until the previous commit.

This is the output of `make format` with no hand edits. The diff is
struct field alignment and one binary expression spacing change:
`git diff -w` is empty.
@thanderoy
thanderoy requested a review from a team as a code owner August 11, 2026 08:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant