feat: add prepush lifecycle hook (#498)
* feat: add prepush lifecycle hook Add `prepushScript` configuration — an optional shell script that runs automatically before pushing code to the remote repository. Reuses the existing `executeLifecycleHook` infrastructure (bash execution, 2-min timeout, error propagation on non-zero exit). When unconfigured the hook is a no-op. Made-with: Cursor * fix: add prepushScript to run-context API response, fix UI separator Include prepushScript in the settings returned by the run-context endpoint so the hook actually fires in production. Also fix the separator pattern in AgentSettings to match the existing convention (spacer + hr + spacer instead of margin). Made-with: Cursor
This commit is contained in:
committed by
pullfrog[bot]
parent
7454e66533
commit
cb8e33360c
@@ -146600,6 +146600,7 @@ ${status}`
|
|||||||
}
|
}
|
||||||
const refspec = branch === pushDest.remoteBranch ? branch : `${branch}:${pushDest.remoteBranch}`;
|
const refspec = branch === pushDest.remoteBranch ? branch : `${branch}:${pushDest.remoteBranch}`;
|
||||||
const pushArgs = force ? ["--force", "-u", pushDest.remoteName, refspec] : ["-u", pushDest.remoteName, refspec];
|
const pushArgs = force ? ["--force", "-u", pushDest.remoteName, refspec] : ["-u", pushDest.remoteName, refspec];
|
||||||
|
await executeLifecycleHook({ event: "prepush", script: ctx.prepushScript });
|
||||||
log.debug(`pushing ${branch} to ${pushDest.remoteName}/${pushDest.remoteBranch}`);
|
log.debug(`pushing ${branch} to ${pushDest.remoteName}/${pushDest.remoteBranch}`);
|
||||||
if (force) {
|
if (force) {
|
||||||
log.warning(`force pushing - this will overwrite remote history`);
|
log.warning(`force pushing - this will overwrite remote history`);
|
||||||
@@ -150509,6 +150510,7 @@ var defaultSettings = {
|
|||||||
modes: [],
|
modes: [],
|
||||||
setupScript: null,
|
setupScript: null,
|
||||||
postCheckoutScript: null,
|
postCheckoutScript: null,
|
||||||
|
prepushScript: null,
|
||||||
push: "restricted",
|
push: "restricted",
|
||||||
shell: "restricted",
|
shell: "restricted",
|
||||||
prApproveEnabled: false,
|
prApproveEnabled: false,
|
||||||
@@ -150547,7 +150549,8 @@ async function fetchRunContext(params) {
|
|||||||
...data.settings,
|
...data.settings,
|
||||||
modes: data.settings?.modes ?? [],
|
modes: data.settings?.modes ?? [],
|
||||||
setupScript: data.settings?.setupScript ?? null,
|
setupScript: data.settings?.setupScript ?? null,
|
||||||
postCheckoutScript: data.settings?.postCheckoutScript ?? null
|
postCheckoutScript: data.settings?.postCheckoutScript ?? null,
|
||||||
|
prepushScript: data.settings?.prepushScript ?? null
|
||||||
},
|
},
|
||||||
apiToken: data.apiToken,
|
apiToken: data.apiToken,
|
||||||
oss: data.oss ?? false,
|
oss: data.oss ?? false,
|
||||||
@@ -150976,6 +150979,7 @@ async function main() {
|
|||||||
apiToken: runContext.apiToken,
|
apiToken: runContext.apiToken,
|
||||||
modes: modes2,
|
modes: modes2,
|
||||||
postCheckoutScript: runContext.repoSettings.postCheckoutScript,
|
postCheckoutScript: runContext.repoSettings.postCheckoutScript,
|
||||||
|
prepushScript: runContext.repoSettings.prepushScript,
|
||||||
prApproveEnabled: runContext.repoSettings.prApproveEnabled,
|
prApproveEnabled: runContext.repoSettings.prApproveEnabled,
|
||||||
modeInstructions: runContext.repoSettings.modeInstructions,
|
modeInstructions: runContext.repoSettings.modeInstructions,
|
||||||
toolState,
|
toolState,
|
||||||
|
|||||||
@@ -275,6 +275,7 @@ export async function main(): Promise<MainResult> {
|
|||||||
apiToken: runContext.apiToken,
|
apiToken: runContext.apiToken,
|
||||||
modes,
|
modes,
|
||||||
postCheckoutScript: runContext.repoSettings.postCheckoutScript,
|
postCheckoutScript: runContext.repoSettings.postCheckoutScript,
|
||||||
|
prepushScript: runContext.repoSettings.prepushScript,
|
||||||
prApproveEnabled: runContext.repoSettings.prApproveEnabled,
|
prApproveEnabled: runContext.repoSettings.prApproveEnabled,
|
||||||
modeInstructions: runContext.repoSettings.modeInstructions,
|
modeInstructions: runContext.repoSettings.modeInstructions,
|
||||||
toolState,
|
toolState,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { regex } from "arkregex";
|
|||||||
import { type } from "arktype";
|
import { type } from "arktype";
|
||||||
import { log } from "../utils/cli.ts";
|
import { log } from "../utils/cli.ts";
|
||||||
import { $git } from "../utils/gitAuth.ts";
|
import { $git } from "../utils/gitAuth.ts";
|
||||||
|
import { executeLifecycleHook } from "../utils/lifecycle.ts";
|
||||||
import { $ } from "../utils/shell.ts";
|
import { $ } from "../utils/shell.ts";
|
||||||
import type { StoredPushDest, ToolContext } from "./server.ts";
|
import type { StoredPushDest, ToolContext } from "./server.ts";
|
||||||
import { execute, tool } from "./shared.ts";
|
import { execute, tool } from "./shared.ts";
|
||||||
@@ -143,6 +144,8 @@ export function PushBranchTool(ctx: ToolContext) {
|
|||||||
? ["--force", "-u", pushDest.remoteName, refspec]
|
? ["--force", "-u", pushDest.remoteName, refspec]
|
||||||
: ["-u", pushDest.remoteName, refspec];
|
: ["-u", pushDest.remoteName, refspec];
|
||||||
|
|
||||||
|
await executeLifecycleHook({ event: "prepush", script: ctx.prepushScript });
|
||||||
|
|
||||||
log.debug(`pushing ${branch} to ${pushDest.remoteName}/${pushDest.remoteBranch}`);
|
log.debug(`pushing ${branch} to ${pushDest.remoteName}/${pushDest.remoteBranch}`);
|
||||||
if (force) {
|
if (force) {
|
||||||
log.warning(`force pushing - this will overwrite remote history`);
|
log.warning(`force pushing - this will overwrite remote history`);
|
||||||
|
|||||||
@@ -135,6 +135,7 @@ export interface ToolContext {
|
|||||||
apiToken: string;
|
apiToken: string;
|
||||||
modes: Mode[];
|
modes: Mode[];
|
||||||
postCheckoutScript: string | null;
|
postCheckoutScript: string | null;
|
||||||
|
prepushScript: string | null;
|
||||||
prApproveEnabled: boolean;
|
prApproveEnabled: boolean;
|
||||||
modeInstructions: Record<string, string>;
|
modeInstructions: Record<string, string>;
|
||||||
toolState: ToolState;
|
toolState: ToolState;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ export interface RepoSettings {
|
|||||||
modes: Mode[];
|
modes: Mode[];
|
||||||
setupScript: string | null;
|
setupScript: string | null;
|
||||||
postCheckoutScript: string | null;
|
postCheckoutScript: string | null;
|
||||||
|
prepushScript: string | null;
|
||||||
push: PushPermission;
|
push: PushPermission;
|
||||||
shell: ShellPermission;
|
shell: ShellPermission;
|
||||||
prApproveEnabled: boolean;
|
prApproveEnabled: boolean;
|
||||||
@@ -33,6 +34,7 @@ const defaultSettings: RepoSettings = {
|
|||||||
modes: [],
|
modes: [],
|
||||||
setupScript: null,
|
setupScript: null,
|
||||||
postCheckoutScript: null,
|
postCheckoutScript: null,
|
||||||
|
prepushScript: null,
|
||||||
push: "restricted",
|
push: "restricted",
|
||||||
shell: "restricted",
|
shell: "restricted",
|
||||||
prApproveEnabled: false,
|
prApproveEnabled: false,
|
||||||
@@ -93,6 +95,7 @@ export async function fetchRunContext(params: {
|
|||||||
modes: data.settings?.modes ?? [],
|
modes: data.settings?.modes ?? [],
|
||||||
setupScript: data.settings?.setupScript ?? null,
|
setupScript: data.settings?.setupScript ?? null,
|
||||||
postCheckoutScript: data.settings?.postCheckoutScript ?? null,
|
postCheckoutScript: data.settings?.postCheckoutScript ?? null,
|
||||||
|
prepushScript: data.settings?.prepushScript ?? null,
|
||||||
},
|
},
|
||||||
apiToken: data.apiToken,
|
apiToken: data.apiToken,
|
||||||
oss: data.oss ?? false,
|
oss: data.oss ?? false,
|
||||||
|
|||||||
Reference in New Issue
Block a user