Merge RepoSettings into Repo (#248)
* Merge RepoSettings into Repo Inline all RepoSettings fields (triggers, tools, instructions, scripts, defaultAgent) directly into the Repo model. Pivot Macro/Mode foreign keys from repoSettingsId to repoId. Drop the repo_settings table entirely. Migration backfills all existing data safely. Co-authored-by: Cursor <cursoragent@cursor.com> * Remove dead null-coalescing and defaultSettings fallback All settings fields are now NOT NULL on Repo, so ?? fallbacks in run-context are unnecessary. initialSettings is non-nullable, so the defaultSettings memo in RepoConsole was dead code. Co-authored-by: Cursor <cursoragent@cursor.com> * drop dead /workflows route, extract getAuthenticatedRepoContext helper - delete /api/repo/[owner]/[repo]/workflows/ (duplicate of /modes/, no consumers) - extract shared auth helper that returns { account, owner, repo, token, dbRepo, role } - update settings, macros, modes routes to use the helper Co-authored-by: Cursor <cursoragent@cursor.com> * type-safe API route returns via inferred NextResponse generics - add ApiResponse<T> utility type that extracts JSON body from route handlers - remove explicit return type annotations and dead interfaces from 5 routes - update 3 routes with existing type exports to use ApiResponse<typeof handler> - narrow error union in ReposTable fetchRepos Co-authored-by: Cursor <cursoragent@cursor.com> * run tests on push in addition to pull_request Co-authored-by: Cursor <cursoragent@cursor.com> * add rule: no --trailer flags on git commits Co-authored-by: Cursor <cursoragent@cursor.com> * move git trailer rule into Rules section Co-authored-by: Cursor <cursoragent@cursor.com> * consolidate Learnings into Rules section Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
committed by
pullfrog[bot]
parent
60da0e5749
commit
623e11c7ce
@@ -41449,28 +41449,35 @@ async function getIsCancelled(params) {
|
|||||||
}
|
}
|
||||||
log.info("[post] no cancellation found, assuming failure");
|
log.info("[post] no cancellation found, assuming failure");
|
||||||
} catch (error2) {
|
} catch (error2) {
|
||||||
log.warning(`[post] failed to get job status: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
log.warning(
|
||||||
|
`[post] failed to get job status: ${error2 instanceof Error ? error2.message : String(error2)}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
async function runPostCleanup() {
|
async function runPostCleanup() {
|
||||||
log.info("\xBB [post] starting post cleanup");
|
log.info("\xBB [post] starting post cleanup");
|
||||||
const runIdStr = process.env.GITHUB_RUN_ID;
|
const runIdStr = process.env.GITHUB_RUN_ID;
|
||||||
if (!runIdStr)
|
if (!runIdStr) return log.info("\xBB [post] no GITHUB_RUN_ID available, skipping cleanup");
|
||||||
return log.info("\xBB [post] no GITHUB_RUN_ID available, skipping cleanup");
|
|
||||||
let promptInput = null;
|
let promptInput = null;
|
||||||
try {
|
try {
|
||||||
const resolved = resolvePromptInput();
|
const resolved = resolvePromptInput();
|
||||||
if (typeof resolved !== "string") promptInput = resolved;
|
if (typeof resolved !== "string") promptInput = resolved;
|
||||||
} catch (error2) {
|
} catch (error2) {
|
||||||
log.warning(`[post] failed to resolve prompt input: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
log.warning(
|
||||||
|
`[post] failed to resolve prompt input: ${error2 instanceof Error ? error2.message : String(error2)}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
const token = getJobToken();
|
const token = getJobToken();
|
||||||
const repoContext = parseRepoContext();
|
const repoContext = parseRepoContext();
|
||||||
const octokit = createOctokit(token);
|
const octokit = createOctokit(token);
|
||||||
const commentId = await validateStuckProgressComment(promptInput, octokit, repoContext.owner, repoContext.name);
|
const commentId = await validateStuckProgressComment(
|
||||||
if (!commentId)
|
promptInput,
|
||||||
return log.info("\xBB [post] no stuck progress comment to update, skipping cleanup");
|
octokit,
|
||||||
|
repoContext.owner,
|
||||||
|
repoContext.name
|
||||||
|
);
|
||||||
|
if (!commentId) return log.info("\xBB [post] no stuck progress comment to update, skipping cleanup");
|
||||||
log.info(`\xBB [post] validated stuck comment: ${commentId}, updating with error message`);
|
log.info(`\xBB [post] validated stuck comment: ${commentId}, updating with error message`);
|
||||||
try {
|
try {
|
||||||
const body = buildErrorCommentBody({
|
const body = buildErrorCommentBody({
|
||||||
|
|||||||
@@ -68,8 +68,8 @@ async function validateStuckProgressComment(
|
|||||||
* While the job is still in_progress, the individual steps may have their conclusions set.
|
* While the job is still in_progress, the individual steps may have their conclusions set.
|
||||||
*/
|
*/
|
||||||
async function getIsCancelled(params: {
|
async function getIsCancelled(params: {
|
||||||
repoContext: ReturnType<typeof parseRepoContext>,
|
repoContext: ReturnType<typeof parseRepoContext>;
|
||||||
octokit: ReturnType<typeof createOctokit>,
|
octokit: ReturnType<typeof createOctokit>;
|
||||||
runIdStr: string;
|
runIdStr: string;
|
||||||
}): Promise<boolean> {
|
}): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
@@ -85,7 +85,7 @@ async function getIsCancelled(params: {
|
|||||||
// So we match jobs that START with the job ID
|
// So we match jobs that START with the job ID
|
||||||
const currentJobName = process.env.GITHUB_JOB;
|
const currentJobName = process.env.GITHUB_JOB;
|
||||||
const currentJob = currentJobName
|
const currentJob = currentJobName
|
||||||
? jobs.jobs.find(j => j.name === currentJobName || j.name.startsWith(`${currentJobName} (`))
|
? jobs.jobs.find((j) => j.name === currentJobName || j.name.startsWith(`${currentJobName} (`))
|
||||||
: jobs.jobs[0]; // fallback to first job
|
: jobs.jobs[0]; // fallback to first job
|
||||||
|
|
||||||
if (!currentJob) {
|
if (!currentJob) {
|
||||||
@@ -97,14 +97,16 @@ async function getIsCancelled(params: {
|
|||||||
if (currentJob.conclusion === "cancelled") return true; // whole job explicit cancellation
|
if (currentJob.conclusion === "cancelled") return true; // whole job explicit cancellation
|
||||||
|
|
||||||
// but if it's still null, check steps for cancellation:
|
// but if it's still null, check steps for cancellation:
|
||||||
const cancelledStep = currentJob.steps?.find(step => step.conclusion === "cancelled");
|
const cancelledStep = currentJob.steps?.find((step) => step.conclusion === "cancelled");
|
||||||
if (cancelledStep) {
|
if (cancelledStep) {
|
||||||
log.info(`[post] found cancelled step: ${cancelledStep.name}`);
|
log.info(`[post] found cancelled step: ${cancelledStep.name}`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
log.info("[post] no cancellation found, assuming failure");
|
log.info("[post] no cancellation found, assuming failure");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.warning(`[post] failed to get job status: ${error instanceof Error ? error.message : String(error)}`);
|
log.warning(
|
||||||
|
`[post] failed to get job status: ${error instanceof Error ? error.message : String(error)}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return false; // assuming failure
|
return false; // assuming failure
|
||||||
}
|
}
|
||||||
@@ -114,8 +116,7 @@ async function runPostCleanup(): Promise<void> {
|
|||||||
|
|
||||||
const runIdStr = process.env.GITHUB_RUN_ID;
|
const runIdStr = process.env.GITHUB_RUN_ID;
|
||||||
|
|
||||||
if (!runIdStr)
|
if (!runIdStr) return log.info("» [post] no GITHUB_RUN_ID available, skipping cleanup");
|
||||||
return log.info("» [post] no GITHUB_RUN_ID available, skipping cleanup");
|
|
||||||
|
|
||||||
// resolve prompt input once and use it for both issue number and comment ID extraction
|
// resolve prompt input once and use it for both issue number and comment ID extraction
|
||||||
// only use the object form (JSON payload), not plain string prompts
|
// only use the object form (JSON payload), not plain string prompts
|
||||||
@@ -124,7 +125,9 @@ async function runPostCleanup(): Promise<void> {
|
|||||||
const resolved = resolvePromptInput();
|
const resolved = resolvePromptInput();
|
||||||
if (typeof resolved !== "string") promptInput = resolved;
|
if (typeof resolved !== "string") promptInput = resolved;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.warning(`[post] failed to resolve prompt input: ${error instanceof Error ? error.message : String(error)}`);
|
log.warning(
|
||||||
|
`[post] failed to resolve prompt input: ${error instanceof Error ? error.message : String(error)}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get job token for API calls
|
// get job token for API calls
|
||||||
@@ -133,10 +136,14 @@ async function runPostCleanup(): Promise<void> {
|
|||||||
const octokit = createOctokit(token);
|
const octokit = createOctokit(token);
|
||||||
|
|
||||||
// validate that progressCommentId from prompt input is stuck on "Leaping into action"
|
// validate that progressCommentId from prompt input is stuck on "Leaping into action"
|
||||||
const commentId = await validateStuckProgressComment(promptInput, octokit, repoContext.owner, repoContext.name);
|
const commentId = await validateStuckProgressComment(
|
||||||
|
promptInput,
|
||||||
|
octokit,
|
||||||
|
repoContext.owner,
|
||||||
|
repoContext.name
|
||||||
|
);
|
||||||
|
|
||||||
if (!commentId)
|
if (!commentId) return log.info("» [post] no stuck progress comment to update, skipping cleanup");
|
||||||
return log.info("» [post] no stuck progress comment to update, skipping cleanup");
|
|
||||||
|
|
||||||
log.info(`» [post] validated stuck comment: ${commentId}, updating with error message`);
|
log.info(`» [post] validated stuck comment: ${commentId}, updating with error message`);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user