Skip to content

fix(skills): marketplace setup incorrectly reports error after successful clone - #242

Merged
kolatts merged 1 commit into
mainfrom
claude/issue-239-20260630-1250
Jun 30, 2026
Merged

kolatts merged 1 commit into
mainfrom
claude/issue-239-20260630-1250

Conversation

@claude

@claude claude Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Summary

  • After git clone exits non-zero, verify the destination with git rev-parse HEAD before surfacing the error
  • On Windows with Git Credential Manager, git can write authentication warnings to stderr and exit non-zero even though the repository was successfully written to disk — this false failure is now detected and the command continues normally
  • Only re-throws the original git error when no valid repository exists at the destination

Test plan

  • npm run typecheck — passes
  • npm run lint — passes
  • npm test — 295 tests pass
  • Manual: run pncli skills marketplace setup against a Bitbucket Server with GCM on Windows to confirm the false-negative is gone; run against an actually unauthenticated URL to confirm the real auth error is still surfaced

Closes #239

Generated with Claude Code

…-zero but .git is valid

On Windows with Git Credential Manager, git can write authentication warnings
to stderr and exit non-zero even though the clone was written to disk. After
a non-zero exit, verify with `git rev-parse HEAD`; only surface the error if
no valid repository exists at the destination.

Closes #239

Co-authored-by: Sunny Kolattukudy <kolatts@users.noreply.github.com>
@claude

claude Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor Author

Claude finished @claude[bot]'s task in 2m 18s —— View job


PR Review

  • Read changed files and gather context
  • Review code quality, correctness, edge cases
  • Post formal review

Verdict: Approve (can't self-approve; tagging for human merge)

The fix is correct. git rev-parse HEAD at the destination is exactly the right gate — it reliably distinguishes a valid clone (HEAD resolves → continue) from a genuinely failed one (HEAD doesn't resolve → re-throw). The credential-scrubbing regex on the error path is preserved verbatim.

One nit (inline suggestion posted): the cloneActuallySucceeded boolean can be eliminated by re-throwing directly inside the inner catch. Same semantics, one fewer variable.

// current
let cloneActuallySucceeded = false;
try {
  execFileSync('git', ['-C', resolvedPath, 'rev-parse', 'HEAD'], { stdio: 'pipe' });
  cloneActuallySucceeded = true;
} catch { /* ... */ }
if (!cloneActuallySucceeded) { throw ... }

// simpler
try {
  execFileSync('git', ['-C', resolvedPath, 'rev-parse', 'HEAD'], { stdio: 'pipe' });
} catch {
  const msg = e instanceof Error ? e.message : String(e);
  throw new Error(msg.replace(...));
}

Test coverage: The command action handler isn't unit-tested, but that's a pre-existing gap for all marketplace actions in this file — not introduced by this PR and not something it needs to fix.

No blocking issues.

Comment on lines +271 to +279
let cloneActuallySucceeded = false;
try {
execFileSync('git', ['-C', resolvedPath, 'rev-parse', 'HEAD'], { stdio: 'pipe' });
cloneActuallySucceeded = true;
} catch { /* repo not valid — fall through and re-throw original error */ }
if (!cloneActuallySucceeded) {
const msg = e instanceof Error ? e.message : String(e);
throw new Error(msg.replace(/x-(?:token-auth|access-token):[^@]+@/g, 'x-token-auth:***@'));
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The boolean flag can be eliminated — re-throw inside the inner catch instead:

Suggested change
let cloneActuallySucceeded = false;
try {
execFileSync('git', ['-C', resolvedPath, 'rev-parse', 'HEAD'], { stdio: 'pipe' });
cloneActuallySucceeded = true;
} catch { /* repo not valid — fall through and re-throw original error */ }
if (!cloneActuallySucceeded) {
const msg = e instanceof Error ? e.message : String(e);
throw new Error(msg.replace(/x-(?:token-auth|access-token):[^@]+@/g, 'x-token-auth:***@'));
}
try {
execFileSync('git', ['-C', resolvedPath, 'rev-parse', 'HEAD'], { stdio: 'pipe' });
} catch {
// rev-parse failed — repo is not valid, surface the original clone error
const msg = e instanceof Error ? e.message : String(e);
throw new Error(msg.replace(/x-(?:token-auth|access-token):[^@]+@/g, 'x-token-auth:***@'));
}

Same semantics, one less variable, easier to read at a glance.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@claude[agent] fix this

Copilot stopped work on behalf of kolatts due to an error June 30, 2026 20:11
@Claude
Claude AI requested a review from kolatts June 30, 2026 20:11
@kolatts
kolatts merged commit 417cda8 into main Jun 30, 2026
5 of 6 checks passed
@kolatts
kolatts deleted the claude/issue-239-20260630-1250 branch June 30, 2026 21:45
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.

pncli skills marketplace setup incorrectly states error after successful clone

1 participant