feat(fleet): per-repo verify + auto-merge options for PR jobs
Add job-level verify (command run in the PR checkout before opening the PR) and autoMerge (squash-merge the PR once opened). Surfaced in the New Job form as a Verify-command field + Auto-merge checkbox (PR mode only); confirmation now shows PR-mode/repo. More repos added to the dropdown. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
2adddce754
commit
c239abeec9
@ -40,6 +40,11 @@ const FLEET_REPOS = [
|
||||
'learning_ai_2nd_brain',
|
||||
'learning_ai_auth_app',
|
||||
'learning_agent_monitoring_fx',
|
||||
'learning_notif_scanr',
|
||||
'learning_ai_local_llms',
|
||||
'learning_ai_mac_tooling',
|
||||
'learning_ai_productivity_web',
|
||||
'learning_ai_webui_copilot',
|
||||
];
|
||||
const FLEET_BASE_BRANCH = 'main';
|
||||
|
||||
@ -55,6 +60,8 @@ export default function FleetJobsPage() {
|
||||
const [priority, setPriority] = useState<'critical' | 'high' | 'medium' | 'low'>('high');
|
||||
const [caps, setCaps] = useState('build');
|
||||
const [repo, setRepo] = useState('');
|
||||
const [verifyCmd, setVerifyCmd] = useState('');
|
||||
const [autoMerge, setAutoMerge] = useState(false);
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const [submitMsg, setSubmitMsg] = useState<{ ok: boolean; text: string } | null>(null);
|
||||
|
||||
@ -95,9 +102,24 @@ export default function FleetJobsPage() {
|
||||
bodyMd: body.trim(),
|
||||
priority,
|
||||
capabilities,
|
||||
...(repo ? { repo, baseBranch: FLEET_BASE_BRANCH } : {}),
|
||||
...(repo
|
||||
? {
|
||||
repo,
|
||||
baseBranch: FLEET_BASE_BRANCH,
|
||||
...(verifyCmd.trim() ? { verify: verifyCmd.trim() } : {}),
|
||||
...(autoMerge ? { autoMerge: true } : {}),
|
||||
}
|
||||
: {}),
|
||||
});
|
||||
setSubmitMsg({
|
||||
ok: true,
|
||||
text:
|
||||
`Submitted ${job.id} (stage: ${job.stage})` +
|
||||
(repo
|
||||
? ` — PR mode: ${repo}@${FLEET_BASE_BRANCH}${verifyCmd.trim() ? ' +verify' : ''}${autoMerge ? ' +auto-merge' : ''}`
|
||||
: ' — no PR (plain job)') +
|
||||
'.',
|
||||
});
|
||||
setSubmitMsg({ ok: true, text: `Submitted ${job.id} (stage: ${job.stage}).` });
|
||||
setBody('');
|
||||
await refresh();
|
||||
} catch (err: unknown) {
|
||||
@ -106,7 +128,7 @@ export default function FleetJobsPage() {
|
||||
} finally {
|
||||
setSubmitting(false);
|
||||
}
|
||||
}, [body, caps, priority, repo, refresh]);
|
||||
}, [body, caps, priority, repo, verifyCmd, autoMerge, refresh]);
|
||||
|
||||
return (
|
||||
<div className="p-6 space-y-6">
|
||||
@ -191,6 +213,34 @@ export default function FleetJobsPage() {
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
{repo && (
|
||||
<div>
|
||||
<label htmlFor="job-verify" className="mb-1 block text-sm font-medium">
|
||||
Verify command (optional)
|
||||
</label>
|
||||
<input
|
||||
id="job-verify"
|
||||
value={verifyCmd}
|
||||
onChange={e => setVerifyCmd(e.target.value)}
|
||||
placeholder="e.g. pnpm install && pnpm test"
|
||||
className="w-64 rounded border bg-background px-2 py-1 text-sm font-mono"
|
||||
/>
|
||||
<p className="mt-1 text-xs text-muted-foreground">
|
||||
Runs in the checkout; the PR opens only if it passes.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
{repo && (
|
||||
<label className="flex items-center gap-2 self-end pb-1 text-sm">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={autoMerge}
|
||||
onChange={e => setAutoMerge(e.target.checked)}
|
||||
aria-label="Auto-merge the PR when opened"
|
||||
/>
|
||||
Auto-merge PR
|
||||
</label>
|
||||
)}
|
||||
<Button onClick={handleSubmit} disabled={submitting} aria-label="Submit new job">
|
||||
{submitting ? 'Submitting…' : 'Submit Job'}
|
||||
</Button>
|
||||
|
||||
@ -202,6 +202,9 @@ export interface SubmitJobBody {
|
||||
/** PR mode: open a PR against this repo (`owner/name` or clone URL) + base branch. */
|
||||
repo?: string;
|
||||
baseBranch?: string;
|
||||
/** PR mode: verify command run in the checkout before the PR opens; auto-merge the PR. */
|
||||
verify?: string;
|
||||
autoMerge?: boolean;
|
||||
}
|
||||
|
||||
/** Submit a new fleet job. Returns the created job. */
|
||||
|
||||
@ -214,6 +214,8 @@ export async function submitJob(productId: string, input: SubmitJobInput): Promi
|
||||
trackerItemId: input.trackerItemId,
|
||||
repo: input.repo,
|
||||
baseBranch: input.baseBranch,
|
||||
verify: input.verify,
|
||||
autoMerge: input.autoMerge,
|
||||
attempts: 0,
|
||||
leaseEpoch: 0,
|
||||
rev: 0,
|
||||
|
||||
@ -185,6 +185,8 @@ export const FleetJobDocSchema = z.object({
|
||||
*/
|
||||
repo: z.string().optional(),
|
||||
baseBranch: z.string().optional(),
|
||||
verify: z.string().optional(),
|
||||
autoMerge: z.boolean().optional(),
|
||||
checkpoint: CheckpointSchema.optional(),
|
||||
attempts: z.number().int().nonnegative().default(0),
|
||||
leaseEpoch: z.number().int().nonnegative().default(0),
|
||||
@ -352,6 +354,10 @@ export const SubmitJobSchema = z.object({
|
||||
/** Optional PR target (§PR mode): repo (`owner/name` or clone URL) + base branch. */
|
||||
repo: z.string().optional(),
|
||||
baseBranch: z.string().optional(),
|
||||
/** PR mode options: verify command to run in the checkout before opening the PR,
|
||||
* and whether to auto-merge the PR once opened. */
|
||||
verify: z.string().optional(),
|
||||
autoMerge: z.boolean().optional(),
|
||||
/** Phase 3 DAG: inline children to create atomically with the parent. */
|
||||
children: z
|
||||
.array(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user