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 { try {
await this.git(["push", "origin", `${revision}:refs/heads/${this.config.branch}`]); await this.git(["push", "origin", `${revision}:refs/heads/${this.config.branch}`]);
} catch (error) { } 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); throw this.sanitizeGitError(error);
} }
} }
@@ -239,9 +243,16 @@ export class GitWorkspaceRepository {
/** Create a local publication commit without contacting the remote. */ /** Create a local publication commit without contacting the remote. */
async commitOnly(paths: readonly string[], message: string): Promise<GitStatus> { 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"); 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]); try {
await this.git(["commit", "-m", message], this.publicationIdentity()); await this.git(["add", "--", ...paths]);
return await this.status(); 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. */ /** 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"); const root = join(remote.root, "registry-link");
mkdirSync(target); mkdirSync(target);
symlinkSync(target, root); symlinkSync(target, root);
const registry = makeRegistry(config(root, remote.remote)); expect(() => makeRegistry(config(root, remote.remote))).toThrow("invalid sessions root");
await expect(bootstrap(registry)).rejects.toMatchObject({ code: "git_unavailable" });
expect(existsSync(join(target, "locks"))).toBe(false); 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) { 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); roots.push(root);
const remote = join(root, "remote.git"); const remote = join(root, "remote.git");
const source = join(root, "source"); const source = join(root, "source");