mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-21 00:02:30 +00:00
fix: enable a draft-only schedule the way deploying it will
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ViTUkt4czrvZdxdWwxqRAQ
This commit is contained in:
co-authored by
Claude Opus 5
parent
e3658ec288
commit
db791f0493
@@ -55,6 +55,7 @@
|
||||
import { onUserInput } from '$lib/userDraftEditGate'
|
||||
import { isTemporaryPath, newItemPath, useItem, type ItemAdapter } from '$lib/itemStore.svelte'
|
||||
import {
|
||||
draftOnlyScheduleCfg,
|
||||
newScheduleCfg,
|
||||
normalizeScheduleCfg,
|
||||
scheduleCfgOf,
|
||||
@@ -192,9 +193,12 @@
|
||||
const s = await ScheduleService.getSchedule({ workspace, path, getDraft: true })
|
||||
// Drafts are saved in the form's config shape, over the deployed fields.
|
||||
const { draft, draft_saved_at, no_deployed, ...deployedSchedule } = s as any
|
||||
const loadedDraft = draft
|
||||
? normalizeScheduleCfg({ ...deployedSchedule, ...draft })
|
||||
: undefined
|
||||
return {
|
||||
deployed: no_deployed ? undefined : normalizeScheduleCfg(deployedSchedule),
|
||||
draft: draft ? normalizeScheduleCfg({ ...deployedSchedule, ...draft }) : undefined,
|
||||
draft: no_deployed && loadedDraft ? draftOnlyScheduleCfg(loadedDraft) : loadedDraft,
|
||||
draftSavedAt: draft_saved_at
|
||||
}
|
||||
} catch (err) {
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import { normalizeScheduleCfg, scheduleCfgOf, scheduleFormOf } from './scheduleCfg'
|
||||
import {
|
||||
draftOnlyScheduleCfg,
|
||||
normalizeScheduleCfg,
|
||||
scheduleCfgOf,
|
||||
scheduleFormOf
|
||||
} from './scheduleCfg'
|
||||
|
||||
// A deployed schedule as the API returns it: server fields the form never shows, a short cron.
|
||||
const deployed = {
|
||||
@@ -37,4 +42,17 @@ describe('schedule config normalization', () => {
|
||||
})
|
||||
expect(once).not.toHaveProperty('edited_by')
|
||||
})
|
||||
|
||||
// Deploying a draft-only schedule creates it, and a create always enables it. A draft that
|
||||
// kept its stored state would show a disabled schedule the server has enabled, and later
|
||||
// updates omit the field, so nothing would ever correct it.
|
||||
it('records a draft-only schedule as enabled, however it was stored', () => {
|
||||
expect(
|
||||
draftOnlyScheduleCfg(normalizeScheduleCfg({ ...deployed, enabled: false }))
|
||||
).toMatchObject({ enabled: true })
|
||||
const { enabled: _dropped, ...withoutEnabled } = deployed
|
||||
expect(draftOnlyScheduleCfg(normalizeScheduleCfg(withoutEnabled))).toMatchObject({
|
||||
enabled: true
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -173,6 +173,16 @@ export function normalizeScheduleCfg(raw: ScheduleCfg): ScheduleCfg {
|
||||
return scheduleCfgOf(scheduleFormOf(raw))
|
||||
}
|
||||
|
||||
/**
|
||||
* A schedule that exists only as a draft, as deploying it will leave it: deploying one creates
|
||||
* it, and a create always enables it (`writeScheduleCfg`), so the draft has to carry the state
|
||||
* that create produces. Left as stored, a disabled draft would record `enabled: false` against
|
||||
* a server that says otherwise, and later updates omit the field, so nothing corrects it.
|
||||
*/
|
||||
export function draftOnlyScheduleCfg(cfg: ScheduleCfg): ScheduleCfg {
|
||||
return { ...cfg, enabled: true }
|
||||
}
|
||||
|
||||
/** The handlers a new schedule starts with, from the workspace's defaults. */
|
||||
async function workspaceDefaultHandlers(workspace: string): Promise<ScheduleCfg> {
|
||||
const [error, recovery, success] = (await Promise.all(
|
||||
|
||||
Reference in New Issue
Block a user