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
65 changes: 65 additions & 0 deletions .github/workflows/studio-knip.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: Studio Dead Code (knip)

on:
push:
branches:
- master
paths:
- 'apps/studio/**'
- 'knip.jsonc'
- 'package.json'
- 'pnpm-lock.yaml'
- 'pnpm-workspace.yaml'
- '.github/workflows/studio-knip.yml'
# No `branches` filter: stacked PRs target a sibling branch, not master, and
# the gate should still run on them.
pull_request:
paths:
- 'apps/studio/**'
- 'knip.jsonc'
- 'package.json'
- 'pnpm-lock.yaml'
- 'pnpm-workspace.yaml'
- '.github/workflows/studio-knip.yml'

# Cancel old builds on new commit for same workflow + branch/PR
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
knip:
# Uses larger hosted runner as it significantly decreases build times
runs-on: blacksmith-4vcpu-ubuntu-2404
env:
NODE_OPTIONS: --max-old-space-size=6144

steps:
# No sparse-checkout: knip resolves the whole pnpm workspace graph, so it
# needs every workspace's package.json present even when scoped to studio.
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false

- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
name: Install pnpm
with:
run_install: false

- name: Use Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version-file: '.nvmrc'
cache: 'pnpm'

- name: Install deps
run: pnpm install --frozen-lockfile

# `symbols` keeps the readable table in the job log, `github-actions` adds
# the same findings as inline PR annotations.
- name: Run knip
run: pnpm knip --workspace apps/studio --no-progress --reporter symbols --reporter github-actions
1 change: 1 addition & 0 deletions apps/studio/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ Older Studio code predates some of these conventions. For new or modified code,
## Defaults that differ here

- **ESLint warnings are ratcheted in CI**: the per-rule occurrence count must not increase, so a new `any`, unresolved `exhaustive-deps` warning, or default export fails the build even though it's "only a warning". Check locally with `pnpm --filter studio run lint:ratchet`.
- **Dead files and deps are gated in CI** by knip (`pnpm knip --workspace apps/studio` locally). Framework-convention files nothing imports (routes, Vercel functions, TanStack Start files) belong in `knip.jsonc` under `workspaces["apps/studio"].entry`, not `ignore` — an ignored file's imports aren't traced, so anything only it uses gets reported as dead. There's no inline `knip-ignore` comment; the only per-file opt-out is config. In a PR stack, a file whose first consumer lands in a later PR fails the gate on the earlier one — either add it in the same PR as its first use, or add it to `workspaces["apps/studio"].ignore` with a `used from #NNN` comment and remove it in that PR.
- **Clipboard**: `copyToClipboard` from `'ui'`, and never `await` anything before calling it (Safari requires the write inside the user gesture; lint-enforced) — pass a Promise as the argument instead.
- **`useParams()` comes from `'common'`**, not `next/navigation` — it camelCases keys and returns `string | undefined`.
- **Permissions**: `useAsyncCheckPermissions` from `hooks/misc/useCheckPermissions` (returns `can: true` when self-hosted).
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Loading
Loading