Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,23 @@ All paths below are relative to `packages/cli/`.

- [ ] `src/constructs/__tests__/{name}-alert-channel.spec.ts` — Unit tests covering: construct instantiation, `synthesize()` output structure, property mapping, and `describe()`. Follow existing alert channel tests as template.

## Phase 5: Build and Verify
## Phase 5: AI Context (modify existing files)

- [ ] `pnpm --filter checkly run prepare` — Rebuild.
Unlike monitors (one reference file each), all alert channels share a single reference. Add the new channel to it rather than creating a new file.

- [ ] `src/ai-context/context.fixtures.json` — Add an alert channel fixture entry (`logicalId: 'example-{name}-alert-channel'` plus a `config` block of the channel's properties). This is the source that `import plan` turns into a generated example config under `gen/resources/alert-channels/{name}/`. Follow the existing `example-email-alert-channel` / `example-slack-alert-channel` entries.

- [ ] `src/ai-context/context.ts`:
1. Add an `{UPPER_NAME}_ALERT_CHANNEL` entry to `EXAMPLE_CONFIGS` with a `templateString` of `<!-- EXAMPLE: {UPPER_NAME}_ALERT_CHANNEL -->`, the `exampleConfigPath` pointing at the generated `resources/alert-channels/{name}/...check.ts`, and the docs `reference` URL. Mirror the `SLACK_ALERT_CHANNEL` entry.
2. Update the `configure-alert-channels` entry in the `REFERENCES` array — extend its `description` to mention the new channel's class name.

- [ ] `src/ai-context/references/configure-alert-channels.md` — Add a short section documenting the new channel and an `<!-- EXAMPLE: {UPPER_NAME}_ALERT_CHANNEL -->` marker where the generated example should be injected. Follow the existing channel sections.

## Phase 6: Build and Verify

- [ ] `pnpm --filter checkly run prepare` — Rebuild (compiles TS + regenerates AI context).
- [ ] `pnpm --filter checkly test` — Run unit tests.
- [ ] `pnpm run sync:skills` — Sync AI context to published skills (from repo root).
- [ ] `pnpm lint:fix` — Fix formatting (run from repo root).

## Naming Conventions
Expand All @@ -63,3 +76,6 @@ All paths below are relative to `packages/cli/`.
| Props interface | `{Name}AlertChannelProps` | `TelegramAlertChannelProps` |
| Webhook type | `WEBHOOK_{UPPER_NAME}` | `WEBHOOK_TELEGRAM` |
| Codegen class | `{Name}AlertChannelCodegen` | `TelegramAlertChannelCodegen` |
| AI context reference | shared `configure-alert-channels.md` | (one file for all channels) |
| AI context example | `{UPPER_NAME}_ALERT_CHANNEL` | `SLACK_ALERT_CHANNEL` |
| Example fixture id | `example-{name}-alert-channel` | `example-slack-alert-channel` |
83 changes: 83 additions & 0 deletions .claude/commands/checkly-cli-update-dependencies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Update Dependencies

**Input:** $ARGUMENTS

Update the monorepo's dependencies (including devDependencies) to the latest versions that remain compatible with our supported Node range. Optionally interpret `$ARGUMENTS` as a scope hint (e.g. specific package names, "dry run" to only report, or "cli only"). With no arguments, survey and update everything eligible across all workspace packages.

The guiding rule: **never raise our minimum supported Node version as a side effect of a dependency bump.** We are on the stable 8.x line; dropping Node 20 would be a breaking (v9) change, so a dependency whose newest version requires a higher Node than our floor must be held back to its latest still-compatible version.

All paths below are relative to the repo root unless noted otherwise.

## Phase 0: Determine the Node floor

- [ ] Read `engines.node` from `packages/cli/package.json` and `packages/create-cli/package.json`. They should match. The current value is `^20.19.0 || >=22.12.0`, so the **minimum supported runtime is Node 20.19.0** — this is the version every dependency must remain installable on.
- [ ] Set `FLOOR` to that minimum (e.g. `20.19.0`). Do not hardcode it from this doc — read it live, since a future major may change it.

## Phase 1: Survey what is outdated

- [ ] Run `pnpm outdated -r` to list outdated direct dependencies across all workspace packages.

## Phase 2: Choose target versions (compatibility-aware)

For each outdated package, pick the **latest version whose `engines.node` still satisfies `FLOOR`** — which may be the latest overall, or an older version if the newest major dropped support for our floor. Use this helper to compute it (requires the `semver` already installed under the CLI package):

```bash
# Prints the latest non-prerelease version of each package compatible with FLOOR.
FLOOR=20.19.0 # read this from engines.node, do not assume
SEMVER=$(ls -d node_modules/.pnpm/semver@* | head -1)
for p in "PACKAGE_NAME_1" "PACKAGE_NAME_2"; do
enc=$(echo "$p" | sed 's#/#%2f#')
curl -s "https://registry.npmjs.org/$enc" | \
SEMVERDIR="$PWD/$SEMVER" PKG="$p" FLOOR="$FLOOR" node -e '
const semver=require(process.env.SEMVERDIR+"/node_modules/semver");
let d="";process.stdin.on("data",c=>d+=c).on("end",()=>{
const j=JSON.parse(d), floor=process.env.FLOOR, ok=[];
for(const [v,m] of Object.entries(j.versions)){
if(semver.prerelease(v)) continue;
const e=m.engines&&m.engines.node;
if(!e || semver.satisfies(floor,e)) ok.push(v);
}
ok.sort(semver.rcompare);
console.log(process.env.PKG+": latest compatible = "+(ok[0]||"NONE"));
});'
done
```

- [ ] For every outdated package, decide its target version with the helper above. If the latest compatible version is below the latest published version, **note the gap and the reason** (newer major requires Node > our floor).

### Mandatory exclusions — do NOT update these

- [ ] **`@types/node`** — leave it untouched. We deliberately keep it *behind* latest to stay aligned with our **minimum** supported Node version. Typing against a newer Node than our floor would let code use runtime APIs that don't exist on the oldest Node we support. Pin it near our minimum Node major, not at latest.
- [ ] **`vitest`** — do not move to v4. As of this writing, vitest 4 has incompatibilities with our setup and cannot be adopted yet. Updates *within the current major* (3.x) are fine; the jump to 4.x is blocked until the incompatibilities are resolved. Re-evaluate periodically.

If `$ARGUMENTS` explicitly asks to update one of these, stop and confirm with the user, explaining the above before proceeding.

## Phase 3: Apply the updates

- [ ] Apply the chosen versions. For packages going to their latest compatible version use, e.g.:
```bash
pnpm update -r --latest <pkgA> <pkgB> ...
```
- [ ] For packages where the latest compatible version is **not** the latest published (held-back majors), pin the explicit range instead so `--latest` doesn't overshoot:
```bash
pnpm add -w -D "<pkg>@^<compatible-version>" # -w for root devDeps; target the owning package otherwise
```
- [ ] Confirm the resulting `package.json` ranges and `pnpm-lock.yaml` reflect the intended versions, and that the excluded packages (`@types/node`, `vitest`) are unchanged.

## Phase 4: Verify

Run the full local pipeline and confirm each step is green before reporting success:

- [ ] **Build both packages:** `pnpm --filter checkly run prepare:dist` and `pnpm --filter create-checkly run prepare`
- [ ] **Lint:** `pnpm lint`
- [ ] **Commitlint smoke test** (it has a Node floor of its own — proves the held-back versions still work):
`echo "feat: x" | pnpm exec commitlint` (accepts) and `echo "nope" | pnpm exec commitlint` (rejects)
- [ ] **Unit tests:** `pnpm --filter checkly test` and `pnpm --filter create-checkly exec vitest --run`
- [ ] **Re-confirm the Node floor:** for every changed package, read `engines.node` from its installed copy under `node_modules/.pnpm/<pkg>@<ver>/node_modules/<pkg>/package.json` and verify it satisfies `FLOOR`. There should be no `engines` warnings during install.

## Phase 5: Report

- [ ] Summarize in a table with these columns: **Package**, **Type** (`dependency` or `devDependency` — list whichever it is in the manifest), **Owning package** (`checkly`, `create-checkly`, or root), **From → To**, and **Notes**.
- [ ] In the same report, call out separately what was **held back** and why (which major dropped our Node floor), and the **intentional exclusions** (`@types/node`, `vitest`).
- [ ] State the verification results plainly (build/lint/tests pass, no engine warnings).
- [ ] Do not commit or open a PR unless asked. If asked, use a `chore(deps):` conventional-commit subject and spell out the held-back/excluded packages in the body and PR description.
26 changes: 19 additions & 7 deletions .github/workflows/check-ai-context.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ on:
branches:
- main
- next/*
paths:
- "packages/cli/**"

jobs:
check-ai-context:
Expand All @@ -15,19 +13,33 @@ jobs:
pull-requests: write
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v5
# Path filtering is done inside the job (not via an `on:` paths filter) so
# this required check always runs and reports a status. A workflow skipped
# by an `on:` paths filter stays "pending" forever and blocks merge.
- uses: dorny/paths-filter@v3
id: changes
with:
filters: |
cli:
- 'packages/cli/**'
- if: steps.changes.outputs.cli == 'true'
uses: pnpm/action-setup@v5
with:
version: 10
- uses: actions/setup-node@v4
- if: steps.changes.outputs.cli == 'true'
uses: actions/setup-node@v4
with:
node-version: '20.x'
cache: "pnpm"
- run: pnpm install --frozen-lockfile
- run: pnpm run sync:skills
- if: steps.changes.outputs.cli == 'true'
run: pnpm install --frozen-lockfile
- if: steps.changes.outputs.cli == 'true'
run: pnpm run sync:skills
- name: Check for uncommitted changes in skills/
if: steps.changes.outputs.cli == 'true'
run: git diff --exit-code skills/
- name: Comment on PR if skills/ is out of date
if: failure()
if: failure() && steps.changes.outputs.cli == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ The core abstraction is the `Construct` base class (`src/constructs/construct.ts

`Session` is a static class on `Project` that carries global context during check file loading: the current project, available runtimes, check defaults, file loaders, and the path of the currently-loading check file.

To add a new construct, use `/new-monitor` or `/new-alert-channel` for step-by-step checklists.
To add a new construct, use `/checkly-cli-new-monitor` or `/checkly-cli-new-alert-channel` for step-by-step checklists. To update the monorepo's dependencies within the supported Node range, use `/checkly-cli-update-dependencies`.

### Check discovery and loading

Expand Down
Loading