Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ This repository is open source. Treat GitHub and other public surfaces as fully
- Treat workflow prompts and instructions as a first-class control surface. When agent behavior is off, debug prompt clarity before defaulting to code enforcement.
- `apps/docs/` is the public product documentation site (published at `https://docs.roomote.dev`) and should be kept in sync with user-facing product changes.
- Keep equivalent functionality in sync across supported source-control, communication, and sandbox providers whenever applicable. Do not intentionally make provider-specific exceptions unless the user explicitly requests one.
- When adding or changing a built-in automation, explicitly evaluate whether it needs text-based Additional rules for repository scope, per-repository communication-output routing, and residual workflow/report guidance. Opt in when its output goes to a communication provider and can contain material relevant to different people or teams; exclude inherently global, triage-oriented (except CI Failure Triage), and non-communication-output automations. Keep the eligibility metadata, settings UI, save-time compilation and validation, persisted automation settings, runtime scope/routing enforcement, and prompt propagation aligned.
- **Schema N-1 rollback guarantee:** Roomote must always be able to roll application code back one release against the current database. Do not drop tables or columns that the previous release still reads or writes in the same release that removes the feature. Stop using the columns in app code first, keep them in `packages/db` with an explicit N-1 comment, and drop them only after the next release is the supported rollback target. See `packages/db/AGENTS.md` for the package-local rules.

## Slack message formatting
Expand Down
19 changes: 12 additions & 7 deletions apps/docs/automations.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -491,8 +491,10 @@ For Gitea, repository webhook resync includes the `workflow_run` event so
Actions completions reach Roomote; host matching uses the deployment
`GITEA_BASE_URL`.

In **Settings > Automations > CI Failure Triage**, choose the standard report
destination and optionally describe **Additional rules** in natural language:
For **Suggest Ideas**, **Summarize Merged PRs**, **Security Auditor**, **Code
Quality Auditor**, **CI Failure Triage**, and **Merge announcer**, choose the
standard report destination and optionally describe **Additional rules** in
natural language:

> Only triage backend and platform. Send platform failures to #platform-ci in our Engineering Slack workspace.

Expand All @@ -502,13 +504,16 @@ workspace, when names could be ambiguous. Unclear, contradictory, unavailable,
or unsupported rules cannot be saved. An inference provider must be available
to interpret new rules. A failed save leaves the previous configuration intact.

Repository restrictions apply to webhook failures and **Run now**. Explicit
Repository restrictions apply to scheduled runs, **Run now**, and webhook runs
where the automation uses them. Explicit
restrictions select the matching repositories at save time; save revised rules
to include newly added repositories. Destination-only rules do not limit scope:
other repositories continue using the standard destination. Investigation and
report-writing guidance can also be included. Workflow, job, branch, and time
conditions are not supported in additional rules. Clear the rules to restore
all-repository triage using the standard destination.
other repositories continue using the standard destination. Workflow and
report-writing guidance can also be included. Pre-run workflow, job, branch,
and time conditions are not supported in Additional rules. Clear the rules to
restore the automation's all-repository behavior using the standard
destination. Existing **Suggestion preferences** and merged-PR **Additional
instructions** remain separate and keep their current meaning.

Repositories still need an active connection and a configured environment.
**Run now** starts at most one eligible investigation per click, using that
Expand Down
301 changes: 197 additions & 104 deletions apps/web/src/components/settings/automations/AutomationsSettings.tsx

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,40 +1,52 @@
'use client';

import type { ReactNode } from 'react';
import {
getTriggerableBackgroundAutomationDescriptorByKey,
type TriggerableBackgroundAutomationKey,
} from '@roomote/types';
import { Label, Textarea } from '@/components/system';

