diff --git a/apps/server/src/git/GitManager.test.ts b/apps/server/src/git/GitManager.test.ts index 3c1f225ca35f7..a7f64f925bef6 100644 --- a/apps/server/src/git/GitManager.test.ts +++ b/apps/server/src/git/GitManager.test.ts @@ -2565,6 +2565,46 @@ it.layer(layerGitManagerTest)("GitManager", (it) => { }), ); + it.effect("keeps signature output out of recent commit subjects", () => + Effect.gen(function* () { + const repoDir = yield* makeTempDir("t3code-git-manager-"); + yield* initRepo(repoDir); + const signingKey = NodePath.join(yield* makeTempDir("t3code-git-signing-key-"), "key"); + NodeChildProcess.execFileSync("ssh-keygen", [ + "-q", + "-t", + "ed25519", + "-N", + "", + "-f", + signingKey, + ]); + yield* runGit(repoDir, ["config", "gpg.format", "ssh"]); + // A global signer such as 1Password's cannot use the fixture's generated key. + yield* runGit(repoDir, ["config", "gpg.ssh.program", "ssh-keygen"]); + yield* runGit(repoDir, ["config", "user.signingkey", `${signingKey}.pub`]); + yield* runGit(repoDir, ["config", "log.showSignature", "true"]); + yield* runGit(repoDir, ["commit", "--amend", "-S", "--no-edit"]); + NodeFS.writeFileSync(NodePath.join(repoDir, "README.md"), "hello again\n"); + let commitInstructions: string | undefined; + + const { manager } = yield* makeManager({ + textGeneration: { + generateCommitMessage: (input) => { + commitInstructions = input.policy?.commitInstructions; + return Effect.succeed({ subject: "Update readme", body: "" }); + }, + }, + }); + + yield* runStackedAction(manager, { cwd: repoDir, action: "commit" }); + + expect(commitInstructions).toMatch( + /Recent commit subjects from this repository:\nInitial commit$/, + ); + }), + ); + it.effect("falls back when the dedicated source control writer is unavailable", () => Effect.gen(function* () { const repoDir = yield* makeTempDir("t3code-git-manager-"); diff --git a/apps/server/src/git/GitManager.ts b/apps/server/src/git/GitManager.ts index d1f48bfed3681..f8a64733736f0 100644 --- a/apps/server/src/git/GitManager.ts +++ b/apps/server/src/git/GitManager.ts @@ -791,7 +791,7 @@ export const make = Effect.gen(function* () { .execute({ operation: "GitManager.readRecentCommitSubjects", cwd, - args: ["log", "-n", "20", "--no-merges", "--pretty=format:%s"], + args: ["log", "-n", "20", "--no-merges", "--no-show-signature", "--pretty=format:%s"], }) .pipe( Effect.map((result) => diff --git a/apps/server/src/vcs/GitVcsDriverCore.test.ts b/apps/server/src/vcs/GitVcsDriverCore.test.ts index 1c3e075d165c8..7c9e764f441b3 100644 --- a/apps/server/src/vcs/GitVcsDriverCore.test.ts +++ b/apps/server/src/vcs/GitVcsDriverCore.test.ts @@ -2849,20 +2849,38 @@ it.layer(layerTest)("GitVcsDriver core integration", (it) => { }), ); - it.effect("reads range patches from source without textconv, color, or diff.relative", () => + it.effect("reads raw range context regardless of Git display configuration", () => Effect.gen(function* () { const cwd = yield* makeTmpDir(); const { initialBranch } = yield* initRepoWithCommit(cwd); yield* git(cwd, ["config", "diff.probe.textconv", "touch textconv-ran; echo converted"]); yield* git(cwd, ["config", "color.ui", "always"]); yield* git(cwd, ["config", "diff.relative", "true"]); + yield* git(cwd, ["config", "log.decorate", "short"]); yield* git(cwd, ["checkout", "-b", "feature/range"]); yield* writeTextFile(cwd, ".gitattributes", "*.doc diff=probe\n"); yield* writeTextFile(cwd, "notes.doc", "source line\n"); yield* writeTextFile(cwd, "plain.txt", "plain line\n"); yield* writeTextFile(cwd, "binary.dat", "binary\0data"); yield* git(cwd, ["add", "."]); - yield* git(cwd, ["commit", "-m", "range files"]); + const signingKey = `${yield* makeTmpDir("git-vcs-driver-signing-key-")}/key`; + const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; + const keygen = ChildProcess.make("ssh-keygen", [ + "-q", + "-t", + "ed25519", + "-N", + "", + "-f", + signingKey, + ]); + assert.equal(Number(yield* spawner.exitCode(keygen)), 0); + yield* git(cwd, ["config", "gpg.format", "ssh"]); + // A global signer such as 1Password's cannot use the fixture's generated key. + yield* git(cwd, ["config", "gpg.ssh.program", "ssh-keygen"]); + yield* git(cwd, ["config", "user.signingkey", `${signingKey}.pub`]); + yield* git(cwd, ["config", "log.showSignature", "true"]); + yield* git(cwd, ["commit", "-S", "-m", "range files"]); const driver = yield* GitVcsDriver.GitVcsDriver; const fileSystem = yield* FileSystem.FileSystem; const projectCwd = `${cwd}/app`; @@ -2870,6 +2888,7 @@ it.layer(layerTest)("GitVcsDriver core integration", (it) => { const context = yield* driver.readRangeContext(projectCwd, initialBranch); + assert.match(context.commitSummary.trim(), /^[a-f0-9]+ range files$/); assert.include(context.diffPatch, "+source line"); assert.notInclude(context.diffPatch, "converted"); assert.include(context.diffPatch, "+plain line"); diff --git a/apps/server/src/vcs/GitVcsDriverCore.ts b/apps/server/src/vcs/GitVcsDriverCore.ts index 2736cbc6d4fcb..f8b59f389567b 100644 --- a/apps/server/src/vcs/GitVcsDriverCore.ts +++ b/apps/server/src/vcs/GitVcsDriverCore.ts @@ -2942,7 +2942,15 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* runGitStdoutWithOptions( "GitVcsDriver.readRangeContext.log", cwd, - ["log", "--oneline", "--no-color", "--end-of-options", commitRange], + [ + "log", + "--oneline", + "--no-color", + "--no-decorate", + "--no-show-signature", + "--end-of-options", + commitRange, + ], { maxOutputBytes: RANGE_COMMIT_SUMMARY_MAX_OUTPUT_BYTES, appendTruncationMarker: true,