Skip to content

feat(cli): gRPC/SSL/Traceroute typed result rendering + IaC constructs#1362

Open
danielpaulus wants to merge 3 commits into
mainfrom
feat/cli-pertype-result-rendering
Open

feat(cli): gRPC/SSL/Traceroute typed result rendering + IaC constructs#1362
danielpaulus wants to merge 3 commits into
mainfrom
feat/cli-pertype-result-rendering

Conversation

@danielpaulus

@danielpaulus danielpaulus commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Summary

This branch now covers two related pieces of CLI support for the new uptime monitor types (gRPC, SSL, Traceroute):

1. Typed result/report rendering (original scope)

  • Renders typed result output for gRPC, SSL, and traceroute checks in CLI reporters.
  • Adds per-type output formatting and tests for the new diagnostics payloads.

2. IaC constructs (added)

Implements the missing checkly/constructs classes so users can author and deploy the new monitor types, and so backend CLI export templates that import { GrpcMonitor, SslMonitor, TracerouteMonitor } from 'checkly/constructs' compile.

  • GrpcMonitor (grpc-monitor.ts, grpc-request.ts, grpc-assertion.ts + codegen) — checkType: 'GRPC', top-level degradedResponseTime/maxResponseTime (≤30000). Request mirrors the public API: url, port, ipFamily, skipSSL, timeout, grpcConfig { mode, tls, storeResponseBody, serviceDefinition, method, protoContent, message, service, metadata }, assertions. GrpcAssertionBuilder: responseTime, statusCode, healthCheckStatus, responseMessage, responseMetadata.
  • SslMonitor (ssl-monitor.ts, ssl-request.ts, ssl-assertion.ts + codegen) — checkType: 'SSL'. Response-time limits live inside sslConfig (degradedResponseTimeMs/maxResponseTimeMs), not at the top level. Models serverName, skipChainValidation, handshakeTimeoutMs, alertDaysBeforeExpiry, securityBaseline, clientCertificateMode + sslClientCertificateId. SslAssertionBuilder covers cert expiry/trust/hostname/TLS version/cipher/key size/etc.
  • TracerouteMonitor (traceroute-monitor.ts, traceroute-request.ts, traceroute-assertion.ts + codegen) — checkType: 'TRACEROUTE', top-level degradedResponseTime/maxResponseTime (≤30000). Request: url, protocol, port, ipFamily, maxHops, maxUnknownHops, ptrLookup, timeout, assertions. port is dropped from generated code for ICMP probes (matches the backend strip). TracerouteAssertionBuilder: responseTime, hopCount, packetLoss.

Wiring:

  • Exports added to constructs/index.ts.
  • Import/codegen wired in constructs/check-codegen.ts (GRPC → GrpcMonitorCodegen, SSL → SslMonitorCodegen, TRACEROUTE → TracerouteMonitorCodegen).
  • GRPC/SSL/TRACEROUTE added to constants.CheckTypes.

Request shapes were verified against checkly-go-sdk types and the terraform-provider resource schemas, and the synthesized payloads are byte-identical to the previously parity-validated create bodies.

3. Deploy fix for uptime-only projects (T65)

  • Adds Bundler.isEmpty and skips the archive.store() / "Uploading Playwright tests" step when no files were registered for bundling.
  • This prevents uptime-only GRPC/SSL/TRACEROUTE deploys from uploading an empty code bundle to /next/checkly-storage/upload-code-bundle.
  • Playwright/browser projects still use the upload path when files are registered.

Feature flags for the backend: GRPC_CHECKS, SSL_CHECKS, TRACEROUTE_CHECKS.

AI-context reference pages (configure-*-monitors.md) were intentionally not added: they are optional, not in the acceptance criteria, and adding partial pages would risk the skills/checkly/SKILL.md sync CI check. Running prepare:ai-context produced no drift in the published skill.

Testing

  • T65 local UAT: real npx checkly deploy against local devenv through the dev-auth proxy created one GRPC, one SSL, and one TRACEROUTE check without CHECKLY_SKIP_AUTH; the uptime-only project skipped "Uploading Playwright tests"; checks were readable via the public API and cleaned up.
  • tsc --noEmit and tsc --build: clean.
  • eslint on all new/changed files: clean.
  • New unit tests (all green):
    • constructs/__tests__/grpc-monitor.spec.ts, ssl-monitor.spec.ts, traceroute-monitor.spec.ts — synthesize / validation / grouping.
    • constructs/__tests__/uptime-monitor-codegen.spec.ts — codegen emits compiling construct code (incl. ICMP port strip, assertion builders).
    • constructs/__tests__/uptime-monitor-export-snippets.spec.ts — backend-style export snippets compile against checkly/constructs and synthesize the expected payload.
  • Deploy validation against the local devenv (flags enabled): see PR comment for full evidence.

…I-RESULTS)

Render failure-debug diagnostics for the three uptime monitor types across
every CLI result surface, mirroring the 4.1 public check-results fields:

- rest/check-results.ts: typed TracerouteCheckResult/GrpcCheckResult/
  SslCheckResult interfaces + additive fields on CheckResult/CheckResultField.
- formatters/check-result-detail.ts: per-type terminal + markdown diagnostic
  block (checks results get) keyed on the typed fields.
- reporters/util.ts: GRPC/SSL/TRACEROUTE branches in formatCheckResult
  (checkly test terminal), sourced from the runner artifact (checkRunData).
- formatters/batch-stats.ts: add the three types to TIMING_TYPES.
- reporters/json.ts: emit a per-type diagnostics object in the JSON report
  for a failed run (checkly test --reporter json).

Snapshot + assertion tests for each type across all three surfaces.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@danielpaulus danielpaulus force-pushed the feat/cli-pertype-result-rendering branch from 37e7d34 to 1f8b58d Compare June 26, 2026 13:18
@danielpaulus

Copy link
Copy Markdown
Contributor Author

Follow-up scope identified after opening this PR: the current branch adds typed result/report rendering, but CLI IaC is not complete until the new monitor constructs exist.

A remote implementation run has been kicked off to add:

  • GrpcMonitor, SslMonitor, TracerouteMonitor exports from checkly/constructs
  • request/config/assertion helpers as needed
  • check import/codegen support
  • focused construct/codegen/import tests
  • validation that npx checkly deploy creates one GRPC, one SSL, and one TRACEROUTE check

Current context for that work:

  • branch has been rebased on latest main
  • backend/API/UI support has merged
  • feature flags: GRPC_CHECKS, SSL_CHECKS, TRACEROUTE_CHECKS

Tracking ticket lives in the spec branch at specs/CLI_CONSTRUCTS_TICKET.md.

…constructs

Implement the missing CLI constructs so users can author and deploy gRPC, SSL
and Traceroute uptime monitors via checkly/constructs, and so backend CLI export
templates that import these classes compile.

Constructs follow the DNS/TCP/ICMP monitor pattern (extend Monitor, register
with Session, validate, synthesize):

- GrpcMonitor / GrpcRequest / GrpcConfig / GrpcMetadata + GrpcAssertionBuilder
  (RESPONSE_TIME, GRPC_STATUS_CODE, GRPC_HEALTHCHECK_STATUS, GRPC_RESPONSE,
  GRPC_METADATA). checkType GRPC, top-level degraded/maxResponseTime (<=30000).
- SslMonitor / SslRequest / SslConfig / SecurityBaseline + SslAssertionBuilder
  (cert expiry, chain, hostname, TLS version, cipher, key size, etc). checkType
  SSL; response-time limits live in sslConfig (degraded/maxResponseTimeMs).
- TracerouteMonitor / TracerouteRequest + TracerouteAssertionBuilder
  (RESPONSE_TIME, HOP_COUNT, PACKET_LOSS). checkType TRACEROUTE, top-level
  degraded/maxResponseTime (<=30000); port dropped for ICMP probes.

Request shapes mirror the public API (verified against checkly-go-sdk types and
the p5-parity captured payloads). Wires exports in constructs/index.ts, import
codegen in check-codegen.ts (GRPC/SSL/TRACEROUTE -> *MonitorCodegen), and adds
the three types to constants.CheckTypes.

Tests: construct synthesize/validation/grouping specs, codegen specs (incl.
ICMP port-strip and assertion builders), and a regression spec asserting the
backend-style export snippets compile against checkly/constructs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@danielpaulus danielpaulus changed the title feat(reporters): render typed check result output feat(cli): gRPC/SSL/Traceroute typed result rendering + IaC constructs Jun 26, 2026
@danielpaulus

Copy link
Copy Markdown
Contributor Author

Deploy validation evidence (local devenv, flags enabled)

Target: local devenv backend (localhost:3000) in dev-auth mode, reached through the p5-parity dev-auth reverse proxy (localhost:3010) which injects the devenv auth envelope. GRPC_CHECKS / SSL_CHECKS / TRACEROUTE_CHECKS are enabled for the account (creates returned 201, not 403).

What fully passed via the real CLI

A fixture project with one GrpcMonitor, one SslMonitor and one TracerouteMonitor (import ... from 'checkly/constructs') was run through the repo CLI (bin/run deploy):

Parsing your project... ✅
Validating project resources... ✅
Bundling project resources... ✅
Uploading Playwright tests... ❌  (see blocker below)

Parse → validate → bundle of all three new constructs succeeds against the real backend.

Known blocker for end-to-end checkly deploy in this devenv

deploy unconditionally uploads a project code bundle (commands/deploy.tsarchive.store()POST /next/checkly-storage/upload-code-bundle) before creating checks, even for a project containing only uptime monitors (which carry no code). That storage endpoint is not available in this local devenv:

POST /next/checkly-storage/upload-code-bundle -> 502 (proxy: socket hang up to backend storage dep)

This is an infrastructure limitation of the local devenv storage service and is independent of the new constructs (it fails identically for any project).

Check creation proven against the real per-type API

Because the construct's synthesize() output is byte-identical to the parity-validated terraform create bodies, the synthesized payloads were POSTed to the real backend per-type endpoints (same auth path the CLI uses) to confirm the backend accepts the schema and creates checks. Full lifecycle, then cleaned up (shared account):

type POST id GET DELETE GET after delete
GRPC 201 3181f60a-4640-461a-92d3-efad5a3d43a1 200 204 404
SSL 201 afbf4313-5dbf-4d70-9f35-bc09ec3a6466 200 204 404
TRACEROUTE 201 1f11f58d-f797-45bb-9e33-e37ee7ca2ccc 200 204 404

All three created checks were deleted afterwards (confirmed 404). Created checkType values matched GRPC/SSL/TRACEROUTE.

Payload parity

GrpcMonitor/SslMonitor/TracerouteMonitor .synthesize() output is byte-identical to the previously parity-validated create bodies (request block diff = empty for all three types).

Net: constructs parse/validate/bundle through the real CLI and the backend creates checks from their exact payloads. The only gap to a single npx checkly deploy run is the devenv's unavailable code-bundle storage endpoint, not the construct code.

@danielpaulus

Copy link
Copy Markdown
Contributor Author

Addendum: re-ran the CLI validation without CHECKLY_SKIP_AUTH.

Using CHECKLY_ENV=local, CHECKLY_API_URL=http://localhost:3010, CHECKLY_ACCOUNT_ID=<local account id>, and a dummy API key through the dev-auth proxy:

checkly whoami
You are currently on account "dude@dude.com" (...) as undefined.
Plan: Enterprise

Then checkly deploy --preview again passed parse/validate/bundle and failed at the same storage upload step:

Parsing your project... ✅
Validating project resources... ✅
Bundling project resources... ✅
Uploading Playwright tests... ❌
ServerError: An internal server error occurred
Caused by: AxiosError: Request failed with status code 500

So CHECKLY_SKIP_AUTH was not the cause. Auth works against the local account path; the remaining blocker is still the devenv /next/checkly-storage/upload-code-bundle path.

archive.store() (the 'Uploading Playwright tests' step) was called
unconditionally on every deploy. For a project of only uptime monitors
(GRPC/SSL/TRACEROUTE), the bundler registers no files, so this uploaded an
empty Playwright bundle — an unnecessary code-bundle upload in production, and
a hard failure in devenv where it 500s on the storage backend.

The remote code bundle is consumed only by Playwright check suites (via
bundler.marker -> playwright-check.ts); browser checks upload snapshots
separately. Add Bundler.isEmpty and skip store() when no files were registered.

Refs T65.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@danielpaulus

Copy link
Copy Markdown
Contributor Author

T65: local CLI deploy of GRPC/SSL/TRACEROUTE uptime monitors

Pushed ea5e677fix(deploy): skip code-bundle upload when nothing was bundled.

Problem: npx checkly deploy of a project containing only GRPC/SSL/TRACEROUTE uptime monitors failed at Uploading Playwright testsarchive.store() (POST /next/checkly-storage/upload-code-bundle) was called unconditionally even though no files were bundled. In devenv the storage backend 500s; in prod it's a wasted upload on every uptime-only deploy.

Fix (this PR): add Bundler.isEmpty and gate archive.store() on it. The remote code bundle is consumed only by Playwright check suites (bundler.markerplaywright-check.ts); browser checks upload snapshots separately, so skipping an empty bundle is safe.

Companion backend fix (checkly monorepo): the project-deploy path also silently dropped the type-specific config (grpcConfig/sslConfig) because checkly-cli-schema's checkRequestSchema had no SSL/TRACEROUTE branch and mapCheckResourcesToDatabaseObject never built the grpc_check_configs/ssl_check_configs nodes. Fixed there to mirror the direct /v1/checks/* create path.

Verified end-to-end against devenv (real npx checkly deploy, dev-auth proxy, account dude@dude.com, flags GRPC_CHECKS/SSL_CHECKS/TRACEROUTE_CHECKS):

  • deploy succeeds, Uploading Playwright tests step correctly skipped;
  • one GRPC + one SSL + one TRACEROUTE check created;
  • each GET /v1/checks/{id} returns 200 with full config (grpcConfig / sslConfig / traceroute fields); GET /v1/checks lists all three;
  • re-deploy is idempotent (no duplicate config rows);
  • CLI bundler unit tests green; Bundler.isEmpty gating confirmed (empty→skip, files registered→upload).

Created checks cleaned up after verification.

@danielpaulus

Copy link
Copy Markdown
Contributor Author

T65 update: CLI PR now includes the deploy fix for uptime-only projects.

New commit: ea5e677664eb671c29075e5d99a187f1cd1133bd

What changed:

  • Added Bundler.isEmpty.
  • deploy now skips archive.store() / "Uploading Playwright tests" when no files were registered for bundling.
  • This avoids uploading an empty code bundle for GRPC/SSL/TRACEROUTE-only projects.
  • Playwright/browser projects still take the upload path when files are registered.

UAT from hub ticket T65:

  • Real npx checkly deploy, no CHECKLY_SKIP_AUTH, through local dev-auth proxy :3010.
  • GRPC+SSL+TRACEROUTE-only project deployed successfully and skipped "Uploading Playwright tests".
  • Created checks were readable through public API and cleaned up.
  • CLI CI is green on this PR head.

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