Skip to content

feat(deploy): write frequency, retry strategy, alert policy and assertions back into the code - #1495

Open
sorccu wants to merge 3 commits into
simo/red-985-deploy-write-backfrom
simo/red-986-deploy-write-back-helpers
Open

sorccu wants to merge 3 commits into
simo/red-985-deploy-write-backfrom
simo/red-986-deploy-write-back-helpers

Conversation

@sorccu

@sorccu sorccu commented Sep 21, 2026

Copy link
Copy Markdown
Member

Summary

The interactive checkly deploy write-back (#1494) wrote only literal values. It now also writes the properties a construct spells with a helper, in the form checkly import generates:

Property Written as
frequency Frequency.EVERY_30S for a sub-minute schedule; a plain number where the code already spells one; Frequency.EVERY_10M when the property is added
retryStrategy RetryStrategyBuilder.fixedStrategy({ maxRetries: 3 }), noRetries(), …
alertEscalationPolicy AlertEscalationBuilder.runBasedEscalation(3, …) / timeBasedEscalation(…); 'global' on a CheckGroupV2 moved to the global policy
request.assertions, apiCheckDefaults.assertions AssertionBuilder.statusCode().equals(200) and the corresponding builder of each monitor class (UrlAssertionBuilder, TcpAssertionBuilder, …)

The expression is built by the same codegen the import command uses, then rendered in the file's own quotes, indentation, line ending and trailing-comma habit. A helper the file does not import is appended to its import { … } from 'checkly/constructs' (or the require of it); no statement is ever added, and the report lists what was imported.

The rules of #1494 stay: an existing value is replaced only when replacing it loses nothing written by hand (a plain literal, null, or a call/member/new chain on the same helper whose arguments are literals), every rewrite is read back structurally before the file is written, and everything else is listed as not updated with a reason. New reasons: a helper call holding a variable, doubleCheck set beside a retry strategy, a check (or v1 group) moved to the global alert policy or a group without a policy of its own (nothing is ever removed from the code), a value the codegen cannot spell, a helper name the file already uses for something else, a file with no checkly/constructs import to extend.

Changes

  • fix(codegen): valueForAlertEscalation kept its positional arguments aligned only when every earlier one was present (a policy without reminders put its parallel-run threshold in the reminders slot; one without a threshold put the reminders in the numeric slot); valueForRetryStrategy threw on onlyOn: null. Both also affected checkly import.
  • services/write-back/helper-edit.ts: builds the expression with the codegen, renders it in the file style, decides what may be replaced, verifies a rewrite.
  • services/write-back/imports.ts: finds the local name a helper is bound to, refuses a clash, appends missing names to the file's checkly/constructs declaration.
  • services/write-back/apply-edits.ts: applyEdits (was applyLiteralEdits in literal-edit.ts) applies both edit kinds and the import splice, and reads them back.
  • services/write-back/plan.ts: the rule table gains the helper rules with companions (/frequencyOffsetfrequency, /useGlobalAlertSettingsalertEscalationPolicy, a code-origin /doubleCheck marks retryStrategy as locally changed); per class, the props the codegen omits are left out (AgenticCheck and PlaywrightCheck take no retryStrategy; AgenticCheck now gets frequency, which it does take). WriteBackPlan.imports lists the helpers added per file.
  • commands/deploy.ts: prints <file>: imported X, Y from checkly/constructs under each file's lines; a multi-line value is shown on one line.
  • constructs/playwright-check-codegen.ts: the omitted props are an exported constant, as the agentic ones already were, so the write-back table and its spec read the same source.
  • ai-context/references/configure.md: the bullet on the choice.

Accepted limitations

  • A value spelled with a variable, a spread or a TS wrapper (as, satisfies) is not rewritten.
  • Comments inside a replaced helper expression are lost, as inside a replaced literal.
  • The rendering is the checkly import form: options equal to the builder's defaults are elided.
  • A property the construct inherits from checkly.config.ts or a group default is inserted into the construct, pinning it, as feat(deploy): offer to write changes made in Checkly back into the code [RED-985] #1494 already does for literals.
  • runParallel and doubleCheck are not written.

Testing

  • Unit: helper-edit.spec.ts (rendering in every style, replaceability, imports in every layout, read-back, every assertion builder, agreement with sourcegen's printer), plan.spec.ts (the table per class against the codegens' omitted props, each helper property, the companions, the refusals), confirm-flow-deploy.spec.ts (the prompt writing a Frequency constant and its import), the two codegen specs.
  • No e2e: the prompt needs a TTY.

Stacked on #1494 (RED-985). Docs: checkly/docs#517, to merge with the CLI release.

🤖 Generated with Claude Code

sorccu and others added 3 commits September 22, 2026 03:27
…ondition as unset [RED-986]

`valueForAlertEscalation` appended the builder's positional arguments only
when present, so a policy without reminders put its parallel-run threshold
in the reminders slot, and one without a threshold put the reminders in the
required numeric slot. A missing reminders slot is now held by `undefined`
and a missing threshold gets the builder's own default.

`valueForRetryStrategy` threw on `onlyOn: null`, which is how a stored row
spells an unset condition, and rendered `onlyOn: []` for an empty list;
both, and an empty string, are now unset.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…D-986]

The write-back can now spell a property the way `checkly import` does when
the construct takes a helper rather than a literal: `Frequency.EVERY_30S`,
`RetryStrategyBuilder.fixedStrategy({ … })`,
`AlertEscalationBuilder.runBasedEscalation(…)`, and an assertion list built
with the monitor class's own builder. The expression comes from the same
codegen the import command uses; only the rendering differs, following the
file's quotes, indentation, line ending and trailing-comma habit.

An existing value is replaced only when replacing it loses nothing written
by hand: a plain literal, null, or a member, call or `new` chain on the same
helper whose arguments are literals. The helper class is used under the
name the file binds it to, or appended to the file's `checkly/constructs`
import (or `require`) when it lacks it; a name the file already uses for
something else refuses the edit, and no statement is ever added. Every
written expression is read back structurally before the file is written.

The rule table that produces such edits follows in the next commit; the
planner only takes the renamed `applyEdits` and the shared read-back here.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…sertions [RED-986]

The deploy write-back now writes the properties a construct spells with a
helper: `frequency` (a `Frequency` constant for a sub-minute schedule, a
number where the code already uses one), `retryStrategy`
(`RetryStrategyBuilder`), `alertEscalationPolicy`
(`AlertEscalationBuilder`, or the word `'global'` on a v2 group) and the
`assertions` of a request or of a group's API defaults, each with the
monitor class's own builder. A helper the file lacks is added to its
`checkly/constructs` import, and the report says so.

The rule table gains companions: `/frequencyOffset` belongs to
`frequency` (only for a sub-minute schedule), `/useGlobalAlertSettings` to
`alertEscalationPolicy`, and a code-origin `/doubleCheck` marks
`retryStrategy` as locally changed. A candidate is anchored to its
target's own rule whichever change created it, and each change is
cross-checked against the pointer that matched it; a leaf that became a
subtree (a strategy where there was null, a policy that gained reminders)
passes that check. Per class, the props the codegen omits (agentic and
Playwright checks take no retry strategy) are left out, which the spec
asserts against the same constants.

`doubleCheck` and `runParallel` stay unwritten, with reasons of their own.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant