feat(cli): convert checkly config validation to diagnostics [RED-914] - #1455
Open
sorccu wants to merge 5 commits into
Open
feat(cli): convert checkly config validation to diagnostics [RED-914]#1455sorccu wants to merge 5 commits into
sorccu wants to merge 5 commits into
Conversation
…cklyConfig [RED-914] Convert the four throw-based, fail-fast config validators to report through the Diagnostics system instead. All config problems are now collected in a single run into a ConfigFileDiagnostics collector that attributes each diagnostic to the config file. When any fatal diagnostic is present, loading fails with a new InvalidConfigError carrying the diagnostics; otherwise the collector is returned alongside the config for later rendering. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…yer [RED-914] Add CommandStyle.diagnostics() as the single severity-to-renderer dispatch, AuthCommand.validateProject() to absorb the project validation block that was duplicated across five commands, and an InvalidConfigError branch in BaseCommand.catch() that renders the carried config diagnostics and exits 1, giving every command styled output for a fatally invalid config without per-command error handling. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ics first [RED-914] Wire the diagnostics returned by loadChecklyConfig into every command that loads a config: deploy, test, pw-test, validate and import plan seed them into project validation so config diagnostics render ahead of project diagnostics, while destroy, trigger and the other import commands render them right after loading. Fatal config diagnostics abort every command via the shared InvalidConfigError handling. trigger no longer silently ignores an invalid config (other load failures, including a missing config, are still tolerated). debug parse-project keeps its machine-readable JSON contract for an invalid config, emitting the diagnostics with a null payload, and preserves its non-zero exit code for any other load failure. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The trigger fixture config derives its logicalId from EXECUTION_ID, and runCheckly runs with extendEnv: false, so invocations that omit the variable load a config with no logicalId. Trigger aborts on an invalid config, so every invocation must pass the variable, not just the deploy/destroy setup steps. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…gnostic [RED-914] The runner.registries and bundle.packages.prune validators used to stop at their first problem, so a config with several mistakes inside one of those blocks surfaced them one edit-run cycle at a time. Both validators now walk the whole value, reporting each issue through a callback that the config loader turns into an individual diagnostic; the throwing entry points the bundler uses keep their contract by rethrowing the first issue. Cascading noise is gated rather than reported: an invalid or empty upstreams block skips the per-rule upstream-existence checks, an invalid final pattern skips the match-all requirement, and a match-all rule that merely sits in the wrong place is not additionally reported as missing. Pattern issues from the per-class prune map are prefixed with the dependency class so the same bad pattern in two classes stays distinguishable. Validation messages that feed diagnostics Reason: lines now end with terminal punctuation; this also touches the embedded-package spec errors and dependency cache version errors shared with other code paths. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Linear: RED-914
Affected Components
loadChecklyConfig()used to validate the config with four throw-based, fail-fast validators: a broken config reported only the first problem, as a rawErrorrendered by oclif's default handler — unlike construct validation, which collects everything into theDiagnosticssystem and renders it nicely.This converts config validation to diagnostics, in three commits:
ConfigFileDiagnosticscollector, so all config problems are reported in one run (both required fields, every badbundle.packages.embedspec, every unknownrunnerkey). Each diagnostic is attributed to the config file (e.g.[checkly.config.ts] Invalid property value;<generated config>when the config was synthesized in memory). When any diagnostic is fatal, loading fails with a newInvalidConfigErrorcarrying the diagnostics; otherwise the collector is returned alongside the config.CommandStyle.diagnostics()is now the single severity-to-renderer dispatch,AuthCommand.validateProject()absorbs the validate/render/exit block that was duplicated across five commands, andBaseCommand.catch()rendersInvalidConfigErrordiagnostics and exits 1 — every command gets styled output for a fatally invalid config without per-command error handling.project.validate(), so config diagnostics always render before project/construct diagnostics; destroy, trigger and the other import commands render them right after loading. Today every config diagnostic is fatal (so the returned collector is always empty), making this the plumbing for future warning-level config diagnostics.Nested validators, too: the
runner.registriesandbundle.packages.prunevalidators used to stop at their first problem, so several mistakes inside one block still surfaced one edit-run cycle at a time. They now walk the whole value and report each issue through a callback the loader turns into its own diagnostic (the throwing entry points the bundler uses rethrow the first issue, keeping their contract). Cascading noise is gated — an invalid/emptyupstreamsblock skips the per-rule existence checks, an invalid final pattern skips the match-all requirement, and a misplaced match-all isn't additionally reported as missing. Per-class prune pattern issues carry the dependency class so identical patterns in two classes stay distinguishable.Notes for the Reviewer
Intentional behavior changes:
Config field 'x' ...sentences to the diagnostics phrasing (Property "x" is required and must be set./The value provided for property "x" is not valid.+Reason: ...). The underlying cause strings are preserved verbatim in theReason:line.CommandStyle(matching how project diagnostics already render), instead of oclif's default stderr dump. Exit code stays 1.checkly triggernow fails on an invalid config it previously ignored silently. Deliberately narrow: onlyInvalidConfigErroris fatal — a missing config, an unloadable config (e.g. dependencies not installed in a trigger-only CI image), or any other load failure is still tolerated as before.checkly debug parse-projectkeeps its machine-readable contract: an invalid config emits the standardParseProjectOutputJSON shape with the diagnostics andpayload: nullat exit 0, while any other load failure (e.g. missing config) still exits non-zero.ParseProjectOutput.payloadis now typed| nullto match the actual contract.Regression coverage added: loader specs with multi-error fixtures,
CommandStyle.diagnostics+BaseCommand.catchunit specs, a deploy-level spec asserting config diagnostics render before project diagnostics, a trigger spec pinning which load failures are tolerated, and two sandbox tests running the real packed CLI throughdebug parse-projectfor the invalid-config and missing-config exit-code contracts.Other changes
EXECUTION_IDto everycheckly triggerinvocation (previously only the deploy/destroy setup steps did). The fixture config derives itslogicalIdfrom that variable, so the trigger runs used to load an invalid config that the old behavior silently ignored — with this PR the invalid config aborts the command, which is what failed CI.🤖 Generated with Claude Code