Skip to content

feat: Report shallow clones and print errors in plain text - #214

Merged
goloroden merged 2 commits into
mainfrom
feature/shallow-detection-and-error-output
Sep 3, 2026
Merged

feat: Report shallow clones and print errors in plain text#214
goloroden merged 2 commits into
mainfrom
feature/shallow-detection-and-error-output

Conversation

@goloroden

Copy link
Copy Markdown
Member

Refers to #213

While analyzing #213 three findings turned up that are worth fixing independently of the feature discussion in that issue. The warnings, --base and --strict ideas discussed there are deliberately not part of this PR.

The README described behavior that does not exist

The claim "By default, output will be printed to the console in a human-readable format" has been wrong since 2022 — the default target version prints a bare version string. This is exactly what led the reporter of #213 to assume a target=human-readable exists.

The README also never documented that the next version is computed relative to the last release reachable from HEAD, rather than the highest tag in the repository. That is the root cause of the surprises which drive users to write defensive validation steps in their workflows. There is now a section How the next version is determined that spells this out, including the case where the result can be lower than the latest release.

Shallow clones now say what is wrong

A missing fetch-depth: 0 is by far the most common misconfiguration, and it failed with object not found.

Error: repository is a shallow clone and does not contain enough history; run `git fetch --unshallow`, or set `fetch-depth: 0` if you are using actions/checkout

The check deliberately only fires when no release tag was found within the truncated history. A shallow clone that still contains the base tag produces a correct result today and keeps working — verified against a real clone:

Situation before after
shallow, base tag found correct result unchanged, still correct
shallow, no base tag object not found actionable message
not shallow completely unchanged

Errors are readable again

zerolog was not doing any logging here: all six call sites were Fatal, with no Info, Warn or Debug anywhere. In CI it turned every error into {"level":"fatal",...} — precisely where the new message above needs to be readable. On top of that, main.go swallowed the actual cause and appended a second, meaningless line to the message cobra had already printed:

$ get-next-version --bogus
Error: unknown flag: --bogus
Usage: ...
{"level":"fatal","time":...,"message":"failed to execute root command"}   # ← gone

Errors now go through cobra's own mechanism (RunE + SilenceUsage), which removes both problems. As a side effect zerolog and go-isatty are no longer needed as dependencies. An invalid target now also names the valid ones.

Observable behavior

Intended

  • Shallow clone without a reachable tag reports what to do instead of object not found
  • All errors in plain text instead of JSON
  • No more duplicate, meaningless error line on flag errors
  • Invalid target names the valid values
  • README describes what the tool actually does

Worth knowing

  • The error format changes for everyone. Anyone grepping stderr for "level":"fatal" would break — unlikely, but it is a change.
  • stdout is unchanged, which was the critical invariant: --target version and json still write nothing but the version resp. the JSON object to stdout, errors go to stderr only.
  • Exit code stays 1 on all error paths.
  • The usage dump no longer appears for runtime errors, only for flag errors.

Verification

make passes. Beyond that, verified against real clones of this repository:

# stdout purity
get-next-version 2>/dev/null              # 2.7.8
get-next-version -t json 2>/dev/null      # {"version": "2.7.8", ...}
get-next-version -t bogus 2>/dev/null     # empty

# shallow without tags        -> new message, exit 1
# shallow with reachable tag  -> 2.7.7, exit 0   (regression guard)
# full clone without tags     -> 1.0.0, exit 0   (unchanged, not reported as shallow)

New tests cover IsShallow and all three rows of the table above.

🤖 Generated with Claude Code

https://claude.ai/code/session_014zcGUq3NUnFpU1mRWkyBpU

Three findings from the analysis of #213, none of which depend on the
feature discussion there.

The README claimed that output is printed in a human-readable format by
default, which has been wrong since 2022 and caused the misunderstanding
in the issue. It also never documented that the next version is computed
relative to the last release reachable from HEAD, which is the root of
the surprises that drive users to write defensive validation steps.

A shallow clone, by far the most common misconfiguration, failed with
"object not found". It now reports what is actually wrong and how to fix
it, but only when no release tag was found within the truncated history,
so a shallow clone that still contains the base tag keeps working.

zerolog did not do any logging in this project: all six call sites were
Fatal, and there was no Info, Warn or Debug at all. In CI it turned every
error into an unreadable JSON line, and main.go swallowed the actual
cause and appended a second, meaningless message to the one cobra had
already printed. Errors now go through cobra, which removes both
problems, and zerolog and go-isatty are no longer needed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014zcGUq3NUnFpU1mRWkyBpU
@goloroden
goloroden requested a review from a team as a code owner September 3, 2026 07:42
@goloroden
goloroden merged commit de2862a into main Sep 3, 2026
2 checks passed
@goloroden
goloroden deleted the feature/shallow-detection-and-error-output branch September 3, 2026 07:43
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