fix author git publication recovery

This commit is contained in:
2026-08-12 01:29:41 +02:00
parent 7741e61045
commit a5c4a355b4
3 changed files with 16 additions and 7 deletions
+14 -3
View File
@@ -232,6 +232,10 @@ export class GitWorkspaceRepository {
try {
await this.git(["push", "origin", `${revision}:refs/heads/${this.config.branch}`]);
} catch (error) {
// `git` already returns a sanitized WorkspaceRegistryError. Preserve it rather
// than mapping its public code a second time (notably git_push_rejected).
await this.restoreFailedPublication();
if (error instanceof WorkspaceRegistryError) throw error;
throw this.sanitizeGitError(error);
}
}
@@ -239,9 +243,16 @@ export class GitWorkspaceRepository {
/** Create a local publication commit without contacting the remote. */
async commitOnly(paths: readonly string[], message: string): Promise<GitStatus> {
if (paths.length === 0 || paths.some((path) => !this.isRegistryArtifactPath(path))) throw new WorkspaceRegistryError("workspace_invalid", "Workspace repository path is invalid");
await this.git(["add", "--", ...paths]);
await this.git(["commit", "-m", message], this.publicationIdentity());
return await this.status();
try {
await this.git(["add", "--", ...paths]);
await this.git(["commit", "-m", message], this.publicationIdentity());
return await this.status();
} catch (error) {
// A failed prepare must not leave staged or generated artifacts in the
// long-lived author checkout for the next request.
await this.restoreFailedPublication();
throw error;
}
}
/** Commit and push a fixed set of validated artifact paths without exposing Git output. */
+1 -3
View File
@@ -1142,9 +1142,7 @@ test("rejects a symbolic-link registry root before creating a lock below it", as
const root = join(remote.root, "registry-link");
mkdirSync(target);
symlinkSync(target, root);
const registry = makeRegistry(config(root, remote.remote));
await expect(bootstrap(registry)).rejects.toMatchObject({ code: "git_unavailable" });
expect(() => makeRegistry(config(root, remote.remote))).toThrow("invalid sessions root");
expect(existsSync(join(target, "locks"))).toBe(false);
});
@@ -83,7 +83,7 @@ async function git(cwd: string, args: string[]): Promise<string> {
}
async function fixture(workspaceSource = filesystemWorkspace) {
const root = mkdtempSync(join(tmpdir(), "tht-runtime-handoff-"));
const root = realpathSync(mkdtempSync(join(tmpdir(), "tht-runtime-handoff-")));
roots.push(root);
const remote = join(root, "remote.git");
const source = join(root, "source");