export function CiFailureTriageAdditionalRules({
export function AutomationAdditionalRules({
automationKey = 'ci_failure_triage',
value,
onChange,
error,
globalDestination,
}: {
automationKey?: TriggerableBackgroundAutomationKey;
value: string;
onChange: (value: string) => void;
error?: string;
globalDestination: ReactNode;
}) {
const automation =
getTriggerableBackgroundAutomationDescriptorByKey(automationKey);
const descriptor =
automation && 'additionalRules' in automation
? automation.additionalRules
: null;
if (!descriptor) return globalDestination;
const fieldId = `${automationKey.replaceAll('_', '-')}-additional-rules`;

return (
<div className="space-y-4">
{globalDestination}
<div className="space-y-2">
<Label htmlFor="ci-additional-rules">Additional rules (optional)</Label>
<Label htmlFor={fieldId}>Additional rules (optional)</Label>
<Textarea
id="ci-additional-rules"
id={fieldId}
value={value}
onChange={(event) => onChange(event.target.value)}
maxLength={8000}
placeholder="Only triage backend and platform. Send platform failures to #platform-ci in our Engineering Slack workspace."
aria-describedby="ci-additional-rules-help"
placeholder={descriptor.placeholder}
aria-describedby={`${fieldId}-help`}
aria-invalid={Boolean(error)}
/>
<p
id="ci-additional-rules-help"
className="text-sm text-muted-foreground"
>
Describe repository scope, report destinations, or investigation
guidance. Leave blank to triage all repositories using the destination
above. Rules are checked when you save.
<p id={`${fieldId}-help`} className="text-sm text-muted-foreground">
Describe repository scope, report destinations, or workflow guidance.
Leave blank to {descriptor.defaultScopeDescription} using the
destination above. Rules are checked when you save.
</p>
{error ? (
<p role="alert" className="text-sm text-destructive">
Expand Down
22 changes: 22 additions & 0 deletions apps/web/src/components/settings/automations/formState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ const DESTINATION_CHANNEL_FIELDS_BY_AUTOMATION_ID = Object.fromEntries(

export type FormState = {
ciFailureTriageAdditionalRules?: string;
suggesterAdditionalRules?: string;
announcerAdditionalRules?: string;
securityAuditorAdditionalRules?: string;
codeQualityAuditorAdditionalRules?: string;
mergeAnnouncerAdditionalRules?: string;
callRoomoteViaEmojiEnabled: boolean;
callRoomoteViaEmojiName: string;
callRoomoteViaEmojiInstructions: string;
Expand Down Expand Up @@ -207,12 +212,14 @@ const SUGGESTER_FIELDS: Array<keyof FormState> = [
'suggesterUseTelegram',
'suggesterUseTeams',
'suggesterInstructions',
'suggesterAdditionalRules',
];

const ANNOUNCER_FIELDS: Array<keyof FormState> = [
'announcerFrequency',
...DESTINATION_CHANNEL_FIELDS_BY_AUTOMATION_ID.announcer,
'announcerInstructions',
'announcerAdditionalRules',
];

const PLATFORM_ISSUE_ALERT_FIELDS: Array<keyof FormState> = [
Expand All @@ -228,6 +235,12 @@ const SCHEDULE_ONLY_AUTOMATION_FIELDS = Object.fromEntries(
...(automation.id === 'ciFailureTriage'
? (['ciFailureTriageAdditionalRules'] as const)
: []),
...(automation.id === 'securityAuditor'
? (['securityAuditorAdditionalRules'] as const)
: []),
...(automation.id === 'codeQualityAuditor'
? (['codeQualityAuditorAdditionalRules'] as const)
: []),
...(DESTINATION_CHANNEL_FIELDS_BY_AUTOMATION_ID[
automation.id as keyof typeof DESTINATION_CHANNEL_FIELDS_BY_AUTOMATION_ID
] ?? []),
Expand All @@ -239,6 +252,7 @@ const SCHEDULE_ONLY_AUTOMATION_FIELDS = Object.fromEntries(
'mergeAnnouncerTargetProvider',
'mergeAnnouncerTargetMode',
'mergeAnnouncerTargetChannelId',
'mergeAnnouncerAdditionalRules',
] as const)
: []),
],
Expand Down Expand Up @@ -348,6 +362,14 @@ export function buildAutomationSettingsSaveInput(
savingAutomation: automationId,
ciFailureTriageAdditionalRules:
stateToSave.ciFailureTriageAdditionalRules ?? '',
suggesterAdditionalRules: stateToSave.suggesterAdditionalRules ?? '',
announcerAdditionalRules: stateToSave.announcerAdditionalRules ?? '',
securityAuditorAdditionalRules:
stateToSave.securityAuditorAdditionalRules ?? '',
codeQualityAuditorAdditionalRules:
stateToSave.codeQualityAuditorAdditionalRules ?? '',
mergeAnnouncerAdditionalRules:
stateToSave.mergeAnnouncerAdditionalRules ?? '',
callRoomoteViaEmojiEnabled: stateToSave.callRoomoteViaEmojiEnabled,
callRoomoteViaEmojiName: stateToSave.callRoomoteViaEmojiName.trim() || null,
callRoomoteViaEmojiInstructions:
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading