feat: Add time saved mode workflow setting (#22343)

This commit is contained in:
Stephen Wright
2025-11-26 15:45:36 +00:00
committed by GitHub
parent df81c77a24
commit b2f78d7c7a
3 changed files with 30 additions and 0 deletions
@@ -405,6 +405,15 @@ export class WorkflowsController {
let updateData = new WorkflowEntity();
const { tags, parentFolderId, ...rest } = req.body;
// TODO: Add zod validation for entire `rest` object before assigning to `updateData`
if (
rest.settings?.timeSavedMode !== undefined &&
!['fixed', 'dynamic'].includes(rest.settings.timeSavedMode)
) {
throw new BadRequestError('Invalid timeSavedMode');
}
Object.assign(updateData, rest);
const isSharingEnabled = this.license.isSharingEnabled();
@@ -2458,6 +2458,8 @@ describe('PATCH /workflows/:workflowId', () => {
saveDataSuccessExecution: 'all',
executionTimeout: 3600,
timezone: 'America/New_York',
timeSavedMode: 'fixed',
timeSavedPerExecution: 10,
},
};
@@ -2468,6 +2470,8 @@ describe('PATCH /workflows/:workflowId', () => {
} = response.body;
expect(response.statusCode).toBe(200);
expect(response.body.data.settings.timeSavedMode).toBe('fixed');
expect(response.body.data.settings.timeSavedPerExecution).toBe(10);
expect(id).toBe(workflow.id);
expect(await workflowHistoryRepository.count({ where: { workflowId: id } })).toBe(2);
@@ -2723,6 +2727,22 @@ describe('PATCH /workflows/:workflowId', () => {
expect(updatedWorkflow.parentFolder).toBe(null);
});
test('should fail if an invalid timeSavedMode is provided', async () => {
const workflow = await createWorkflow({}, owner);
const payload = {
name: 'name updated',
versionId: workflow.versionId,
settings: {
timeSavedMode: 'invalid' as 'fixed' | 'dynamic',
},
};
const response = await authOwnerAgent.patch(`/workflows/${workflow.id}`).send(payload);
expect(response.statusCode).toBe(400);
expect(response.body.message).toBe('Invalid timeSavedMode');
});
test('should fail if trying update workflow parent folder with a folder that does not belong to project', async () => {
const ownerPersonalProject = await projectRepository.getPersonalProjectForUserOrFail(owner.id);
const memberPersonalProject = await projectRepository.getPersonalProjectForUserOrFail(
+1
View File
@@ -2738,6 +2738,7 @@ export interface IWorkflowSettings {
executionTimeout?: number;
executionOrder?: 'v0' | 'v1';
timeSavedPerExecution?: number;
timeSavedMode?: 'fixed' | 'dynamic';
availableInMCP?: boolean;
}