Skip to content

fix(attest): don't fail when a CI-defaulted --commit has no repository - #1202

Open
mbevc1 wants to merge 7 commits into
mainfrom
20260917_fix_attest
Open

mbevc1 wants to merge 7 commits into
mainfrom
20260917_fix_attest

Conversation

@mbevc1

@mbevc1 mbevc1 commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Fixes kosli-dev/server#6094 and kosli-dev/server#5615.

Closes #1127

--commit is populated from CI environment variables (GITHUB_SHA, CI_COMMIT_SHA, BITBUCKET_COMMIT, ...) whether or not the user asked for it. The common attestation flow and begin trail then ran a git lookup because commitSHA was non-empty, so a CI job that has not checked out the repository failed with:

failed to get commit info. failed to open git repository at .: repository does not exist

for a commit the user never requested. There is no escape hatch: refuseEmptyFlagValues in root.go rejects --commit "", so a pipeline could not opt out from the command line.

What changes

  • A --commit that was defaulted from the CI environment (not passed, not set via KOSLI_COMMIT or config) now warns and proceeds without commit info when --repo-root was also left at its default. Anything asked for explicitly — --commit, or --repo-root pointing at a repository that isn't there — still fails, so a misconfigured pipeline isn't silently swallowed.
  • An unresolvable commit (e.g. a shallow clone) takes the same warn-or-fail route, for the same reason.
  • Whether a flag was passed is now read once, centrally, from the flag set addAttestationFlags already keeps on the shared options — no per-command RunE line to remember.
  • attest pullrequest * and attest jira cannot do their work without the commit, so they name that need and fail with one clear error instead of warning and then hitting a nil dereference.
  • Every message states which --commit failed, whether it was defaulted from CI, the underlying git error, and what to do (--repo-root).
  • --commit help text on the attest commands and begin trail documents the new behaviour; the docs golden fixture is updated.

Testing

The CI-defaulted path is exercised end to end: KOSLI_TESTS is unset around the command run (the same trick TestDefaultValue already uses), a GitHub Actions job is simulated, and the test asserts the command exits 0, warns, and sends no git_commit_info. Also covered: the shallow-clone case, an explicit --repo-root with no repository, an explicit --commit with no repository, a successful explicit --commit, and the two commit-required commands.

Checklist

@github-actions github-actions Bot added go Pull requests that update go code fix labels Sep 17, 2026
@claude

claude Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Claude finished @mbevc1's task in 2m 27s —— View job


Follow-up review complete ✅

  • Fetch prior review comments and new commit diff
  • Check status of each previously-raised finding
  • Flag any new bugs/regressions introduced by the latest commits
  • Post summary comment

Result: The pushed range (4261dca607848ba5) turned out to be a rebase, not new edits — both commits share the same message and identical diff stats (+81/-47), and the branch's total diff against origin/main still matches the PR description exactly. There was no new code to review.

All four previously-raised findings were already resolved in the prior round and remain resolved:

  • repoRootExplicit now excludes the config/env . default — pinned by TestRepoRootFromEnvVarAtDefaultValueStillWarns
  • origin renamed to describedCommit, warning split into two logger.Warn calls, lookup extracted to commitInfoRequest.lookup()
  • commitInfoRequest now carries flags *pflag.FlagSet, one shared mechanism for both attestation.go and beginTrail.go
  • Added KOSLI_COMMIT/KOSLI_REPO_ROOT=. env-var test coverage, map loop converted to a slice

No new bugs, security issues, or regressions found. Posted a summary as a PR comment; no new inline comments needed since all four review threads were already marked resolved.

Comment thread cmd/kosli/attestation.go Outdated
Comment thread cmd/kosli/attestation.go Outdated
Comment thread cmd/kosli/beginTrail.go Outdated
Comment thread cmd/kosli/attestationCommitInfo_test.go
mbevc1 pushed a commit that referenced this pull request Sep 17, 2026
…cit-flag detection

A config or env value for --repo-root marked the flag Changed even when it
equaled the "." default, because bindFlags applies it with Flags().Set()
regardless of value. That made KOSLI_REPO_ROOT=. or a config-file repo-root:
"." hard-fail a CI-defaulted commit instead of warning, contradicting the
help text. repoRootExplicit now also requires the value to differ from ".".

begin trail kept its own commitExplicit/repoRootExplicit booleans because it
doesn't go through addAttestationFlags. commitInfoRequest now takes the flag
set directly and derives both from it, so there is one place, not two, that
knows how "explicit" is decided.

Adds coverage for the KOSLI_COMMIT env route (explicit, hard-fails) and the
KOSLI_REPO_ROOT=. case (still warns), and converts a map-based test loop to a
slice for deterministic failure output.

Addresses review feedback on #1202.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014HZK6c41JmmUMAB71ZsDpX
--commit is populated from CI environment variables (GITHUB_SHA,
CI_COMMIT_SHA, BITBUCKET_COMMIT, ...) whether or not the user asked for
it. The common attestation flow and begin trail then ran a git lookup
because commitSHA was non-empty, so a CI job that has not checked out
the repository failed with "failed to get commit info. failed to open
git repository at .: repository does not exist" for a commit the user
never requested.

A commit that arrived from the CI default now warns and proceeds without
commit info; a commit the user passed explicitly still errors, so a wrong
--repo-root is not silently swallowed. An unresolvable commit in a shallow
clone takes the same route, being the same surprise for the same reason.

Doing nothing was not an option for affected users: the empty-value rule
in refuseEmptyFlagValues rejects --commit "", so there is no way to opt
out of the CI default from the command line.

The two copies of the lookup are now one resolveCommitInfo, which is also
the only level at which the CI default is testable — DefaultValue returns
"" whenever KOSLI_TESTS is set, so no command-level test can produce an
implicitly defaulted --commit.

attest pr * and attest jira need the commit to do their work and
dereferenced payload.Commit unguarded. That was unreachable while the
empty-value rule blocked every route to a nil commit; soft-failing opens
one, so both now report what is missing instead of panicking.

Refs kosli-dev/server#6094
On macOS os.MkdirTemp returns a path under /var/folders, which is a
symlink to /private/var/folders. osfs resolves the symlink for the
worktree root but leaves the caller's unresolved path in place for the
git dir, so go-git sees a git dir that is not ".git" relative to the
worktree, decides the repository lives elsewhere, and tries to write a
"gitdir:" file over the directory it just created:

  open /private/var/folders/.../testDir123/.git: is a directory

InitializeGitRepo in the same file already resolves the path for exactly
this reason. CloneGitRepo did not, so AttestGitlabPRCommandTestSuite and
AttestBitbucketPRCommandTestSuite fail in SetupTest on any machine whose
temp dir is symlinked.
…ed commit end to end

A --commit defaulted from the CI environment is only downgraded to a warning
when --repo-root was left at its default too: a user who pointed at a
repository that is not there asked for something and should hear that it
failed. The check for whether a flag was passed now reads the command's flag
set kept by addAttestationFlags, so no attest command has to remember to
capture it.

attest pullrequest * and attest jira cannot do their work without the commit,
so they name that need in one error rather than warning and then failing.

The CI default is reachable through the command harness by unsetting
KOSLI_TESTS around the run, as TestDefaultValue already does, so the fix is
now exercised end to end: the command exits 0, warns, and sends no
git_commit_info.

Refs kosli-dev/server#6094, kosli-dev/server#5615
The help for --commit on the attest commands and begin trail now states the
rule: only when both --commit and --repo-root are left at their defaults is a
commit that cannot be read downgraded to a warning.

Refs kosli-dev/server#6094
…ttest skill

CloneGitRepo resolves symlinks before cloning, so cloneTo has to exist; say
so on the helper. The new-command attest archetype explains why --commit and
--repo-root are not captured in RunE and when to set commitRequiredFor.
Drop comments that restate a name or duplicate a sibling field, and trim the
rest to the one fact the code cannot show: why a flag set sits on the
options, what a false commitExplicit means, why resolve returns nil, nil, and
why CloneGitRepo resolves symlinks first.
…cit-flag detection

A config or env value for --repo-root marked the flag Changed even when it
equaled the "." default, because bindFlags applies it with Flags().Set()
regardless of value. That made KOSLI_REPO_ROOT=. or a config-file repo-root:
"." hard-fail a CI-defaulted commit instead of warning, contradicting the
help text. repoRootExplicit now also requires the value to differ from ".".

begin trail kept its own commitExplicit/repoRootExplicit booleans because it
doesn't go through addAttestationFlags. commitInfoRequest now takes the flag
set directly and derives both from it, so there is one place, not two, that
knows how "explicit" is decided.

Adds coverage for the KOSLI_COMMIT env route (explicit, hard-fails) and the
KOSLI_REPO_ROOT=. case (still warns), and converts a map-based test loop to a
slice for deterministic failure output.

Addresses review feedback on #1202.
@mbevc1
mbevc1 force-pushed the 20260917_fix_attest branch from 4261dca to 07848ba Compare September 17, 2026 18:26
@claude

claude Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Follow-up review: commit 4261dca07848ba

The pushed range turned out to be a rebase, not new edits: 4261dca6 (BEFORE) and 07848ba5 (AFTER) have identical commit messages, identical diff stats (+81/-47), and the full PR diff against origin/main still matches the PR description exactly (291 additions / 19 deletions / 10 files). So there's no new code to review — the four review threads from the previous rounds were already closed as resolved:

  • repoRootExplicit counting a config/env . as explicit — fixed, repoRootExplicit() now also checks r.repoRoot != "." (cmd/kosli/attestation.go), pinned by TestRepoRootFromEnvVarAtDefaultValueStillWarns.
  • origin naming / warning message split / err invariant — fixed, renamed to describedCommit, lookup pulled into commitInfoRequest.lookup(), warning split into two logger.Warn calls.
  • ✅ Two separate "was this flag passed" mechanisms — fixed, commitInfoRequest now carries flags *pflag.FlagSet and both attestation.go and beginTrail.go derive commitExplicit()/repoRootExplicit() from it via o.flags = cmd.Flags().
  • ✅ Missing KOSLI_COMMIT/KOSLI_REPO_ROOT=. env-var test coverage + map→slice conversion — fixed, TestCommitFromEnvVarIsExplicit and TestRepoRootFromEnvVarAtDefaultValueStillWarns added, TestCommandsNeedingTheCommitFail now iterates a slice.

No new bugs, security issues, or regressions found in the (nonexistent) diff. 0 new inline comments.

View job run

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

Labels

fix go Pull requests that update go code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant