checkly 9.5.0 → 10.0.0-prerelease-4f88d60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -0
- package/bin/launch.cjs +12 -0
- package/dist/ai-context/context.js +1 -0
- package/dist/ai-context/context.js.map +1 -1
- package/dist/ai-context/onboarding-boilerplate/checkly-config-template.ts +2 -2
- package/dist/ai-context/public-skills/checkly/SKILL.md +34 -5
- package/dist/ai-context/skills-command/references/communicate.md +8 -5
- package/dist/ai-context/skills-command/references/configure-api-checks.md +1 -9
- package/dist/ai-context/skills-command/references/configure-browser-checks.md +1 -8
- package/dist/ai-context/skills-command/references/configure-check-groups.md +1 -0
- package/dist/ai-context/skills-command/references/configure-dns-monitors.md +1 -9
- package/dist/ai-context/skills-command/references/configure-grpc-monitors.md +24 -0
- package/dist/ai-context/skills-command/references/configure-heartbeat-monitors.md +1 -9
- package/dist/ai-context/skills-command/references/configure-icmp-monitors.md +1 -9
- package/dist/ai-context/skills-command/references/configure-multistep-checks.md +1 -9
- package/dist/ai-context/skills-command/references/configure-playwright-checks.md +2 -2
- package/dist/ai-context/skills-command/references/configure-supporting-constructs.md +6 -2
- package/dist/ai-context/skills-command/references/configure-tcp-monitors.md +1 -10
- package/dist/ai-context/skills-command/references/configure-url-monitors.md +1 -10
- package/dist/ai-context/skills-command/references/configure.md +17 -5
- package/dist/ai-context/skills-command/references/initialize.md +11 -3
- package/dist/ai-context/skills-command/references/investigate-checks.md +1 -1
- package/dist/auth/api-key.d.ts +24 -0
- package/dist/auth/api-key.js +104 -0
- package/dist/auth/api-key.js.map +1 -0
- package/dist/auth/device-flow.d.ts +58 -0
- package/dist/auth/device-flow.js +228 -0
- package/dist/auth/device-flow.js.map +1 -0
- package/dist/auth/index.d.ts +6 -6
- package/dist/auth/index.js +64 -64
- package/dist/auth/index.js.map +1 -1
- package/dist/commands/account/plan.js +1 -1
- package/dist/commands/account/plan.js.map +1 -1
- package/dist/commands/account/usage/projections.d.ts +16 -0
- package/dist/commands/account/usage/projections.js +40 -0
- package/dist/commands/account/usage/projections.js.map +1 -0
- package/dist/commands/account/usage/series.d.ts +7 -3
- package/dist/commands/account/usage/series.js +30 -87
- package/dist/commands/account/usage/series.js.map +1 -1
- package/dist/commands/account/usage/summary.d.ts +4 -1
- package/dist/commands/account/usage/summary.js +19 -27
- package/dist/commands/account/usage/summary.js.map +1 -1
- package/dist/commands/account/usage/term.d.ts +15 -0
- package/dist/commands/account/usage/term.js +32 -0
- package/dist/commands/account/usage/term.js.map +1 -0
- package/dist/commands/account/usage/terms.d.ts +4 -0
- package/dist/commands/account/usage/terms.js +19 -27
- package/dist/commands/account/usage/terms.js.map +1 -1
- package/dist/commands/alert-channels/get.js +2 -1
- package/dist/commands/alert-channels/get.js.map +1 -1
- package/dist/commands/alert-channels/list.js +2 -1
- package/dist/commands/alert-channels/list.js.map +1 -1
- package/dist/commands/alert-channels/logs.js +2 -1
- package/dist/commands/alert-channels/logs.js.map +1 -1
- package/dist/commands/api.js +53 -10
- package/dist/commands/api.js.map +1 -1
- package/dist/commands/assets/download.js +11 -7
- package/dist/commands/assets/download.js.map +1 -1
- package/dist/commands/assets/list.js +2 -3
- package/dist/commands/assets/list.js.map +1 -1
- package/dist/commands/authCommand.d.ts +19 -0
- package/dist/commands/authCommand.js +118 -12
- package/dist/commands/authCommand.js.map +1 -1
- package/dist/commands/baseCommand.d.ts +12 -1
- package/dist/commands/baseCommand.js +24 -5
- package/dist/commands/baseCommand.js.map +1 -1
- package/dist/commands/checks/delete.js +1 -1
- package/dist/commands/checks/delete.js.map +1 -1
- package/dist/commands/checks/run.js +3 -1
- package/dist/commands/checks/run.js.map +1 -1
- package/dist/commands/debug/parse-project.d.ts +1 -0
- package/dist/commands/debug/parse-project.js +5 -2
- package/dist/commands/debug/parse-project.js.map +1 -1
- package/dist/commands/deploy.d.ts +8 -2
- package/dist/commands/deploy.js +735 -274
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/destroy.js +3 -3
- package/dist/commands/destroy.js.map +1 -1
- package/dist/commands/env/add.js +2 -2
- package/dist/commands/env/add.js.map +1 -1
- package/dist/commands/env/ls.js +2 -1
- package/dist/commands/env/ls.js.map +1 -1
- package/dist/commands/env/pull.js +3 -3
- package/dist/commands/env/pull.js.map +1 -1
- package/dist/commands/env/update.js +2 -2
- package/dist/commands/env/update.js.map +1 -1
- package/dist/commands/import/apply.js +12 -10
- package/dist/commands/import/apply.js.map +1 -1
- package/dist/commands/import/cancel.js +4 -4
- package/dist/commands/import/cancel.js.map +1 -1
- package/dist/commands/import/commit.js +11 -9
- package/dist/commands/import/commit.js.map +1 -1
- package/dist/commands/import/plan.js +82 -62
- package/dist/commands/import/plan.js.map +1 -1
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.js +62 -41
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/login.d.ts +38 -2
- package/dist/commands/login.js +848 -52
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.js +10 -4
- package/dist/commands/logout.js.map +1 -1
- package/dist/commands/pw-test.js +6 -3
- package/dist/commands/pw-test.js.map +1 -1
- package/dist/commands/rca/get.js +1 -1
- package/dist/commands/rca/get.js.map +1 -1
- package/dist/commands/rca/run.js +1 -1
- package/dist/commands/rca/run.js.map +1 -1
- package/dist/commands/skills/index.js +1 -1
- package/dist/commands/skills/index.js.map +1 -1
- package/dist/commands/skills/install.js +12 -12
- package/dist/commands/skills/install.js.map +1 -1
- package/dist/commands/switch.d.ts +10 -1
- package/dist/commands/switch.js +75 -13
- package/dist/commands/switch.js.map +1 -1
- package/dist/commands/sync-playwright.js +5 -10
- package/dist/commands/sync-playwright.js.map +1 -1
- package/dist/commands/test.d.ts +2 -0
- package/dist/commands/test.js +58 -29
- package/dist/commands/test.js.map +1 -1
- package/dist/commands/trigger.d.ts +1 -2
- package/dist/commands/trigger.js +27 -20
- package/dist/commands/trigger.js.map +1 -1
- package/dist/commands/validate.js +1 -0
- package/dist/commands/validate.js.map +1 -1
- package/dist/commands/whoami.d.ts +8 -0
- package/dist/commands/whoami.js +57 -6
- package/dist/commands/whoami.js.map +1 -1
- package/dist/constants.d.ts +3 -2
- package/dist/constants.js +8 -1
- package/dist/constants.js.map +1 -1
- package/dist/constructs/alert-channel-codegen.d.ts +6 -1
- package/dist/constructs/alert-channel-codegen.js +12 -6
- package/dist/constructs/alert-channel-codegen.js.map +1 -1
- package/dist/constructs/alert-channel-subscription.d.ts +1 -0
- package/dist/constructs/alert-channel-subscription.js +4 -0
- package/dist/constructs/alert-channel-subscription.js.map +1 -1
- package/dist/constructs/alert-channel.js +8 -5
- package/dist/constructs/alert-channel.js.map +1 -1
- package/dist/constructs/alert-escalation-policy-codegen.d.ts +7 -0
- package/dist/constructs/alert-escalation-policy-codegen.js +25 -8
- package/dist/constructs/alert-escalation-policy-codegen.js.map +1 -1
- package/dist/constructs/api-assertion.d.ts +0 -2
- package/dist/constructs/api-assertion.js +0 -4
- package/dist/constructs/api-assertion.js.map +1 -1
- package/dist/constructs/api-check-bundle.d.ts +4 -124
- package/dist/constructs/api-check-codegen.js +1 -1
- package/dist/constructs/api-check-codegen.js.map +1 -1
- package/dist/constructs/api-check.d.ts +8 -128
- package/dist/constructs/api-check.js +15 -17
- package/dist/constructs/api-check.js.map +1 -1
- package/dist/constructs/api-request-codegen.js +10 -8
- package/dist/constructs/api-request-codegen.js.map +1 -1
- package/dist/constructs/browser-check-bundle.d.ts +11 -125
- package/dist/constructs/browser-check-bundle.js +5 -1
- package/dist/constructs/browser-check-bundle.js.map +1 -1
- package/dist/constructs/browser-check.d.ts +5 -107
- package/dist/constructs/browser-check.js +1 -1
- package/dist/constructs/browser-check.js.map +1 -1
- package/dist/constructs/check-codegen.d.ts +46 -14
- package/dist/constructs/check-codegen.js +118 -34
- package/dist/constructs/check-codegen.js.map +1 -1
- package/dist/constructs/check-group-codegen.js +23 -9
- package/dist/constructs/check-group-codegen.js.map +1 -1
- package/dist/constructs/check-group-v1.d.ts +28 -16
- package/dist/constructs/check-group-v1.js +48 -17
- package/dist/constructs/check-group-v1.js.map +1 -1
- package/dist/constructs/check-group-v2.d.ts +2 -21
- package/dist/constructs/check-group-v2.js +4 -4
- package/dist/constructs/check-group-v2.js.map +1 -1
- package/dist/constructs/check.d.ts +68 -220
- package/dist/constructs/check.js +106 -37
- package/dist/constructs/check.js.map +1 -1
- package/dist/constructs/construct-codegen.d.ts +1 -2
- package/dist/constructs/construct-diagnostics.d.ts +3 -0
- package/dist/constructs/construct-diagnostics.js +11 -0
- package/dist/constructs/construct-diagnostics.js.map +1 -1
- package/dist/constructs/construct.d.ts +30 -4
- package/dist/constructs/construct.js +52 -6
- package/dist/constructs/construct.js.map +1 -1
- package/dist/constructs/dashboard.js +11 -7
- package/dist/constructs/dashboard.js.map +1 -1
- package/dist/constructs/dns-monitor.d.ts +4 -100
- package/dist/constructs/dns-request-codegen.js +1 -1
- package/dist/constructs/dns-request-codegen.js.map +1 -1
- package/dist/constructs/email-alert-channel-codegen.js +1 -1
- package/dist/constructs/email-alert-channel-codegen.js.map +1 -1
- package/dist/constructs/engine.d.ts +4 -2
- package/dist/constructs/engine.js +3 -1
- package/dist/constructs/engine.js.map +1 -1
- package/dist/constructs/frequency-codegen.js +10 -2
- package/dist/constructs/frequency-codegen.js.map +1 -1
- package/dist/constructs/frequency.d.ts +8 -3
- package/dist/constructs/frequency.js +7 -2
- package/dist/constructs/frequency.js.map +1 -1
- package/dist/constructs/grpc-monitor.d.ts +4 -100
- package/dist/constructs/grpc-monitor.js +19 -0
- package/dist/constructs/grpc-monitor.js.map +1 -1
- package/dist/constructs/grpc-request-codegen.js +13 -4
- package/dist/constructs/grpc-request-codegen.js.map +1 -1
- package/dist/constructs/grpc-request.d.ts +23 -0
- package/dist/constructs/heartbeat-monitor.d.ts +2 -1
- package/dist/constructs/heartbeat-monitor.js +2 -2
- package/dist/constructs/heartbeat-monitor.js.map +1 -1
- package/dist/constructs/icmp-monitor.d.ts +4 -100
- package/dist/constructs/icmp-request-codegen.js +1 -1
- package/dist/constructs/icmp-request-codegen.js.map +1 -1
- package/dist/constructs/incidentio-alert-channel-codegen.d.ts +1 -1
- package/dist/constructs/incidentio-alert-channel-codegen.js +14 -8
- package/dist/constructs/incidentio-alert-channel-codegen.js.map +1 -1
- package/dist/constructs/index.d.ts +1 -1
- package/dist/constructs/index.js +1 -1
- package/dist/constructs/index.js.map +1 -1
- package/dist/constructs/internal/assertion-validation.js +1 -2
- package/dist/constructs/internal/assertion-validation.js.map +1 -1
- package/dist/constructs/internal/codegen/context.d.ts +73 -6
- package/dist/constructs/internal/codegen/context.js +78 -6
- package/dist/constructs/internal/codegen/context.js.map +1 -1
- package/dist/constructs/internal/codegen/index.d.ts +3 -1
- package/dist/constructs/internal/codegen/index.js +2 -1
- package/dist/constructs/internal/codegen/index.js.map +1 -1
- package/dist/constructs/internal/codegen/render.d.ts +68 -0
- package/dist/constructs/internal/codegen/render.js +75 -0
- package/dist/constructs/internal/codegen/render.js.map +1 -0
- package/dist/constructs/internal/common-diagnostics.d.ts +1 -2
- package/dist/constructs/internal/common-diagnostics.js +7 -17
- package/dist/constructs/internal/common-diagnostics.js.map +1 -1
- package/dist/constructs/internal/declaring-file.d.ts +39 -0
- package/dist/constructs/internal/declaring-file.js +139 -0
- package/dist/constructs/internal/declaring-file.js.map +1 -0
- package/dist/constructs/internal/default-retry-strategy.d.ts +9 -0
- package/dist/constructs/internal/default-retry-strategy.js +13 -0
- package/dist/constructs/internal/default-retry-strategy.js.map +1 -0
- package/dist/constructs/internal/retry-strategy-defaults.d.ts +13 -0
- package/dist/constructs/internal/retry-strategy-defaults.js +14 -0
- package/dist/constructs/internal/retry-strategy-defaults.js.map +1 -0
- package/dist/constructs/key-value-pair-codegen.d.ts +6 -1
- package/dist/constructs/key-value-pair-codegen.js +24 -3
- package/dist/constructs/key-value-pair-codegen.js.map +1 -1
- package/dist/constructs/maintenance-window-codegen.d.ts +7 -0
- package/dist/constructs/maintenance-window-codegen.js +36 -19
- package/dist/constructs/maintenance-window-codegen.js.map +1 -1
- package/dist/constructs/maintenance-window.d.ts +37 -3
- package/dist/constructs/maintenance-window.js +34 -1
- package/dist/constructs/maintenance-window.js.map +1 -1
- package/dist/constructs/monitor.d.ts +6 -119
- package/dist/constructs/monitor.js +3 -5
- package/dist/constructs/monitor.js.map +1 -1
- package/dist/constructs/msteams-alert-channel-codegen.d.ts +1 -1
- package/dist/constructs/msteams-alert-channel-codegen.js +8 -18
- package/dist/constructs/msteams-alert-channel-codegen.js.map +1 -1
- package/dist/constructs/multi-step-check-bundle.d.ts +4 -109
- package/dist/constructs/multi-step-check.d.ts +4 -100
- package/dist/constructs/opsgenie-alert-channel-codegen.js +1 -1
- package/dist/constructs/opsgenie-alert-channel-codegen.js.map +1 -1
- package/dist/constructs/pagerduty-alert-channel-codegen.js +1 -1
- package/dist/constructs/pagerduty-alert-channel-codegen.js.map +1 -1
- package/dist/constructs/phone-call-alert-channel-codegen.js +1 -1
- package/dist/constructs/phone-call-alert-channel-codegen.js.map +1 -1
- package/dist/constructs/playwright-check-bundle.d.ts +10 -130
- package/dist/constructs/playwright-check-bundle.js +3 -3
- package/dist/constructs/playwright-check-bundle.js.map +1 -1
- package/dist/constructs/playwright-check-codegen.d.ts +85 -0
- package/dist/constructs/playwright-check-codegen.js +212 -0
- package/dist/constructs/playwright-check-codegen.js.map +1 -0
- package/dist/constructs/playwright-check.d.ts +14 -122
- package/dist/constructs/playwright-check.js +17 -51
- package/dist/constructs/playwright-check.js.map +1 -1
- package/dist/constructs/private-location-check-assignment.d.ts +1 -0
- package/dist/constructs/private-location-check-assignment.js +4 -0
- package/dist/constructs/private-location-check-assignment.js.map +1 -1
- package/dist/constructs/private-location-group-assignment.d.ts +1 -0
- package/dist/constructs/private-location-group-assignment.js +4 -0
- package/dist/constructs/private-location-group-assignment.js.map +1 -1
- package/dist/constructs/private-location.js +3 -1
- package/dist/constructs/private-location.js.map +1 -1
- package/dist/constructs/retry-strategy-codegen.d.ts +7 -1
- package/dist/constructs/retry-strategy-codegen.js +41 -32
- package/dist/constructs/retry-strategy-codegen.js.map +1 -1
- package/dist/constructs/retry-strategy.d.ts +0 -4
- package/dist/constructs/retry-strategy.js +5 -8
- package/dist/constructs/retry-strategy.js.map +1 -1
- package/dist/constructs/session.d.ts +38 -1
- package/dist/constructs/session.js +73 -3
- package/dist/constructs/session.js.map +1 -1
- package/dist/constructs/slack-alert-channel-codegen.js +1 -1
- package/dist/constructs/slack-alert-channel-codegen.js.map +1 -1
- package/dist/constructs/slack-app-alert-channel-codegen.js +1 -1
- package/dist/constructs/slack-app-alert-channel-codegen.js.map +1 -1
- package/dist/constructs/sms-alert-channel-codegen.js +1 -1
- package/dist/constructs/sms-alert-channel-codegen.js.map +1 -1
- package/dist/constructs/ssl-monitor.d.ts +4 -142
- package/dist/constructs/ssl-request-codegen.js +4 -3
- package/dist/constructs/ssl-request-codegen.js.map +1 -1
- package/dist/constructs/status-page-v3-automation-rule-codegen.js +5 -4
- package/dist/constructs/status-page-v3-automation-rule-codegen.js.map +1 -1
- package/dist/constructs/status-page-v3-codegen.js +3 -2
- package/dist/constructs/status-page-v3-codegen.js.map +1 -1
- package/dist/constructs/status-page-v3-component-codegen.js +8 -7
- package/dist/constructs/status-page-v3-component-codegen.js.map +1 -1
- package/dist/constructs/tcp-monitor-codegen.js +3 -2
- package/dist/constructs/tcp-monitor-codegen.js.map +1 -1
- package/dist/constructs/tcp-monitor.d.ts +8 -103
- package/dist/constructs/tcp-monitor.js +3 -2
- package/dist/constructs/tcp-monitor.js.map +1 -1
- package/dist/constructs/telegram-alert-channel-codegen.d.ts +1 -1
- package/dist/constructs/telegram-alert-channel-codegen.js +14 -8
- package/dist/constructs/telegram-alert-channel-codegen.js.map +1 -1
- package/dist/constructs/time-zone.d.ts +24 -0
- package/dist/constructs/time-zone.js +455 -0
- package/dist/constructs/time-zone.js.map +1 -0
- package/dist/constructs/traceroute-monitor.d.ts +4 -100
- package/dist/constructs/traceroute-request-codegen.js +2 -2
- package/dist/constructs/traceroute-request-codegen.js.map +1 -1
- package/dist/constructs/url-monitor-codegen.js +1 -1
- package/dist/constructs/url-monitor-codegen.js.map +1 -1
- package/dist/constructs/url-monitor.d.ts +7 -123
- package/dist/constructs/url-monitor.js +3 -0
- package/dist/constructs/url-monitor.js.map +1 -1
- package/dist/constructs/url-request-codegen.js +4 -3
- package/dist/constructs/url-request-codegen.js.map +1 -1
- package/dist/constructs/webhook-alert-channel-codegen.js +3 -3
- package/dist/constructs/webhook-alert-channel-codegen.js.map +1 -1
- package/dist/formatters/check-result-detail.js +0 -185
- package/dist/formatters/check-result-detail.js.map +1 -1
- package/dist/formatters/render.d.ts +2 -1
- package/dist/formatters/render.js +2 -2
- package/dist/formatters/render.js.map +1 -1
- package/dist/formatters/usage.d.ts +18 -12
- package/dist/formatters/usage.js +285 -245
- package/dist/formatters/usage.js.map +1 -1
- package/dist/help/help-extension.js +2 -1
- package/dist/help/help-extension.js.map +1 -1
- package/dist/helpers/accounts.d.ts +28 -0
- package/dist/helpers/accounts.js +50 -0
- package/dist/helpers/accounts.js.map +1 -0
- package/dist/helpers/activate-account.d.ts +13 -0
- package/dist/helpers/activate-account.js +24 -0
- package/dist/helpers/activate-account.js.map +1 -0
- package/dist/helpers/api-fields.js +3 -2
- package/dist/helpers/api-fields.js.map +1 -1
- package/dist/helpers/cli-mode.d.ts +24 -0
- package/dist/helpers/cli-mode.js +64 -8
- package/dist/helpers/cli-mode.js.map +1 -1
- package/dist/helpers/command-preview.d.ts +44 -0
- package/dist/helpers/command-preview.js +29 -9
- package/dist/helpers/command-preview.js.map +1 -1
- package/dist/helpers/command-style.d.ts +1 -0
- package/dist/helpers/command-style.js +51 -37
- package/dist/helpers/command-style.js.map +1 -1
- package/dist/helpers/flags.d.ts +10 -0
- package/dist/helpers/flags.js +18 -0
- package/dist/helpers/flags.js.map +1 -1
- package/dist/helpers/import-plan-selection.d.ts +1 -1
- package/dist/helpers/import-plan-selection.js +8 -20
- package/dist/helpers/import-plan-selection.js.map +1 -1
- package/dist/helpers/invalid-input-error.d.ts +15 -0
- package/dist/helpers/invalid-input-error.js +17 -0
- package/dist/helpers/invalid-input-error.js.map +1 -0
- package/dist/helpers/number.js +4 -3
- package/dist/helpers/number.js.map +1 -1
- package/dist/helpers/onboarding/boilerplate.js +15 -3
- package/dist/helpers/onboarding/boilerplate.js.map +1 -1
- package/dist/helpers/onboarding/index.d.ts +1 -1
- package/dist/helpers/onboarding/index.js +1 -1
- package/dist/helpers/onboarding/index.js.map +1 -1
- package/dist/helpers/onboarding/messages.d.ts +7 -0
- package/dist/helpers/onboarding/messages.js +14 -0
- package/dist/helpers/onboarding/messages.js.map +1 -1
- package/dist/helpers/onboarding/prompt-display.js +2 -2
- package/dist/helpers/onboarding/prompt-display.js.map +1 -1
- package/dist/helpers/onboarding/prompts-helpers.js +3 -1
- package/dist/helpers/onboarding/prompts-helpers.js.map +1 -1
- package/dist/helpers/onboarding/skill-install.js +4 -4
- package/dist/helpers/onboarding/skill-install.js.map +1 -1
- package/dist/helpers/prompts.d.ts +7 -0
- package/dist/helpers/prompts.js +10 -0
- package/dist/helpers/prompts.js.map +1 -0
- package/dist/helpers/result-assets.js +4 -3
- package/dist/helpers/result-assets.js.map +1 -1
- package/dist/helpers/test-helper.d.ts +14 -0
- package/dist/helpers/test-helper.js +33 -3
- package/dist/helpers/test-helper.js.map +1 -1
- package/dist/helpers/usage.d.ts +51 -14
- package/dist/helpers/usage.js +193 -53
- package/dist/helpers/usage.js.map +1 -1
- package/dist/helpers/wrap.js +1 -1
- package/dist/helpers/wrap.js.map +1 -1
- package/dist/messages/common-messages.d.ts +1 -0
- package/dist/messages/common-messages.js +4 -2
- package/dist/messages/common-messages.js.map +1 -1
- package/dist/reporters/abstract-list.d.ts +9 -2
- package/dist/reporters/abstract-list.js +105 -32
- package/dist/reporters/abstract-list.js.map +1 -1
- package/dist/reporters/ci.js +7 -4
- package/dist/reporters/ci.js.map +1 -1
- package/dist/reporters/dot.d.ts +1 -0
- package/dist/reporters/dot.js +19 -7
- package/dist/reporters/dot.js.map +1 -1
- package/dist/reporters/github.d.ts +2 -0
- package/dist/reporters/github.js +29 -4
- package/dist/reporters/github.js.map +1 -1
- package/dist/reporters/json.d.ts +2 -0
- package/dist/reporters/json.js +27 -4
- package/dist/reporters/json.js.map +1 -1
- package/dist/reporters/list.js +10 -8
- package/dist/reporters/list.js.map +1 -1
- package/dist/reporters/reporter.d.ts +1 -0
- package/dist/reporters/reporter.js.map +1 -1
- package/dist/reporters/util.d.ts +5 -2
- package/dist/reporters/util.js +25 -61
- package/dist/reporters/util.js.map +1 -1
- package/dist/rest/analytics.js +0 -4
- package/dist/rest/analytics.js.map +1 -1
- package/dist/rest/api.d.ts +10 -1
- package/dist/rest/api.js +44 -9
- package/dist/rest/api.js.map +1 -1
- package/dist/rest/check-results.d.ts +1 -50
- package/dist/rest/check-results.js.map +1 -1
- package/dist/rest/checkly-storage.d.ts +6 -1
- package/dist/rest/checkly-storage.js +13 -2
- package/dist/rest/checkly-storage.js.map +1 -1
- package/dist/rest/errors.d.ts +19 -0
- package/dist/rest/errors.js +20 -1
- package/dist/rest/errors.js.map +1 -1
- package/dist/rest/projects.d.ts +254 -4
- package/dist/rest/projects.js +208 -17
- package/dist/rest/projects.js.map +1 -1
- package/dist/rest/usage.d.ts +164 -73
- package/dist/rest/usage.js +21 -10
- package/dist/rest/usage.js.map +1 -1
- package/dist/services/abstract-check-runner.d.ts +34 -2
- package/dist/services/abstract-check-runner.js +183 -56
- package/dist/services/abstract-check-runner.js.map +1 -1
- package/dist/services/check-parser/bundler.d.ts +26 -0
- package/dist/services/check-parser/bundler.js +81 -7
- package/dist/services/check-parser/bundler.js.map +1 -1
- package/dist/services/check-parser/cache-hash.d.ts +1 -4
- package/dist/services/check-parser/cache-hash.js.map +1 -1
- package/dist/services/check-parser/package-files/json-text-source-file.d.ts +0 -2
- package/dist/services/check-parser/package-files/json-text-source-file.js +6 -6
- package/dist/services/check-parser/package-files/json-text-source-file.js.map +1 -1
- package/dist/services/check-parser/parser.d.ts +3 -2
- package/dist/services/check-parser/parser.js +31 -40
- package/dist/services/check-parser/parser.js.map +1 -1
- package/dist/services/checkly-config-codegen.js +4 -4
- package/dist/services/checkly-config-codegen.js.map +1 -1
- package/dist/services/checkly-config-loader.d.ts +18 -33
- package/dist/services/checkly-config-loader.js +50 -47
- package/dist/services/checkly-config-loader.js.map +1 -1
- package/dist/services/config.d.ts +42 -1
- package/dist/services/config.js +93 -9
- package/dist/services/config.js.map +1 -1
- package/dist/services/content-hash.d.ts +14 -0
- package/dist/services/content-hash.js +22 -0
- package/dist/services/content-hash.js.map +1 -0
- package/dist/services/deploy-diff/diff-lines.d.ts +52 -0
- package/dist/services/deploy-diff/diff-lines.js +327 -0
- package/dist/services/deploy-diff/diff-lines.js.map +1 -0
- package/dist/services/deploy-diff/double-check.d.ts +9 -0
- package/dist/services/deploy-diff/double-check.js +21 -0
- package/dist/services/deploy-diff/double-check.js.map +1 -0
- package/dist/services/deploy-diff/import-shape.d.ts +171 -0
- package/dist/services/deploy-diff/import-shape.js +633 -0
- package/dist/services/deploy-diff/import-shape.js.map +1 -0
- package/dist/services/deploy-diff/legacy-payload.d.ts +22 -0
- package/dist/services/deploy-diff/legacy-payload.js +51 -0
- package/dist/services/deploy-diff/legacy-payload.js.map +1 -0
- package/dist/services/deploy-diff/plan-summary.d.ts +81 -0
- package/dist/services/deploy-diff/plan-summary.js +262 -0
- package/dist/services/deploy-diff/plan-summary.js.map +1 -0
- package/dist/services/deploy-diff/preview-output.d.ts +63 -0
- package/dist/services/deploy-diff/preview-output.js +403 -0
- package/dist/services/deploy-diff/preview-output.js.map +1 -0
- package/dist/services/deploy-diff/render.d.ts +59 -0
- package/dist/services/deploy-diff/render.js +326 -0
- package/dist/services/deploy-diff/render.js.map +1 -0
- package/dist/services/deploy-diff/shape-changes.d.ts +2 -0
- package/dist/services/deploy-diff/shape-changes.js +48 -0
- package/dist/services/deploy-diff/shape-changes.js.map +1 -0
- package/dist/services/deploy-diff/source-index.d.ts +18 -0
- package/dist/services/deploy-diff/source-index.js +48 -0
- package/dist/services/deploy-diff/source-index.js.map +1 -0
- package/dist/services/deploy-diff/variable-names.d.ts +30 -0
- package/dist/services/deploy-diff/variable-names.js +64 -0
- package/dist/services/deploy-diff/variable-names.js.map +1 -0
- package/dist/services/engine-resolver.js +3 -0
- package/dist/services/engine-resolver.js.map +1 -1
- package/dist/services/engine-rules-loader.d.ts +6 -0
- package/dist/services/engine-rules-loader.js +12 -3
- package/dist/services/engine-rules-loader.js.map +1 -1
- package/dist/services/oxc-parser.d.ts +26 -0
- package/dist/services/oxc-parser.js +70 -0
- package/dist/services/oxc-parser.js.map +1 -0
- package/dist/services/project-cli.d.ts +75 -0
- package/dist/services/project-cli.js +302 -0
- package/dist/services/project-cli.js.map +1 -0
- package/dist/services/project-parser.d.ts +5 -0
- package/dist/services/project-parser.js +25 -13
- package/dist/services/project-parser.js.map +1 -1
- package/dist/services/skills.js +3 -3
- package/dist/services/skills.js.map +1 -1
- package/dist/services/snapshot-service.d.ts +25 -8
- package/dist/services/snapshot-service.js +46 -4
- package/dist/services/snapshot-service.js.map +1 -1
- package/dist/services/socket-client.js +1 -1
- package/dist/services/socket-client.js.map +1 -1
- package/dist/services/test-filters.d.ts +18 -0
- package/dist/services/test-filters.js +10 -0
- package/dist/services/test-filters.js.map +1 -1
- package/dist/services/test-runner.d.ts +1 -1
- package/dist/services/test-runner.js +10 -11
- package/dist/services/test-runner.js.map +1 -1
- package/dist/services/test-session-cancel.d.ts +5 -0
- package/dist/services/test-session-cancel.js +28 -3
- package/dist/services/test-session-cancel.js.map +1 -1
- package/dist/services/trigger-runner.d.ts +1 -1
- package/dist/services/trigger-runner.js +2 -2
- package/dist/services/trigger-runner.js.map +1 -1
- package/dist/services/two-installs.d.ts +39 -0
- package/dist/services/two-installs.js +155 -0
- package/dist/services/two-installs.js.map +1 -0
- package/dist/services/util.d.ts +17 -2
- package/dist/services/util.js +118 -11
- package/dist/services/util.js.map +1 -1
- package/dist/services/write-back/apply-edits.d.ts +29 -0
- package/dist/services/write-back/apply-edits.js +255 -0
- package/dist/services/write-back/apply-edits.js.map +1 -0
- package/dist/services/write-back/helper-edit.d.ts +135 -0
- package/dist/services/write-back/helper-edit.js +343 -0
- package/dist/services/write-back/helper-edit.js.map +1 -0
- package/dist/services/write-back/imports.d.ts +30 -0
- package/dist/services/write-back/imports.js +88 -0
- package/dist/services/write-back/imports.js.map +1 -0
- package/dist/services/write-back/literal-edit.d.ts +183 -0
- package/dist/services/write-back/literal-edit.js +359 -0
- package/dist/services/write-back/literal-edit.js.map +1 -0
- package/dist/services/write-back/output.d.ts +26 -0
- package/dist/services/write-back/output.js +110 -0
- package/dist/services/write-back/output.js.map +1 -0
- package/dist/services/write-back/plan.d.ts +180 -0
- package/dist/services/write-back/plan.js +1046 -0
- package/dist/services/write-back/plan.js.map +1 -0
- package/dist/services/write-back/source-file.d.ts +133 -0
- package/dist/services/write-back/source-file.js +460 -0
- package/dist/services/write-back/source-file.js.map +1 -0
- package/dist/sourcegen/index.d.ts +1 -1
- package/dist/sourcegen/index.js +1 -1
- package/dist/sourcegen/index.js.map +1 -1
- package/dist/sourcegen/program.d.ts +19 -1
- package/dist/sourcegen/program.js +32 -7
- package/dist/sourcegen/program.js.map +1 -1
- package/dist/testing/clear-git-env.d.ts +1 -0
- package/dist/testing/clear-git-env.js +25 -0
- package/dist/testing/clear-git-env.js.map +1 -0
- package/dist/testing/global-setup.d.ts +1 -0
- package/dist/testing/global-setup.js +3 -0
- package/dist/testing/global-setup.js.map +1 -1
- package/oclif.manifest.json +1113 -884
- package/package.json +21 -19
- package/dist/commands/rules.d.ts +0 -9
- package/dist/commands/rules.js +0 -13
- package/dist/commands/rules.js.map +0 -1
- package/dist/constructs/agentic-check-codegen.d.ts +0 -22
- package/dist/constructs/agentic-check-codegen.js +0 -59
- package/dist/constructs/agentic-check-codegen.js.map +0 -1
- package/dist/constructs/agentic-check.d.ts +0 -237
- package/dist/constructs/agentic-check.js +0 -100
- package/dist/constructs/agentic-check.js.map +0 -1
- package/dist/services/check-parser/package-files/json-text-source-file-parser.d.ts +0 -7
- package/dist/services/check-parser/package-files/json-text-source-file-parser.js +0 -47
- package/dist/services/check-parser/package-files/json-text-source-file-parser.js.map +0 -1
- package/dist/services/check-parser/package-files/source-file-parser.d.ts +0 -10
- package/dist/services/check-parser/package-files/source-file-parser.js +0 -13
- package/dist/services/check-parser/package-files/source-file-parser.js.map +0 -1
package/dist/commands/deploy.js
CHANGED
|
@@ -5,45 +5,110 @@ import { Flags } from '@oclif/core';
|
|
|
5
5
|
import { AuthCommand } from './authCommand.js';
|
|
6
6
|
import { parseProject } from '../services/project-parser.js';
|
|
7
7
|
import { loadChecklyConfig, resolveDependencyCacheVersion } from '../services/checkly-config-loader.js';
|
|
8
|
-
import {
|
|
8
|
+
import { Session } from '../constructs/index.js';
|
|
9
9
|
import chalk from 'chalk';
|
|
10
10
|
import { splitConfigFilePath, getGitInformation, getGitRepoRoot } from '../services/util.js';
|
|
11
11
|
import commonMessages from '../messages/common-messages.js';
|
|
12
|
-
import { forceFlag } from '../helpers/flags.js';
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
12
|
+
import { autoOrWholeNumberFlag, dryRunFlag, forceFlag } from '../helpers/flags.js';
|
|
13
|
+
import { formatPreview, NON_REPORTED_TYPES, PRETTY_RESOURCE_TYPES, ResourceDeployStatus, } from '../services/deploy-diff/preview-output.js';
|
|
14
|
+
import { DEPLOY_PLAN_DISABLED, ProjectDeployCancelledError, ProjectPlanStaleError, ProjectPlanDisabledError, ProjectPreviewNotSupportedError, } from '../rest/projects.js';
|
|
15
|
+
import { ConflictError, ValidationError } from '../rest/errors.js';
|
|
16
|
+
import { stripUnsupportedDeployFields } from '../services/deploy-diff/legacy-payload.js';
|
|
17
|
+
import { driftLines, findDrift, planChangeLines, planHasNoChanges, reducePlanForAgent, unbaselinedResources, } from '../services/deploy-diff/plan-summary.js';
|
|
18
|
+
import { formatWriteBackSkipped, formatWriteBackUpdated } from '../services/write-back/output.js';
|
|
19
|
+
import { applyWriteBack, hasWritableChanges, planWriteBack } from '../services/write-back/plan.js';
|
|
15
20
|
import { uploadSnapshots } from '../services/snapshot-service.js';
|
|
16
21
|
import { BrowserCheckBundle } from '../constructs/browser-check-bundle.js';
|
|
17
22
|
import { Bundler } from '../services/check-parser/bundler.js';
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
23
|
+
/**
|
|
24
|
+
* The deploy payload fields that arrived with the preview endpoint, which a
|
|
25
|
+
* deploy schema older than it rejects by name (`"sourceFile" is not allowed`).
|
|
26
|
+
* Kept in step with `stripUnsupportedDeployFields`.
|
|
27
|
+
*/
|
|
28
|
+
const PREVIEW_ERA_FIELDS = ['sourceFile', 'codeBundleSha256', 'sha256'];
|
|
29
|
+
/**
|
|
30
|
+
* Whether the API refused the payload because of a field an older deploy
|
|
31
|
+
* schema does not know: a 400 whose message names the field as not allowed.
|
|
32
|
+
* Only such a refusal is worth repeating in the older form: any other 400,
|
|
33
|
+
* including a bad value for one of these very fields, describes a problem
|
|
34
|
+
* the older form would not fix, or would hide. A refusal whose body the
|
|
35
|
+
* client recognises arrives as a {@link ValidationError}; one it does not
|
|
36
|
+
* arrives as the raw HTTP error.
|
|
37
|
+
*/
|
|
38
|
+
function rejectsPreviewEraField(err) {
|
|
39
|
+
const status = err instanceof ValidationError ? 400 : err?.response?.status ?? err?.data?.statusCode;
|
|
40
|
+
if (status !== 400) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
const message = String(err?.data?.message ?? err?.response?.data?.message ?? err?.message ?? '');
|
|
44
|
+
return message.includes('is not allowed') && PREVIEW_ERA_FIELDS.some(field => message.includes(field));
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Thrown when a `--fail-on-drift` run plans again after its plan went stale
|
|
48
|
+
* and the new plan would overwrite changes made in Checkly. Nothing has been
|
|
49
|
+
* written at that point.
|
|
50
|
+
*/
|
|
51
|
+
class DriftDetectedError extends Error {
|
|
52
|
+
drift;
|
|
53
|
+
constructor(drift) {
|
|
54
|
+
super('The plan would overwrite changes made in Checkly.');
|
|
55
|
+
this.drift = drift;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The further choice a terminal gets when the plan shows a resource edited
|
|
60
|
+
* outside the project and the code can take the edit: write the account's
|
|
61
|
+
* current values into the code and deploy nothing, so the user reviews the
|
|
62
|
+
* diff and deploys again rather than overwriting the edit. Only the
|
|
63
|
+
* properties the write-back knows the construct's spelling of (a literal,
|
|
64
|
+
* or a helper such as `Frequency.EVERY_5M`) can be written; everything
|
|
65
|
+
* else is listed with its reason.
|
|
66
|
+
*/
|
|
67
|
+
function writeBackAlternatives(diff, project, command) {
|
|
68
|
+
if (!hasWritableChanges(diff, project)) {
|
|
69
|
+
return [];
|
|
70
|
+
}
|
|
71
|
+
return [{
|
|
72
|
+
title: 'Update my code with the changes made in Checkly (deploys nothing)',
|
|
73
|
+
run: async () => {
|
|
74
|
+
const cwd = process.cwd();
|
|
75
|
+
const writeBack = await planWriteBack({ diff, project, cwd });
|
|
76
|
+
const skipped = writeBack.skipped.length > 0 ? formatWriteBackSkipped({ writeBack, project, cwd }) : undefined;
|
|
77
|
+
// Sets the outcome apart from the question above it, on stderr.
|
|
78
|
+
command.logToStderr();
|
|
79
|
+
if (writeBack.applied.length === 0) {
|
|
80
|
+
if (skipped !== undefined) {
|
|
81
|
+
command.log(skipped);
|
|
82
|
+
}
|
|
83
|
+
command.log('Nothing in the code could be updated automatically, so nothing was changed.');
|
|
84
|
+
command.log('Nothing was deployed.');
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
await applyWriteBack(writeBack);
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
// What has to be edited by hand is true whether or not the write
|
|
92
|
+
// went through, so it is still said, as part of the error report.
|
|
93
|
+
if (skipped !== undefined) {
|
|
94
|
+
command.logToStderr(skipped);
|
|
95
|
+
}
|
|
96
|
+
// The error names the files already rewritten, if any.
|
|
97
|
+
command.style.longError('Could not update your code.', err.message);
|
|
98
|
+
command.logToStderr('Nothing was deployed.');
|
|
99
|
+
command.exit(1);
|
|
100
|
+
}
|
|
101
|
+
// Reported once the files hold it, not as an intention; what could not
|
|
102
|
+
// be written follows what was.
|
|
103
|
+
command.log(formatWriteBackUpdated({ writeBack, project, cwd }));
|
|
104
|
+
if (skipped !== undefined) {
|
|
105
|
+
command.log(skipped);
|
|
106
|
+
}
|
|
107
|
+
command.log('Nothing was deployed.');
|
|
108
|
+
command.logToStderr('Review with `git diff`, then run `npx checkly deploy` again.');
|
|
109
|
+
},
|
|
110
|
+
}];
|
|
111
|
+
}
|
|
47
112
|
export default class Deploy extends AuthCommand {
|
|
48
113
|
static coreCommand = true;
|
|
49
114
|
static hidden = false;
|
|
@@ -66,15 +131,61 @@ export default class Deploy extends AuthCommand {
|
|
|
66
131
|
default: false,
|
|
67
132
|
}),
|
|
68
133
|
'schedule-on-deploy': Flags.boolean({
|
|
69
|
-
description: '
|
|
70
|
-
|
|
134
|
+
description: 'Schedule checks to run right after the deploy instead of waiting for their next scheduled run. '
|
|
135
|
+
+ 'The other --schedule-on-deploy-* flags refine which checks it schedules.',
|
|
136
|
+
default: false,
|
|
71
137
|
allowNo: true,
|
|
72
138
|
}),
|
|
139
|
+
'schedule-on-deploy-scope': Flags.string({
|
|
140
|
+
description: 'Which checks to schedule after the deploy: "changed" schedules the checks the deploy created or '
|
|
141
|
+
+ 'updated, "all" also the ones it left unchanged.',
|
|
142
|
+
options: ['changed', 'all'],
|
|
143
|
+
default: 'changed',
|
|
144
|
+
}),
|
|
145
|
+
'schedule-on-deploy-threshold': autoOrWholeNumberFlag({
|
|
146
|
+
description: 'Schedule no checks after the deploy if it would schedule more than this many, not counting the '
|
|
147
|
+
+ 'ones --schedule-on-deploy-scope and --schedule-on-deploy-min-frequency leave out. '
|
|
148
|
+
+ '"auto" leaves the threshold to Checkly, which also caps the number you can set.',
|
|
149
|
+
default: 'auto',
|
|
150
|
+
}),
|
|
151
|
+
'schedule-on-deploy-min-frequency': autoOrWholeNumberFlag({
|
|
152
|
+
description: 'After the deploy, schedule only the checks that run every this many minutes or less often; '
|
|
153
|
+
+ 'more frequent checks wait for their next scheduled run. Goes by the frequency Checkly resolves for each '
|
|
154
|
+
+ 'check, its defaults included. 0 schedules every check. "auto" leaves the minimum to Checkly, which also '
|
|
155
|
+
+ 'caps the number you can set.',
|
|
156
|
+
default: 'auto',
|
|
157
|
+
}),
|
|
73
158
|
'preserve-resources': Flags.boolean({
|
|
74
159
|
description: 'Keep resources removed from code (and their run history) in your Checkly account instead of deleting them.',
|
|
75
160
|
default: false,
|
|
76
161
|
}),
|
|
77
162
|
'force': forceFlag(),
|
|
163
|
+
'dry-run': dryRunFlag(),
|
|
164
|
+
'plan': Flags.boolean({
|
|
165
|
+
description: 'Plan the deploy first: Checkly says what would change, property by property, compared '
|
|
166
|
+
+ 'with what is deployed. The deploy then applies that plan, leaves unchanged resources alone and '
|
|
167
|
+
+ 'refuses to run if your Checkly account changed in between. --no-plan deploys without a plan '
|
|
168
|
+
+ 'and writes every resource.',
|
|
169
|
+
default: true,
|
|
170
|
+
allowNo: true,
|
|
171
|
+
}),
|
|
172
|
+
'plan-token': Flags.string({
|
|
173
|
+
description: 'Deploy only if the plan still matches this token from an earlier run. '
|
|
174
|
+
+ 'Aborts if anything changed in your Checkly account since then. Not available with --no-plan.',
|
|
175
|
+
}),
|
|
176
|
+
'prune-unmanaged-relations': Flags.boolean({
|
|
177
|
+
description: 'Delete the alert channel subscriptions and private location assignments on this project\'s '
|
|
178
|
+
+ 'checks and groups that the project does not manage. Not available with --no-plan.',
|
|
179
|
+
default: false,
|
|
180
|
+
}),
|
|
181
|
+
'fail-on-drift': Flags.boolean({
|
|
182
|
+
description: 'Deploy nothing and fail if any resource of this project was changed or deleted in Checkly '
|
|
183
|
+
+ 'since the last planned deploy, which this deploy would overwrite. Ignored with --dry-run, whose output '
|
|
184
|
+
+ 'reports those changes. Not available with --no-plan.',
|
|
185
|
+
default: false,
|
|
186
|
+
allowNo: true,
|
|
187
|
+
env: 'CHECKLY_FAIL_ON_DRIFT',
|
|
188
|
+
}),
|
|
78
189
|
'cancel-in-progress-deployment': Flags.boolean({
|
|
79
190
|
description: 'If a deployment for this project is already in progress, cancel it instead of waiting for it to finish.',
|
|
80
191
|
default: false,
|
|
@@ -102,33 +213,53 @@ export default class Deploy extends AuthCommand {
|
|
|
102
213
|
};
|
|
103
214
|
async run() {
|
|
104
215
|
const { flags, metadata } = await this.parse(Deploy);
|
|
105
|
-
const { force, preview, '
|
|
216
|
+
const { force, preview, 'dry-run': dryRun,
|
|
217
|
+
// Named for what it is, the user's request: `plan` further down is the
|
|
218
|
+
// plan Checkly answered with, which a run that asked may still not have.
|
|
219
|
+
'plan': planRequested, 'plan-token': requestedPlanToken, 'prune-unmanaged-relations': pruneRelations, 'fail-on-drift': failOnDriftFlag, 'cancel-in-progress-deployment': cancelInProgress, 'schedule-on-deploy': scheduleOnDeploy, 'schedule-on-deploy-scope': scheduleScope, 'schedule-on-deploy-threshold': scheduleThreshold, 'schedule-on-deploy-min-frequency': scheduleMinFrequency, 'preserve-resources': preserveResources, output: outputFlag, verbose, config: configFilename, 'verify-runtime-dependencies': verifyRuntimeDependencies, 'debug-bundle': debugBundle, 'debug-bundle-output-file': debugBundleOutputFile, } = flags;
|
|
106
220
|
const output = outputFlag || verbose;
|
|
221
|
+
// A dry run deploys nothing, and its envelope is read by scripts the same
|
|
222
|
+
// way whatever the plan holds, the changes made in Checkly included (each
|
|
223
|
+
// change carries its origin). So the drift check, which a pipeline may
|
|
224
|
+
// switch on for every step with CHECKLY_FAIL_ON_DRIFT, leaves it alone.
|
|
225
|
+
const failOnDrift = failOnDriftFlag && !dryRun;
|
|
226
|
+
// All are promises only a plan can keep: the token, that nothing is
|
|
227
|
+
// deployed unless the account still is what was reviewed; pruning, that
|
|
228
|
+
// what gets deleted was listed first; and the drift check, which reads
|
|
229
|
+
// what was changed in Checkly off the plan. Checked here rather than with
|
|
230
|
+
// the flags' `dependsOn`, which a flag that has a default always satisfies.
|
|
231
|
+
if (!planRequested) {
|
|
232
|
+
const needsPlan = requestedPlanToken !== undefined
|
|
233
|
+
? '--plan-token'
|
|
234
|
+
: pruneRelations
|
|
235
|
+
? '--prune-unmanaged-relations'
|
|
236
|
+
: failOnDrift ? '--fail-on-drift' : undefined;
|
|
237
|
+
if (needsPlan !== undefined) {
|
|
238
|
+
this.style.longError(`${needsPlan} applies to a planned deploy only.`, `Re-run without --no-plan, or without ${needsPlan}.`);
|
|
239
|
+
this.exit(2);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
// The flags that refine scheduling mean nothing on a deploy that schedules
|
|
243
|
+
// no checks. Passing one is taken as having expected scheduling, which is
|
|
244
|
+
// opt-in, so the deploy stops rather than quietly scheduling nothing.
|
|
245
|
+
if (!scheduleOnDeploy) {
|
|
246
|
+
const refiningFlag = [
|
|
247
|
+
'schedule-on-deploy-scope',
|
|
248
|
+
'schedule-on-deploy-threshold',
|
|
249
|
+
'schedule-on-deploy-min-frequency',
|
|
250
|
+
].find(name => metadata.flags[name]?.setFromDefault !== true);
|
|
251
|
+
if (refiningFlag !== undefined) {
|
|
252
|
+
this.style.longError(`--${refiningFlag} applies only when checks are scheduled after the deploy.`, `Add --schedule-on-deploy to schedule them, or drop --${refiningFlag}.`);
|
|
253
|
+
this.exit(2);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
107
256
|
const { configDirectory, configFilenames } = splitConfigFilePath(configFilename);
|
|
108
257
|
const { config: checklyConfig, constructs: checklyConfigConstructs, diagnostics: configDiagnostics, } = await loadChecklyConfig(configDirectory, configFilenames);
|
|
109
258
|
const account = this.account;
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
changes: [
|
|
115
|
-
`Deploy project "${checklyConfig.projectName}" to account "${account.name}"`,
|
|
116
|
-
scheduleOnDeploy
|
|
117
|
-
? 'Schedule checks after deploy'
|
|
118
|
-
: 'Checks will NOT be scheduled after deploy',
|
|
119
|
-
preserveResources
|
|
120
|
-
? 'Keep any resources removed from code (and their run history) in your Checkly account, where you can manage them from the Checkly web app'
|
|
121
|
-
: 'Delete any resources removed from code, losing their run history. Pass --preserve-resources to keep them in your Checkly account instead',
|
|
122
|
-
],
|
|
123
|
-
flags,
|
|
124
|
-
flagMetadata: metadata.flags,
|
|
125
|
-
classification: {
|
|
126
|
-
readOnly: Deploy.readOnly,
|
|
127
|
-
destructive: Deploy.destructive,
|
|
128
|
-
idempotent: Deploy.idempotent,
|
|
129
|
-
},
|
|
130
|
-
}, { force });
|
|
131
|
-
}
|
|
259
|
+
// The confirmation happens further down, once the project has been parsed
|
|
260
|
+
// and Checkly has said what the deploy would change, so that one prompt
|
|
261
|
+
// can show the actual plan instead of asking about a deploy nobody has
|
|
262
|
+
// seen yet.
|
|
132
263
|
this.style.actionStart('Parsing your project');
|
|
133
264
|
const availableRuntimes = await api.runtimes.getAll();
|
|
134
265
|
const project = await parseProject({
|
|
@@ -153,6 +284,7 @@ export default class Deploy extends AuthCommand {
|
|
|
153
284
|
include: checklyConfig.checks?.include,
|
|
154
285
|
embeddedPackages: checklyConfig.bundle?.packages?.embed,
|
|
155
286
|
playwrightChecks: checklyConfig.checks?.playwrightChecks,
|
|
287
|
+
warnOnMissingCheckLocations: true,
|
|
156
288
|
});
|
|
157
289
|
const repoInfo = getGitInformation(project.repoUrl);
|
|
158
290
|
const repoRoot = getGitRepoRoot();
|
|
@@ -179,48 +311,65 @@ export default class Deploy extends AuthCommand {
|
|
|
179
311
|
})();
|
|
180
312
|
const archive = await bundler.finalize();
|
|
181
313
|
bundler.updateMarker(archive.archiveFile);
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
//
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
314
|
+
const browserBundles = Object.values(projectBundle.data.check)
|
|
315
|
+
.map(({ bundle }) => bundle)
|
|
316
|
+
.filter((bundle) => bundle instanceof BrowserCheckBundle);
|
|
317
|
+
// Uploading is what produces the storage keys a deploy needs, and it is
|
|
318
|
+
// deferred until the deploy has been confirmed: a preview describes the
|
|
319
|
+
// code bundle and every snapshot by content hash, and a dry-run deploy
|
|
320
|
+
// accepts a payload without keys, so finding out what a deploy would
|
|
321
|
+
// change costs no uploads. `uploaded` tells `deployPayload` whether the
|
|
322
|
+
// snapshots carry keys yet.
|
|
323
|
+
let uploaded = false;
|
|
324
|
+
const uploadArtifacts = async () => {
|
|
325
|
+
uploaded = true;
|
|
326
|
+
// The remote code bundle is only consumed by Playwright check suites (via
|
|
327
|
+
// bundler.marker). If nothing registered files to bundle (e.g. a project of
|
|
328
|
+
// only uptime monitors), there is nothing to upload — skip the store() to
|
|
329
|
+
// avoid an unnecessary code-bundle upload.
|
|
330
|
+
if (!bundler.isEmpty) {
|
|
331
|
+
this.style.actionStart('Uploading Playwright tests');
|
|
332
|
+
try {
|
|
333
|
+
const storedArchive = await archive.store();
|
|
334
|
+
bundler.updateMarker(storedArchive.key);
|
|
335
|
+
this.style.actionSuccess();
|
|
336
|
+
}
|
|
337
|
+
catch (err) {
|
|
338
|
+
this.style.actionFailure();
|
|
339
|
+
throw err;
|
|
340
|
+
}
|
|
204
341
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
const bundle
|
|
211
|
-
|
|
342
|
+
// The step is only announced when there is a snapshot to upload. Every
|
|
343
|
+
// browser check gets its snapshot list either way, an empty one included.
|
|
344
|
+
if (browserBundles.some(bundle => bundle.rawSnapshots?.length)) {
|
|
345
|
+
this.style.actionStart('Uploading Playwright snapshots');
|
|
346
|
+
try {
|
|
347
|
+
for (const bundle of browserBundles) {
|
|
348
|
+
bundle.snapshots = await uploadSnapshots(bundle.rawSnapshots);
|
|
349
|
+
}
|
|
350
|
+
this.style.actionSuccess();
|
|
351
|
+
}
|
|
352
|
+
catch (err) {
|
|
353
|
+
this.style.actionFailure();
|
|
354
|
+
throw err;
|
|
212
355
|
}
|
|
213
|
-
this.style.actionSuccess();
|
|
214
356
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
357
|
+
else {
|
|
358
|
+
for (const bundle of browserBundles) {
|
|
359
|
+
bundle.snapshots = [];
|
|
360
|
+
}
|
|
218
361
|
}
|
|
219
|
-
}
|
|
220
|
-
|
|
362
|
+
};
|
|
363
|
+
// Synthesized on demand rather than once: the snapshot entries are copied
|
|
364
|
+
// into the payload as values, so the payload sent after the upload has to
|
|
365
|
+
// be built after it to carry the keys.
|
|
366
|
+
const synthesize = () => ({ ...projectBundle.synthesize({ repoRoot }), repoInfo });
|
|
367
|
+
const projectPayload = synthesize();
|
|
221
368
|
if (!projectPayload.resources.length) {
|
|
222
369
|
if (preview) {
|
|
223
|
-
|
|
370
|
+
// The empty preview is the result; where to read up is advice.
|
|
371
|
+
this.log('No checks were detected.');
|
|
372
|
+
this.logToStderr('More information on how to set up a Checkly CLI project is available at https://checklyhq.com/docs/cli/.');
|
|
224
373
|
return;
|
|
225
374
|
}
|
|
226
375
|
else {
|
|
@@ -233,16 +382,176 @@ export default class Deploy extends AuthCommand {
|
|
|
233
382
|
this.log(`Successfully wrote debug bundle to "${debugBundleOutputFile}".`);
|
|
234
383
|
return;
|
|
235
384
|
}
|
|
236
|
-
|
|
237
|
-
//
|
|
238
|
-
//
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
385
|
+
const summaryOptions = { prettyTypes: PRETTY_RESOURCE_TYPES, foldedTypes: NON_REPORTED_TYPES };
|
|
386
|
+
// The refusal of a run whose plan would overwrite changes made in Checkly.
|
|
387
|
+
// The way forward depends on which side should win, so both are named.
|
|
388
|
+
const reportDrift = (drift, title) => this.style.longError(title, [
|
|
389
|
+
...driftLines(drift, summaryOptions).map(line => `- ${line}`),
|
|
390
|
+
'',
|
|
391
|
+
'To keep these changes, add them to your code: `checkly deploy --no-fail-on-drift` in a terminal '
|
|
392
|
+
+ 'shows them and can update the code for many of them. To discard them, deploy with --no-fail-on-drift.',
|
|
393
|
+
].join('\n'));
|
|
394
|
+
const resourceCount = (count) => count === 1 ? '1 resource' : `${count} resources`;
|
|
395
|
+
const classification = {
|
|
396
|
+
readOnly: Deploy.readOnly,
|
|
397
|
+
destructive: Deploy.destructive,
|
|
398
|
+
idempotent: Deploy.idempotent,
|
|
399
|
+
};
|
|
400
|
+
// Ask Checkly what this payload would change. Writes nothing, and needs no
|
|
401
|
+
// upload: the payload describes the code bundle and every snapshot by
|
|
402
|
+
// content hash.
|
|
403
|
+
// `full` buys each changed resource's current state, which is what the
|
|
404
|
+
// rendered construct diff (`--preview`, `--output`, the plan an interactive
|
|
405
|
+
// run shows before asking) and the machine-readable envelope (`--dry-run`,
|
|
406
|
+
// the `confirmation_required` an agent or CI run prints) show. Only a
|
|
407
|
+
// forced deploy prints nothing of the kind, so only it skips paying for
|
|
408
|
+
// the state.
|
|
409
|
+
const detail = dryRun || preview || output || !force ? 'full' : 'changes';
|
|
410
|
+
let plan;
|
|
411
|
+
// Set when the API has no preview endpoint, which also means it rejects the
|
|
412
|
+
// payload fields that arrived with it.
|
|
413
|
+
let previewNotSupported = false;
|
|
414
|
+
// With --no-plan the deploy applies to whatever the account looks like
|
|
415
|
+
// when it runs: no plan, no token, and nothing to render before the prompt.
|
|
416
|
+
if (planRequested) {
|
|
417
|
+
this.style.actionStart('Checking what would change');
|
|
418
|
+
try {
|
|
419
|
+
plan = await api.projects.preview(projectPayload, {
|
|
420
|
+
detail,
|
|
421
|
+
preserveResources,
|
|
422
|
+
pruneRelations,
|
|
423
|
+
onStatus: message => this.style.actionStatus(message),
|
|
424
|
+
});
|
|
425
|
+
this.style.actionSuccess();
|
|
426
|
+
}
|
|
427
|
+
catch (err) {
|
|
428
|
+
this.style.actionFailure();
|
|
429
|
+
// An API that has plans switched off is not one that predates them: it
|
|
430
|
+
// knows the payload fields that arrived with the preview endpoint, so
|
|
431
|
+
// the payload is not stripped of them.
|
|
432
|
+
const plansDisabled = err instanceof ProjectPlanDisabledError;
|
|
433
|
+
previewNotSupported = err instanceof ProjectPreviewNotSupportedError;
|
|
434
|
+
const previewSupported = !previewNotSupported && !plansDisabled;
|
|
435
|
+
// --prune-unmanaged-relations deletes data, and without a plan nothing
|
|
436
|
+
// can say what: an API that predates the preview endpoint would not
|
|
437
|
+
// prune at all, and an API that would prune cannot be asked what it is
|
|
438
|
+
// about to delete. Both are refused rather than silently downgraded.
|
|
439
|
+
if (pruneRelations) {
|
|
440
|
+
this.style.longError(previewSupported
|
|
441
|
+
? 'Could not check which relations --prune-unmanaged-relations would delete, so nothing was deployed.'
|
|
442
|
+
: plansDisabled
|
|
443
|
+
? 'Checkly has deploy plans switched off at the moment, so relations cannot be pruned.'
|
|
444
|
+
: 'This Checkly API cannot prune unmanaged relations yet.', previewSupported ? 'Try again in a moment.' : 'Re-run without --prune-unmanaged-relations.');
|
|
445
|
+
this.exit(1);
|
|
446
|
+
}
|
|
447
|
+
// A deploy pinned to a plan cannot proceed without knowing the plan.
|
|
448
|
+
if (requestedPlanToken !== undefined) {
|
|
449
|
+
this.style.longError('Could not check the plan this deploy is pinned to.', previewSupported
|
|
450
|
+
? err.message
|
|
451
|
+
: plansDisabled
|
|
452
|
+
? 'Checkly has deploy plans switched off at the moment; re-run without --plan-token.'
|
|
453
|
+
: 'This Checkly API does not support deploy previews; re-run without --plan-token.');
|
|
454
|
+
this.exit(1);
|
|
455
|
+
}
|
|
456
|
+
// Without a plan nothing says what was changed in Checkly, and a run
|
|
457
|
+
// that asked to be stopped by such changes must not overwrite them
|
|
458
|
+
// unchecked.
|
|
459
|
+
if (failOnDrift) {
|
|
460
|
+
this.style.longError(previewSupported
|
|
461
|
+
? `Could not check whether anything was changed in Checkly, so nothing was deployed: ${err.message}`
|
|
462
|
+
: plansDisabled
|
|
463
|
+
? 'Checkly has deploy plans switched off at the moment, '
|
|
464
|
+
+ 'so changes made in Checkly cannot be detected and nothing was deployed.'
|
|
465
|
+
: 'This Checkly API cannot detect changes made in Checkly, so nothing was deployed.', previewSupported ? 'Try again in a moment.' : 'Re-run without --fail-on-drift.');
|
|
466
|
+
this.exit(1);
|
|
467
|
+
}
|
|
468
|
+
// Deploying without a reviewed plan beats not deploying at all: one
|
|
469
|
+
// resource Checkly cannot read, or an API that is a version behind, must
|
|
470
|
+
// not make a project undeployable. The run falls back to the coarser
|
|
471
|
+
// dry-run diff and its delete guard, and sends no plan token.
|
|
472
|
+
this.style.longWarning(previewSupported
|
|
473
|
+
// Say which failure it was: the user is about to get a coarser answer
|
|
474
|
+
// than a planned deploy gives and deserves to know why.
|
|
475
|
+
? `Could not check what this deploy would change: ${err.message}`
|
|
476
|
+
: plansDisabled
|
|
477
|
+
? err.message
|
|
478
|
+
// A 404 from this path means the endpoint is not there; whether that
|
|
479
|
+
// is an API predating it or something else in the way, the CLI cannot
|
|
480
|
+
// tell, so it says what it observed.
|
|
481
|
+
: 'This Checkly API answered 404 for the deploy preview endpoint.', 'Falling back to a summary of created, updated and deleted resources.');
|
|
482
|
+
}
|
|
483
|
+
if (plan !== undefined && requestedPlanToken !== undefined && requestedPlanToken !== plan.planToken) {
|
|
484
|
+
this.style.longError('Your Checkly account no longer matches the plan this deploy is pinned to, so nothing was deployed.', 'Re-run `checkly deploy --preview` to see the current plan.');
|
|
485
|
+
this.exit(1);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
// The payload goes out in the form the deploy route accepted before the
|
|
489
|
+
// preview endpoint existed in exactly the two cases where the full one
|
|
490
|
+
// cannot be sent: an API that does not have the endpoint rejects the fields
|
|
491
|
+
// that arrived with it, and a run that skipped the uploads describes
|
|
492
|
+
// snapshots it has no storage key for, which every write route requires.
|
|
493
|
+
//
|
|
494
|
+
// Not for every missing plan: a preview that failed transiently against a
|
|
495
|
+
// current API leaves the fields perfectly acceptable, and stripping them
|
|
496
|
+
// would blank the stored content hashes — making the NEXT deploy report
|
|
497
|
+
// every Playwright suite and every snapshot-bearing check as changed.
|
|
498
|
+
const deployPayload = () => previewNotSupported || !uploaded ? stripUnsupportedDeployFields(synthesize()) : synthesize();
|
|
499
|
+
// A planned run learns from the preview call whether the API has the
|
|
500
|
+
// endpoint, and with it whether the deploy route knows the fields that
|
|
501
|
+
// arrived with it. A run without a plan — one started with --no-plan, or
|
|
502
|
+
// a preview that failed for a reason other than a missing endpoint — does not, so a
|
|
503
|
+
// payload the route refuses because of one of those fields is sent once
|
|
504
|
+
// more in the older form; the rest of the run then sends that form too.
|
|
505
|
+
// If the older form is refused as well, the refusal of the payload the
|
|
506
|
+
// user asked for is the one that surfaces; any other failure of the
|
|
507
|
+
// second attempt is its own and keeps its own handling. The older form
|
|
508
|
+
// blanks the stored content hashes, which the next planned deploy reports
|
|
509
|
+
// as a change to every Playwright check suite and every check with
|
|
510
|
+
// snapshots — once, and worth a warning once a deploy has gone out that
|
|
511
|
+
// way.
|
|
512
|
+
let sentLegacyPayload = false;
|
|
513
|
+
const deployOrRetryLegacy = async (options) => {
|
|
514
|
+
try {
|
|
515
|
+
return await api.projects.deploy(deployPayload(), options);
|
|
516
|
+
}
|
|
517
|
+
catch (err) {
|
|
518
|
+
if (plan !== undefined || previewNotSupported || !rejectsPreviewEraField(err)) {
|
|
519
|
+
throw err;
|
|
520
|
+
}
|
|
521
|
+
previewNotSupported = true;
|
|
522
|
+
try {
|
|
523
|
+
const result = await api.projects.deploy(deployPayload(), options);
|
|
524
|
+
sentLegacyPayload = true;
|
|
525
|
+
return result;
|
|
526
|
+
}
|
|
527
|
+
catch (retryErr) {
|
|
528
|
+
if (retryErr instanceof ValidationError) {
|
|
529
|
+
throw err;
|
|
530
|
+
}
|
|
531
|
+
throw retryErr;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
};
|
|
535
|
+
// Without a plan, deletions are only visible in a dry-run deploy. It runs
|
|
536
|
+
// before the uploads, like the preview: a run that is about to ask for
|
|
537
|
+
// confirmation, or that only reports, must not leave a code bundle and
|
|
538
|
+
// snapshots in storage for an answer that may be no. The dry run validates
|
|
539
|
+
// the payload it is given, in which a code bundle it has not been handed a
|
|
540
|
+
// key for is described by its path on disk and snapshots without a key are
|
|
541
|
+
// left out, as it was before the preview endpoint existed. A storage key
|
|
542
|
+
// the deploy route refuses is therefore caught by the deploy itself, after
|
|
543
|
+
// the uploads, not by this dry run.
|
|
544
|
+
let fallbackDiff;
|
|
545
|
+
if (plan === undefined && (preview || dryRun || (!preserveResources && !force))) {
|
|
242
546
|
this.style.actionStart('Verifying deployed state');
|
|
243
547
|
try {
|
|
244
|
-
const { data
|
|
245
|
-
|
|
548
|
+
const { data } = await deployOrRetryLegacy({
|
|
549
|
+
dryRun: true,
|
|
550
|
+
scheduleOnDeploy,
|
|
551
|
+
preserveResources,
|
|
552
|
+
onStatus: message => this.style.actionStatus(message),
|
|
553
|
+
});
|
|
554
|
+
fallbackDiff = data;
|
|
246
555
|
this.style.actionSuccess();
|
|
247
556
|
}
|
|
248
557
|
catch (err) {
|
|
@@ -250,65 +559,315 @@ export default class Deploy extends AuthCommand {
|
|
|
250
559
|
this.style.longError(`Your project could not be deployed.`, err);
|
|
251
560
|
this.exit(1);
|
|
252
561
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
562
|
+
}
|
|
563
|
+
// The plan as `--preview` prints it, which is also what a terminal sees
|
|
564
|
+
// before it is asked. Without a plan, the dry run's findings are listed.
|
|
565
|
+
const renderPlan = (planToken) => formatPreview({
|
|
566
|
+
heading: { title: 'Deploy preview', projectName: project.name, accountName: account.name },
|
|
567
|
+
diff: plan?.diff ?? fallbackDiff?.diff ?? [],
|
|
568
|
+
project,
|
|
569
|
+
verbose,
|
|
570
|
+
pruneRelations,
|
|
571
|
+
rendering: plan !== undefined ? { plan: plan.diff, local: projectPayload.resources } : undefined,
|
|
572
|
+
planToken,
|
|
573
|
+
});
|
|
574
|
+
// Checked before anything is asked or uploaded, in every mode but a dry
|
|
575
|
+
// run (see `failOnDrift`): a run that asked to be stopped by changes made
|
|
576
|
+
// in Checkly is stopped whoever runs it. A plan exists here, since a run with --fail-on-drift that could not
|
|
577
|
+
// get one has already failed. `--preview --fail-on-drift` doubles as a
|
|
578
|
+
// drift check that deploys nothing: it prints the plan, then fails.
|
|
579
|
+
if (failOnDrift && plan !== undefined) {
|
|
580
|
+
const drift = findDrift(plan.diff, summaryOptions);
|
|
581
|
+
if (drift.length > 0) {
|
|
582
|
+
if (preview) {
|
|
583
|
+
this.log(renderPlan());
|
|
257
584
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
classification: {
|
|
269
|
-
readOnly: Deploy.readOnly,
|
|
270
|
-
destructive: Deploy.destructive,
|
|
271
|
-
idempotent: Deploy.idempotent,
|
|
272
|
-
},
|
|
273
|
-
}, { force });
|
|
585
|
+
reportDrift(drift, preview
|
|
586
|
+
? `This deploy would overwrite changes made in Checkly to ${resourceCount(drift.length)}.`
|
|
587
|
+
: `This deploy would overwrite changes made in Checkly to ${resourceCount(drift.length)}, `
|
|
588
|
+
+ 'so nothing was deployed.');
|
|
589
|
+
this.exit(1);
|
|
590
|
+
}
|
|
591
|
+
const unbaselined = unbaselinedResources(plan.diff, summaryOptions);
|
|
592
|
+
if (unbaselined > 0) {
|
|
593
|
+
this.style.longWarning(`${resourceCount(unbaselined)} could not be checked for changes made in Checkly.`, 'Checkly has no earlier planned deploy of them to compare with. '
|
|
594
|
+
+ 'A planned deploy records one, so later deploys can check them.');
|
|
274
595
|
}
|
|
275
596
|
}
|
|
597
|
+
if (preview && !dryRun) {
|
|
598
|
+
this.log(renderPlan(plan?.planToken));
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
601
|
+
// Resources removed from code that the deploy deletes, as the plan or,
|
|
602
|
+
// without one, the dry run found them. Undefined when neither ran (a
|
|
603
|
+
// forced run without a plan), so nothing is known about them.
|
|
604
|
+
const knownDiff = plan?.diff ?? fallbackDiff?.diff;
|
|
605
|
+
const deletions = knownDiff !== undefined ? collectDeletions(knownDiff) : undefined;
|
|
606
|
+
// What the deploy does as a whole, worded as the confirmation prompt words
|
|
607
|
+
// it. The plan's own lines follow these. The scheduling threshold is left
|
|
608
|
+
// out: few deploys reach it, and the deploy reports it when one does.
|
|
609
|
+
const optionLines = [
|
|
610
|
+
`Deploy project "${checklyConfig.projectName}" to account "${account.name}"`,
|
|
611
|
+
scheduleOnDeploy
|
|
612
|
+
? `Schedule ${scheduleScope} checks after deploy`
|
|
613
|
+
: 'Leave checks to run at their next scheduled time. '
|
|
614
|
+
+ 'Pass --schedule-on-deploy to schedule them right after the deploy instead',
|
|
615
|
+
// Saying resources will be deleted when none are reads as a warning
|
|
616
|
+
// about data loss that is not going to happen.
|
|
617
|
+
...preserveResources
|
|
618
|
+
? ['Keep any resources removed from code (and their run history) in your Checkly account, where you can manage them from the Checkly web app']
|
|
619
|
+
: deletions === undefined || deletions.length > 0
|
|
620
|
+
? ['Delete any resources removed from code, losing their run history. Pass --preserve-resources to keep them in your Checkly account instead']
|
|
621
|
+
: [],
|
|
622
|
+
...pruneRelations
|
|
623
|
+
? ['Delete the alert channel subscriptions and private location assignments on this project\'s checks '
|
|
624
|
+
+ 'and groups that the project does not manage']
|
|
625
|
+
: [],
|
|
626
|
+
];
|
|
627
|
+
// With a plan, every touched resource has a line; without one, only the
|
|
628
|
+
// deletions the dry run found are known.
|
|
629
|
+
const planLines = plan !== undefined
|
|
630
|
+
? planChangeLines(plan.diff, summaryOptions)
|
|
631
|
+
: (deletions ?? [])
|
|
632
|
+
.map(({ resourceType, logicalId }) => `Permanently delete ${PRETTY_RESOURCE_TYPES[resourceType] ?? resourceType}: ${logicalId}, `
|
|
633
|
+
+ 'losing its run history');
|
|
634
|
+
// A plan with nothing to write has nothing to approve, so nobody is asked:
|
|
635
|
+
// a terminal, an agent and a forced run all read that there are no changes
|
|
636
|
+
// and carry on. The deploy is still sent, pinned to the plan's token like
|
|
637
|
+
// any other. It writes no resource, but it records the deployment, renews
|
|
638
|
+
// the deployed state the next plan compares against (which is what clears
|
|
639
|
+
// the mark of a resource edited outside code once the code agrees with
|
|
640
|
+
// it), and schedules the checks unless told not to. --dry-run keeps its
|
|
641
|
+
// envelope, which a script reads the same way whatever the plan holds.
|
|
642
|
+
const nothingToApply = plan !== undefined && planHasNoChanges(plan.diff, summaryOptions);
|
|
643
|
+
if (nothingToApply && !dryRun) {
|
|
644
|
+
this.log(renderPlan());
|
|
645
|
+
}
|
|
646
|
+
else {
|
|
647
|
+
// The one confirmation of the command: the plan is known by now, so the
|
|
648
|
+
// prompt, the agent envelope and --dry-run all describe the deploy that is
|
|
649
|
+
// about to run rather than a deploy nobody has seen. A terminal gets the
|
|
650
|
+
// plan rendered as `--preview` prints it, with the options under it; the
|
|
651
|
+
// plan lines are not repeated there since the overview names every
|
|
652
|
+
// resource. No plan-token footer: this run pins the token itself.
|
|
653
|
+
await this.confirmOrAbort({
|
|
654
|
+
command: 'deploy',
|
|
655
|
+
description: 'Deploy project to Checkly',
|
|
656
|
+
changes: [...optionLines, ...planLines],
|
|
657
|
+
...plan !== undefined
|
|
658
|
+
? {
|
|
659
|
+
terminal: {
|
|
660
|
+
plan: renderPlan,
|
|
661
|
+
changes: optionLines,
|
|
662
|
+
alternatives: writeBackAlternatives(plan.diff, project, this),
|
|
663
|
+
},
|
|
664
|
+
question: 'Apply these changes?',
|
|
665
|
+
}
|
|
666
|
+
: {},
|
|
667
|
+
// The token rides along in the echoed command, so the confirming run
|
|
668
|
+
// deploys the plan that was shown here and refuses a different one.
|
|
669
|
+
flags: plan !== undefined ? { ...flags, 'plan-token': plan.planToken } : flags,
|
|
670
|
+
flagMetadata: metadata.flags,
|
|
671
|
+
classification,
|
|
672
|
+
...plan !== undefined
|
|
673
|
+
? { preview: { planToken: plan.planToken, diff: reducePlanForAgent(plan.diff) } }
|
|
674
|
+
: {},
|
|
675
|
+
}, { force, dryRun });
|
|
676
|
+
}
|
|
677
|
+
await uploadArtifacts();
|
|
678
|
+
const runDeploy = () => deployOrRetryLegacy({
|
|
679
|
+
scheduleOnDeploy,
|
|
680
|
+
scheduleOnDeployScope: scheduleScope,
|
|
681
|
+
scheduleOnDeployThreshold: scheduleThreshold === 'auto' ? undefined : scheduleThreshold,
|
|
682
|
+
scheduleOnDeployMinFrequency: scheduleMinFrequency === 'auto' ? undefined : scheduleMinFrequency,
|
|
683
|
+
preserveResources,
|
|
684
|
+
pruneRelations,
|
|
685
|
+
// Read when the deploy is sent, so that a run which planned again after
|
|
686
|
+
// a stale plan is covered. Only a run that holds a plan asks the deploy
|
|
687
|
+
// to apply one: without it the deploy writes every resource, as it did
|
|
688
|
+
// before plans existed.
|
|
689
|
+
plan: plan !== undefined,
|
|
690
|
+
planToken: plan?.planToken,
|
|
691
|
+
cancelInProgress,
|
|
692
|
+
onProgress: progress => this.style.actionStatus(`${progress}% complete`),
|
|
693
|
+
onStatus: message => this.style.actionStatus(message),
|
|
694
|
+
});
|
|
276
695
|
try {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
696
|
+
// "Deploying" right under "No changes" would read as a contradiction.
|
|
697
|
+
this.style.actionStart(nothingToApply ? 'Recording the deployment' : 'Deploying project');
|
|
698
|
+
let data;
|
|
699
|
+
try {
|
|
700
|
+
({ data } = await runDeploy());
|
|
701
|
+
}
|
|
702
|
+
catch (err) {
|
|
703
|
+
// A run that showed nobody a plan has nothing to protect: rather than
|
|
704
|
+
// failing a pipeline because someone touched the account while the code
|
|
705
|
+
// bundle was uploading, it plans again and deploys that. A pinned run,
|
|
706
|
+
// or one a person confirmed, is refused instead — see the catch below.
|
|
707
|
+
// A run without a plan sent no token, so it cannot be told its plan
|
|
708
|
+
// went stale; the guard keeps it out of the re-plan regardless.
|
|
709
|
+
if (!(err instanceof ProjectPlanStaleError) || !force || requestedPlanToken !== undefined || !planRequested) {
|
|
710
|
+
throw err;
|
|
711
|
+
}
|
|
712
|
+
this.style.actionStatus('Your Checkly account changed; checking again and deploying the current plan');
|
|
713
|
+
plan = await api.projects.preview(deployPayload(), { detail, preserveResources, pruneRelations });
|
|
714
|
+
// An account that moved under the deploy most likely moved because
|
|
715
|
+
// someone changed it in Checkly, which is what the drift check is for.
|
|
716
|
+
const drift = failOnDrift ? findDrift(plan.diff, summaryOptions) : [];
|
|
717
|
+
if (drift.length > 0) {
|
|
718
|
+
throw new DriftDetectedError(drift);
|
|
719
|
+
}
|
|
720
|
+
;
|
|
721
|
+
({ data } = await runDeploy());
|
|
722
|
+
}
|
|
723
|
+
this.style.actionSuccess();
|
|
724
|
+
if (sentLegacyPayload) {
|
|
725
|
+
this.style.longWarning('This Checkly API does not know the fields the preview endpoint added, so the deploy was sent without them.', 'The next planned deploy reports every Playwright check suite and every check with snapshots as changed.');
|
|
726
|
+
}
|
|
727
|
+
// Judged on what the deploy answered, not on the plan it started from: a
|
|
728
|
+
// forced run that planned again after the account moved may have written
|
|
729
|
+
// something after all.
|
|
730
|
+
const wroteNothing = plan !== undefined && planHasNoChanges(data.diff, summaryOptions);
|
|
731
|
+
if (output && !wroteNothing) {
|
|
732
|
+
// The deploy response names every resource with its id; the plan the
|
|
733
|
+
// deploy was confirmed against is where each one's deployed state is.
|
|
734
|
+
// No heading: the success line that follows names the project and account.
|
|
735
|
+
this.log(formatPreview({
|
|
736
|
+
done: true,
|
|
737
|
+
diff: data.diff,
|
|
738
|
+
project,
|
|
739
|
+
verbose,
|
|
740
|
+
pruneRelations,
|
|
741
|
+
rendering: plan !== undefined ? { plan: plan.diff, local: projectPayload.resources } : undefined,
|
|
742
|
+
}));
|
|
290
743
|
}
|
|
291
|
-
|
|
292
|
-
|
|
744
|
+
await setTimeout(500);
|
|
745
|
+
// The checks Checkly marked with whether it scheduled them; none from an
|
|
746
|
+
// API that predates the marks.
|
|
747
|
+
const markedChecks = data.diff.filter(entry => entry.scheduled !== undefined);
|
|
748
|
+
if (wroteNothing) {
|
|
749
|
+
// Scheduling is the one thing such a deploy visibly does, so it is said.
|
|
750
|
+
// Without marks it is counted on what was sent and can be scheduled: a
|
|
751
|
+
// deploy that changed nothing schedules only under the `all` scope, a
|
|
752
|
+
// testOnly check is in the project but not in the deploy, and a
|
|
753
|
+
// heartbeat monitor waits for pings instead of running.
|
|
754
|
+
const heartbeats = project.getHeartbeatLogicalIds();
|
|
755
|
+
const scheduled = markedChecks.length > 0
|
|
756
|
+
? markedChecks.some(entry => entry.scheduled)
|
|
757
|
+
: (data.scheduled ?? scheduleOnDeploy)
|
|
758
|
+
&& scheduleScope === 'all'
|
|
759
|
+
&& Object.keys(projectBundle.data.check).some(logicalId => !heartbeats.includes(logicalId));
|
|
760
|
+
this.log(`Project "${project.name}" is up to date.${scheduled ? ' Checks were scheduled to run.' : ''}`);
|
|
293
761
|
}
|
|
294
|
-
|
|
295
|
-
await setTimeout(500);
|
|
762
|
+
else {
|
|
296
763
|
this.log(`Successfully deployed project "${project.name}" to account "${account.name}".`);
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
764
|
+
}
|
|
765
|
+
// Checkly schedules none of a deploy's checks when there are more than
|
|
766
|
+
// the threshold allows, which is worth a warning. Otherwise it may still
|
|
767
|
+
// leave some out, such as the ones that already run often; a notice
|
|
768
|
+
// lists those, kept short so that it does not push people into relaxing
|
|
769
|
+
// the limits. A deploy that asked for no scheduling hears about neither,
|
|
770
|
+
// and the checks a deploy left unchanged are what the scope leaves out
|
|
771
|
+
// by design, not something to report.
|
|
772
|
+
const notScheduled = scheduleOnDeploy
|
|
773
|
+
? markedChecks.filter(entry => entry.scheduled === false
|
|
774
|
+
&& entry.scheduleSkippedReason !== 'NOT_REQUESTED'
|
|
775
|
+
&& entry.scheduleSkippedReason !== 'UNCHANGED')
|
|
776
|
+
: [];
|
|
777
|
+
if (scheduleOnDeploy && data.scheduled === false) {
|
|
778
|
+
// Set apart from the line above, which ends without one. The blank
|
|
779
|
+
// line belongs to the warning, so it goes to stderr with it.
|
|
780
|
+
this.logToStderr();
|
|
781
|
+
this.style.longWarning('Checks were not scheduled', [
|
|
782
|
+
'This deploy would have scheduled more checks than the scheduling threshold allows.',
|
|
783
|
+
'',
|
|
784
|
+
'All checks will run at their next scheduled time.',
|
|
785
|
+
'',
|
|
786
|
+
'Helpful options:',
|
|
787
|
+
...scheduleScope === 'all'
|
|
788
|
+
? [
|
|
789
|
+
' --schedule-on-deploy-scope=changed',
|
|
790
|
+
' Only schedule the checks the deploy changed.',
|
|
791
|
+
'',
|
|
792
|
+
]
|
|
793
|
+
: [],
|
|
794
|
+
' --schedule-on-deploy-threshold=<number>',
|
|
795
|
+
' Change the threshold to a suitable number of checks.',
|
|
796
|
+
'',
|
|
797
|
+
' --schedule-on-deploy-min-frequency=<number>',
|
|
798
|
+
' Only schedule checks that run less often than the specified frequency',
|
|
799
|
+
' (in minutes), reducing the number of scheduled checks.',
|
|
800
|
+
'',
|
|
801
|
+
' For a full list of options, pass --help.',
|
|
802
|
+
].join('\n'));
|
|
803
|
+
}
|
|
804
|
+
else if (notScheduled.length > 0) {
|
|
805
|
+
this.logToStderr();
|
|
806
|
+
this.style.longInfo('Some checks were not scheduled', [
|
|
807
|
+
'The checks will run at their next scheduled time.',
|
|
808
|
+
'',
|
|
809
|
+
'Not scheduled:',
|
|
810
|
+
...Object.entries(countBy(notScheduled, entry => entry.scheduleSkippedReason ?? 'UNKNOWN'))
|
|
811
|
+
.map(([reason, count]) => `- ${describeNotScheduled(reason, count)}`),
|
|
812
|
+
].join('\n'));
|
|
813
|
+
}
|
|
814
|
+
// Print the ping URL for heartbeat checks. Awaited, so that the lines are
|
|
815
|
+
// part of the run's output. The deploy has been written by now: a failed
|
|
816
|
+
// fetch is a warning about that one check, never a failed deploy.
|
|
817
|
+
const heartbeatLogicalIds = project.getHeartbeatLogicalIds();
|
|
818
|
+
const heartbeatChecks = data.diff.filter(check => heartbeatLogicalIds.includes(check.logicalId));
|
|
819
|
+
for (const { logicalId, physicalId } of heartbeatChecks) {
|
|
820
|
+
try {
|
|
821
|
+
const { data: { pingUrl, name } } = await api.heartbeatCheck.get(physicalId);
|
|
303
822
|
this.log(`Ping URL of heartbeat check ${chalk.green(name)} is ${chalk.italic.underline.blue(pingUrl)}.`);
|
|
304
|
-
}
|
|
823
|
+
}
|
|
824
|
+
catch (err) {
|
|
825
|
+
this.style.longWarning(`The project was deployed, but the ping URL of heartbeat check "${logicalId}" could not be retrieved.`, err);
|
|
826
|
+
}
|
|
305
827
|
}
|
|
306
828
|
}
|
|
307
829
|
catch (err) {
|
|
308
|
-
|
|
309
|
-
|
|
830
|
+
this.style.actionFailure();
|
|
831
|
+
if (err instanceof DriftDetectedError) {
|
|
832
|
+
reportDrift(err.drift, 'Your Checkly account changed while this deploy was being prepared, and the current '
|
|
833
|
+
+ `plan would overwrite changes made in Checkly to ${resourceCount(err.drift.length)}, `
|
|
834
|
+
+ 'so nothing was deployed.');
|
|
310
835
|
}
|
|
311
|
-
if (err instanceof
|
|
836
|
+
else if (err instanceof ProjectPlanStaleError) {
|
|
837
|
+
// Nothing was written. The way out is another run, which previews
|
|
838
|
+
// afresh: this run's token describes a state Checkly has left behind,
|
|
839
|
+
// so sending it again would be refused again.
|
|
840
|
+
if (err.diff.length) {
|
|
841
|
+
// The current plan is the failure report's context: stderr.
|
|
842
|
+
this.logToStderr(formatPreview({
|
|
843
|
+
heading: { title: 'Current plan', projectName: project.name, accountName: account.name },
|
|
844
|
+
diff: err.diff,
|
|
845
|
+
project,
|
|
846
|
+
verbose,
|
|
847
|
+
pruneRelations,
|
|
848
|
+
}));
|
|
849
|
+
this.style.longError(
|
|
850
|
+
// A plan with nothing to apply was confirmed by nobody.
|
|
851
|
+
nothingToApply
|
|
852
|
+
? 'Your Checkly account changed after the plan found no changes, so nothing was deployed.'
|
|
853
|
+
: 'Your Checkly account changed while this deploy was being confirmed, so nothing was deployed.', 'The plan above is the current one. Re-run `checkly deploy` to review and deploy it.');
|
|
854
|
+
}
|
|
855
|
+
else {
|
|
856
|
+
// A refusal with no plan attached: the account moved for a reason the
|
|
857
|
+
// error itself explains, and there is nothing to print above.
|
|
858
|
+
this.style.longError(`${err.message} Nothing was deployed.`, 'Re-run `checkly deploy` to see the current plan and deploy it.');
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
else if (plan !== undefined && err instanceof ValidationError && err.data.code === DEPLOY_PLAN_DISABLED) {
|
|
862
|
+
// The plan was made, and plans were switched off before the deploy
|
|
863
|
+
// that applies it arrived. The refusal is worded for whoever sent a
|
|
864
|
+
// token; this run pinned its own.
|
|
865
|
+
this.style.longError('Checkly switched deploy plans off while this deploy was being prepared, so nothing was deployed.', requestedPlanToken !== undefined || pruneRelations
|
|
866
|
+
? 'Re-run the command without --plan-token and --prune-unmanaged-relations. '
|
|
867
|
+
+ 'While plans are switched off it deploys without one.'
|
|
868
|
+
: 'Re-run the command. While plans are switched off it deploys without one.');
|
|
869
|
+
}
|
|
870
|
+
else if (err instanceof ProjectDeployCancelledError) {
|
|
312
871
|
this.style.longError('Your deployment was cancelled.', err.message);
|
|
313
872
|
}
|
|
314
873
|
else if (err instanceof ConflictError) {
|
|
@@ -323,132 +882,34 @@ export default class Deploy extends AuthCommand {
|
|
|
323
882
|
this.exit(1);
|
|
324
883
|
}
|
|
325
884
|
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
885
|
+
}
|
|
886
|
+
function collectDeletions(diff) {
|
|
887
|
+
return diff
|
|
888
|
+
.filter(change => change.action === ResourceDeployStatus.DELETE
|
|
889
|
+
// A resource the project no longer declares, not a relation it never
|
|
890
|
+
// managed: pruning those is reported under its own heading.
|
|
891
|
+
&& change.origin !== 'unmanaged'
|
|
892
|
+
&& !NON_REPORTED_TYPES.some(t => t === change.type))
|
|
893
|
+
.map(({ type, logicalId }) => ({ resourceType: type, logicalId }))
|
|
894
|
+
.sort((a, b) => a.resourceType.localeCompare(b.resourceType) || a.logicalId.localeCompare(b.logicalId));
|
|
895
|
+
}
|
|
896
|
+
function countBy(items, key) {
|
|
897
|
+
const counts = {};
|
|
898
|
+
for (const item of items) {
|
|
899
|
+
counts[key(item)] = (counts[key(item)] ?? 0) + 1;
|
|
332
900
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
PrivateLocationCheckAssignment.__checklyType,
|
|
346
|
-
PrivateLocationGroupAssignment.__checklyType,
|
|
347
|
-
].some(t => t === type)) {
|
|
348
|
-
// Don't report changes to alert channel subscriptions or private location assignments.
|
|
349
|
-
// Users don't create these directly, so it's more intuitive to consider it as part of the check.
|
|
350
|
-
continue;
|
|
351
|
-
}
|
|
352
|
-
const construct = project.data[type][logicalId];
|
|
353
|
-
if (action === ResourceDeployStatus.UPDATE) {
|
|
354
|
-
updating.push({ resourceType: type, logicalId, physicalId, construct });
|
|
355
|
-
}
|
|
356
|
-
else if (action === ResourceDeployStatus.CREATE) {
|
|
357
|
-
creating.push({ resourceType: type, logicalId, physicalId, construct });
|
|
358
|
-
}
|
|
359
|
-
else if (action === ResourceDeployStatus.DELETE) {
|
|
360
|
-
// Since the resource is being deleted, the construct isn't in the project.
|
|
361
|
-
deleting.push({ resourceType: type, logicalId });
|
|
362
|
-
}
|
|
363
|
-
else if (action === ResourceDeployStatus.DETACHED) {
|
|
364
|
-
// Newer backends report detached resources explicitly. The construct
|
|
365
|
-
// isn't in the project since it was removed from code.
|
|
366
|
-
detaching.push({ resourceType: type, logicalId });
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
// testOnly checks weren't sent to the BE and won't be in previewData.
|
|
370
|
-
// We load them from the `project` instead.
|
|
371
|
-
const skipping = project
|
|
372
|
-
.getTestOnlyConstructs().map(construct => ({
|
|
373
|
-
logicalId: construct.logicalId,
|
|
374
|
-
resourceType: construct.type,
|
|
375
|
-
construct,
|
|
376
|
-
}))
|
|
377
|
-
// There is an edge case when the check already exists in Checkly, but `testOnly: true` was just added.
|
|
378
|
-
// In this case, the check will be included in both `deleting` and `skipping`.
|
|
379
|
-
// To avoid displaying the check twice, we detect this case and only show the check in `deleting`.
|
|
380
|
-
// This implementation is O(n^2), but could be sped up with a map or set.
|
|
381
|
-
.filter(skip => !deleting.find(deletion => deletion.logicalId === skip.logicalId && deletion.resourceType === skip.resourceType));
|
|
382
|
-
// Having some order will make the output easier to read.
|
|
383
|
-
const compareEntries = (a, b) => a.resourceType.localeCompare(b.resourceType)
|
|
384
|
-
|| a.logicalId.localeCompare(b.logicalId);
|
|
385
|
-
// filter resources without contructs that are created dynamically
|
|
386
|
-
// on the flight (i.e. a non project member private-location)
|
|
387
|
-
const sortedUpdating = updating
|
|
388
|
-
.filter(({ construct }) => Boolean(construct))
|
|
389
|
-
.sort(compareEntries);
|
|
390
|
-
// filter resources without contructs that are created dynamically
|
|
391
|
-
// on the flight (i.e. a non project member private-location)
|
|
392
|
-
const sortedCreating = creating
|
|
393
|
-
.filter(({ construct }) => Boolean(construct))
|
|
394
|
-
.sort(compareEntries);
|
|
395
|
-
const sortedDeleting = deleting
|
|
396
|
-
.sort(compareEntries);
|
|
397
|
-
const sortedDetaching = detaching
|
|
398
|
-
.sort(compareEntries);
|
|
399
|
-
if (!sortedCreating.length && !sortedDeleting.length && !sortedDetaching.length
|
|
400
|
-
&& !sortedUpdating.length && !skipping.length) {
|
|
401
|
-
return '\nNo checks were detected. More information on how to set up a Checkly CLI project is available at https://checklyhq.com/docs/cli/.\n';
|
|
402
|
-
}
|
|
403
|
-
const output = [];
|
|
404
|
-
if (sortedCreating.filter(({ construct }) => Boolean(construct)).length) {
|
|
405
|
-
output.push(chalk.bold.green('Create:'));
|
|
406
|
-
for (const { logicalId, physicalId, construct } of sortedCreating) {
|
|
407
|
-
output.push(` ${construct.constructor.name}: ${logicalId}`);
|
|
408
|
-
if (verbose && construct.name) {
|
|
409
|
-
output.push(` name: ${construct.name}`);
|
|
410
|
-
}
|
|
411
|
-
if (verbose && physicalId) {
|
|
412
|
-
output.push(` id: ${physicalId}`);
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
output.push('');
|
|
416
|
-
}
|
|
417
|
-
if (sortedDeleting.length) {
|
|
418
|
-
output.push(chalk.bold.red('Delete:'));
|
|
419
|
-
for (const { resourceType, logicalId } of sortedDeleting) {
|
|
420
|
-
output.push(` ${PRETTY_RESOURCE_TYPES[resourceType] ?? resourceType}: ${logicalId}`);
|
|
421
|
-
}
|
|
422
|
-
output.push('');
|
|
423
|
-
}
|
|
424
|
-
if (sortedDetaching.length) {
|
|
425
|
-
output.push(chalk.bold.yellow('Kept in your Checkly account (removed from code, now managed from the Checkly web app):'));
|
|
426
|
-
for (const { resourceType, logicalId } of sortedDetaching) {
|
|
427
|
-
output.push(` ${PRETTY_RESOURCE_TYPES[resourceType] ?? resourceType}: ${logicalId}`);
|
|
428
|
-
}
|
|
429
|
-
output.push('');
|
|
430
|
-
}
|
|
431
|
-
if (sortedUpdating.length) {
|
|
432
|
-
output.push(chalk.bold.magenta('Update and Unchanged:'));
|
|
433
|
-
for (const { logicalId, physicalId, construct } of sortedUpdating) {
|
|
434
|
-
output.push(` ${construct.constructor.name}: ${logicalId}`);
|
|
435
|
-
if (verbose && construct.name) {
|
|
436
|
-
output.push(` name: ${construct.name}`);
|
|
437
|
-
}
|
|
438
|
-
if (verbose && physicalId) {
|
|
439
|
-
output.push(` id: ${physicalId}`);
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
output.push('');
|
|
443
|
-
}
|
|
444
|
-
if (skipping.length) {
|
|
445
|
-
output.push(chalk.bold.grey('Skip (testOnly):'));
|
|
446
|
-
for (const { logicalId, construct } of skipping) {
|
|
447
|
-
output.push(` ${construct.constructor.name}: ${logicalId}`);
|
|
448
|
-
}
|
|
449
|
-
output.push('');
|
|
450
|
-
}
|
|
451
|
-
return output.join('\n');
|
|
901
|
+
return counts;
|
|
902
|
+
}
|
|
903
|
+
/** One line of the not-scheduled notice: how many checks a skip reason left out. */
|
|
904
|
+
function describeNotScheduled(reason, count) {
|
|
905
|
+
const checks = count === 1 ? '1 check' : `${count} checks`;
|
|
906
|
+
switch (reason) {
|
|
907
|
+
case 'MIN_FREQUENCY':
|
|
908
|
+
return `${checks} that ${count === 1 ? 'runs' : 'run'} more often than the minimum frequency allows`;
|
|
909
|
+
default:
|
|
910
|
+
// A reason this CLI does not know yet, from a newer Checkly API: named
|
|
911
|
+
// as the API reports it.
|
|
912
|
+
return `${checks} for another reason (${reason})`;
|
|
452
913
|
}
|
|
453
914
|
}
|
|
454
915
|
//# sourceMappingURL=deploy.js.map
|