feat(compute): watch paths — which pushes redeploy a service

Merged
FE
2mo ago
+102-9

Companion docs PR: InsForge/insta-skills#83 (insta-cli AGENTS.md #4 — flag changes are mirrored in skills/insta/cli-reference.md).

Platform side is shipped and live: insta-platform#399.

What this adds

insta compute watch-paths [service]                       # print them
insta compute watch-paths --set 'apps/web/**,packages/ui/**'
insta compute watch-paths --clear
insta compute connect-repo <owner/repo> --watch-paths 'apps/web/**'

--set PATCHes; it does not reconnect. Watch paths do not change what a build produces, so changing them must not rebuild the service — and connect-repo would. This is also why the CLI had no way to express the change before: there was no PATCH-shaped command on the source at all (which is why --repo-branch, --root-dir and --no-auto-deploy still cost a rebuild today; not this PR's job).

insta compute repo names the patterns, because they change what "every push to main redeploys it" means. The line distinguishes the three cases: they narrow a push that would deploy, they are stored but inert where nothing deploys on a push at all (public repo, auto-deploy off), or there are none.

The two shapes that would lie, and don't

  • The printed line carries root_dir and the patterns, which are anchored to different roots. It now says so — (apps/api/) — … only when a push changes these repo-root paths: src/** — because a service with root_dir: apps/api whose owner reads src/** as apps/api/src/** would silently stop deploying. Both the help strings and this line say REPOSITORY ROOT for the same reason.
  • --clear used to be documented as "back on every push" and the appended clause read "…deploys are manual (pushes do not redeploy), but only when it changes X" on a public repo. Both are false where a push cannot redeploy at all. The help says "every push that deploys this service", and the line says the patterns are stored but cannot apply.

Encoding

--set takes one comma-separated argument, because a shell expands an unquoted apps/web/** into filenames. The price is that a pattern containing a comma is unexpressible; the comment says so. An empty list is refused locally rather than sent: [] means no patterns to the server, which is the opposite of what --set was asked for — and --watch-paths '' from an unset shell variable would otherwise have connected the repo with no filter at all (that one was a truthiness test, now !== undefined, and it is pinned).

Validation stays server-side — the platform already strips a leading ./, refuses {} braces and an all-exclusions list, and caps 50 patterns / 200 characters — so the CLI does not duplicate any of it. One gap I am not closing here and have filed no workaround for: a non-empty input that normalizes to nothing server-side (--set './') is coerced to null, i.e. read as a clear. That is the platform's to refuse, and I am fixing it there rather than reimplementing the normalizer in the CLI.

Tests

Pure helpers, as this file already does: parseWatchPaths (splitting, trimming, the empty refusal), sourceBody (rides along only when given, and the empty-string case), and repoLine across the reachable public × auto_deploy × watch_paths grid — including the root_dir combination above. computeWatchPaths' --set-with---clear and empty---set guards throw before any network or config access, following test/volume.test.ts's precedent for exactly that.

Four mutation checks, each reddening: allowing --set with --clear, letting an empty --watch-paths vanish, restoring the root ambiguity, and never mutating at all. npm run typecheck, npm run build and 858 tests clean.


Summary by cubic

Adds insta compute watch-paths to show, set, or clear which repo paths trigger a redeploy, and --watch-paths on connect-repo to set them at connect time. compute repo now prints the active patterns, since they change what "every push redeploys it" means.

New Features

  • --set PATCHes the source instead of reconnecting, so changing watch paths never rebuilds the service.
  • Patterns are anchored to the repo root, not the service's root_dir; the output line says so to avoid silently narrowing deploys.
  • --set takes one comma-separated argument because an unquoted apps/web/** would be expanded by the shell; empty lists are refused locally.
  • When a push can't redeploy at all (public repo, auto-deploy off), the output says the patterns are stored but cannot apply rather than implying they'd trigger a deploy.