From 958704928315c3073a61e313c7ca7ced1465444a Mon Sep 17 00:00:00 2001 From: Kevin Messiaen <114553769+kevinmessiaen@users.noreply.github.com> Date: Mon, 15 Jun 2026 19:02:26 +0700 Subject: [PATCH] fix(git): disable gpg signing for ktx's own commits (#299) ktx commits under a synthetic identity (ktx ) that can never own a GPG secret key. On a machine with commit.gpgsign=true, git tried to sign every ktx commit and failed with "No secret key", breaking ingest, scan, wiki, memory, and bootstrap commits. Inject commit.gpgsign=false as a per-invocation -c override in the single core git client factory every ktx commit flows through. This honors the existing principle of not mutating the user's repo config, and is locale-independent (no error-message matching). Also harden the repo-isolation fixture helper to disable signing on its raw commits so the suite is deterministic regardless of the contributor's global git config. Fixes KLO-735. Co-authored-by: Claude Opus 4.8 (1M context) --- packages/cli/src/context/core/git-env.ts | 6 +++++- .../core/git.service.init-identity.test.ts | 19 +++++++++++++++++++ .../core/git.service.repo-isolation.test.ts | 6 +++++- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/context/core/git-env.ts b/packages/cli/src/context/core/git-env.ts index 645a29cc..0bb7bf74 100644 --- a/packages/cli/src/context/core/git-env.ts +++ b/packages/cli/src/context/core/git-env.ts @@ -31,6 +31,10 @@ function sanitizedGitEnv(env: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEn * directory is an existing repo ktx did not create and the machine has no configured git * identity (e.g. a fresh Mac with no ~/.gitconfig), without mutating the user's repo config. * Explicit `--author` flags on individual commits still take precedence over GIT_AUTHOR_NAME. + * + * `commit.gpgsign=false` is injected as a per-invocation `-c` override so ktx's commits never + * attempt GPG signing: ktx commits under a synthetic identity that can never own a secret key, so + * a user's `commit.gpgsign=true` would otherwise fail every commit with "No secret key". */ export function createSimpleGit(baseDir: string, identity?: { name: string; email: string }): SimpleGit { const env = sanitizedGitEnv(); @@ -40,5 +44,5 @@ export function createSimpleGit(baseDir: string, identity?: { name: string; emai env.GIT_COMMITTER_NAME = identity.name; env.GIT_COMMITTER_EMAIL = identity.email; } - return simpleGit({ baseDir, unsafe: { allowUnsafeAskPass: true } }).env(env); + return simpleGit({ baseDir, config: ['commit.gpgsign=false'], unsafe: { allowUnsafeAskPass: true } }).env(env); } diff --git a/packages/cli/test/context/core/git.service.init-identity.test.ts b/packages/cli/test/context/core/git.service.init-identity.test.ts index b84b9aba..a1fb2aac 100644 --- a/packages/cli/test/context/core/git.service.init-identity.test.ts +++ b/packages/cli/test/context/core/git.service.init-identity.test.ts @@ -94,4 +94,23 @@ describe('GitService.initialize without a configured git identity', () => { }).trim(); expect(localName).toBe(''); }); + + // Regression for KLO-735: a machine with commit.gpgsign=true makes git try to GPG-sign every + // commit, but ktx commits under a synthetic identity that can never own a secret key, so signing + // fails with "No secret key". ktx commits must succeed regardless of the user's signing config. + it('commits even when the global git config forces gpg signing', async () => { + // Force signing and point gpg at a program that always fails, mirroring a machine whose + // configured signing key does not match ktx's synthetic identity. + await writeFile( + join(homeDir, '.gitconfig'), + '[user]\n\tuseConfigOnly = true\n[commit]\n\tgpgsign = true\n[gpg]\n\tprogram = false\n', + 'utf-8', + ); + + const service = new GitService(coreConfig(repoDir)); + await expect(service.onModuleInit()).resolves.toBeUndefined(); + + const head = await service.revParseHead(); + expect(head).toMatch(/^[0-9a-f]{40}$/); + }); }); diff --git a/packages/cli/test/context/core/git.service.repo-isolation.test.ts b/packages/cli/test/context/core/git.service.repo-isolation.test.ts index 569750c8..07478019 100644 --- a/packages/cli/test/context/core/git.service.repo-isolation.test.ts +++ b/packages/cli/test/context/core/git.service.repo-isolation.test.ts @@ -21,7 +21,11 @@ function coreConfig(configDir: string): KtxCoreConfig { } function git(cwd: string, args: string[]): string { - return execFileSync('git', args, { + // `-c commit.gpgsign=false` keeps fixture commits deterministic regardless of the host's git + // config: a contributor with commit.gpgsign=true would otherwise fail these raw commits under a + // synthetic identity that owns no secret key. + const fixtureArgs = args[0] === 'commit' ? ['-c', 'commit.gpgsign=false', ...args] : args; + return execFileSync('git', fixtureArgs, { cwd, encoding: 'utf-8', env: {