Skip to content

feat(sm): Update check test subcommand to target existing checks - #1706

Merged
Pokom merged 2 commits into
mainfrom
feat/sm-test-existing-checks
Oct 30, 2026
Merged

Pokom merged 2 commits into
mainfrom
feat/sm-test-existing-checks

Conversation

@Pokom

@Pokom Pokom commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

Adds the ability to pass in a check name to execute a test against. Previously, it was impossibly to test an existing check without gathering the full spec and rewriting it.

What

Why

How it was tested

PR checklist

  • I have reviewed the changes and verified the intended behavior.
  • I have added or updated tests and documentation where needed.
  • I have run GCX_AGENT_MODE=false mise run all and verified that it passes.
  • I have linked the accepted issue and RFC where required.
  • I have signed my commits.

@Pokom
Pokom requested review from a team as code owners October 29, 2026 18:25
@Pokom
Pokom requested a review from gerboland October 29, 2026 18:25
Adds the ability to pass in a check name to execute a test against.
Previously, it was impossibly to test an existing check without
gathering the full spec and rewriting it.
@Pokom
Pokom requested review from The-9880, dgzlopes and mem October 29, 2026 18:25

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intent. gcx synthetic-monitoring checks test could only run a manifest, so testing a saved check meant exporting its full spec first. The change adds an optional NAME positional that loads the saved check through the same TypedCRUD path checks get uses, and makes NAME and --filename mutually exclusive.

Blocking. One finding: the two new usage errors in testOpts.Validate exit 1, while docs/design/exit-codes.md assigns exit 2 to bad positional arguments and missing required flags. The same command already exits 2 when two names are given, so one class of mistake now reports two codes.

Other findings. loadTestSpec repeats the name check and lookup that checks get performs, and fetches the probe list a second time on the NAME path. Nit only.

Fix summary. Wrap both testOpts.Validate errors in fail.NewCommandUsageError. Optionally factor the shared check lookup out of loadTestSpec and checks get.

Assessment. The approach is a good fit: it reuses the existing resource path rather than adding a second one, and the test coverage (slug name, numeric ID, unknown check, name without an ID, stale probe ID, and both source argument errors) is proportionate to a 35 line production change. The exit code finding is the only thing worth fixing before merge; everything else is optional.

Comments below are prefixed required (1) and nit (1). required means fix before merge; nit means take it or leave it.

Comment @claude review for a fresh review.

func (o *testOpts) Validate() error {
if o.File == "" {
return errors.New("--filename/-f is required")
func (o *testOpts) Validate(args []string) error {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

required — Both new branches return a plain errors.New, which no converter in cmd/gcx/fail/convert.go recognises, so the command exits 1. docs/design/exit-codes.md assigns exit 2 to bad positional arguments and missing required flags, and cobra.MaximumNArgs(1) on this same command already exits 2 when two names are given, so one class of mistake now reports two codes. fail.NewCommandUsageError(cmd, msg, nil) fixes it, as it does for the same -f is required case at internal/providers/alert/time_intervals_commands.go:146; it needs cmd in scope, so either move the check into RunE or pass the command in. If synth deliberately keeps exit 1 across the provider (status.go:333 returns a plain error for its own mutually exclusive flags), say so and I will drop this.

// loadTestSpec returns the check to run: the manifest in --filename, or the
// saved check named by args[0] (a resource name or numeric ID). Validate has
// already ensured exactly one of the two is set.
func loadTestSpec(ctx context.Context, loader smcfg.Loader, file string, args []string) (*CheckSpec, error) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit — loadTestSpec repeats the lookup checks get performs at commands.go:233-245, down to a byte identical error string, and on the NAME path the probe list is fetched twice: FetchProbeInfo fetches it at the top of RunE, then NewTypedCRUD's GetFn fetches it again to turn the saved check's probe IDs into names, which resolveProbeIDs immediately turns back into IDs. A shared helper that returns a *checkResource for a name would give both commands one place to change. Separately, the function takes args []string and indexes args[0] under an invariant established in Validate; taking name string would keep that contract local. Staying symmetric with checks get is a fair reason to leave all of this as it is.

@radiohead radiohead left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Adding NAME is backward compatible with the -f usage. It only reads the saved check, rejects stale probes before running, and the tests cover the source and usage-error matrix well.

Nits:

  • The checks test hint in internal/agent/command_annotations.go (L681) still says only -f <check.yaml>. Consider <name> | -f <check.yaml> so agents find the saved-check form.
  • The NAME path fetches probes and the SM proxy config twice (FetchProbeInfo plus NewTypedCRUD). Minor, fine to leave.

Generated by Claude Code

@Pokom
Pokom merged commit 5bc2d2d into main Oct 30, 2026
23 checks passed
@Pokom
Pokom deleted the feat/sm-test-existing-checks branch October 30, 2026 10:08
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.

2 participants