diff --git a/.circleci/config.yml b/.circleci/config.yml index bf208573026..6beac901ce9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -34,7 +34,7 @@ commands: steps: - run: name: Build Docker image - command: docker build -f docker/Dockerfile -t app:build . + command: DOCKER_BUILDKIT=1 docker build -f docker/Dockerfile -t app:build . deploy-to-dockerhub: description: "Deploy to Docker Hub" @@ -100,21 +100,25 @@ jobs: javascript-tests: executor: name: node/default - # The Node version here must be kept in sync with that in `package.json`. - tag: '22.11.0' + # The Node version here should be compatible with `package.json` engines. + # Note: cimg/node requires at least a minor version (e.g., '22.0'), not just major version + tag: '22.0' steps: - checkout - - node/install-packages: - # `yarn install --frozen-lockfile` is run and cache is enabled by default for this orb configuration - pkg-manager: yarn - run: - command: yarn lint + name: Install pnpm + command: sudo corepack enable && corepack prepare pnpm@9.15.0 --activate + - run: + name: Install dependencies + command: pnpm install --frozen-lockfile + - run: + command: pnpm lint name: Run linting - run: - command: yarn markdownlint + command: pnpm markdownlint name: Check markdown linting - run: - command: yarn test:coverage + command: pnpm test:ci name: Run Jest tests - codecov/upload @@ -123,10 +127,6 @@ jobs: - image: 'cimg/python:3.10-node' steps: - checkout - - restore_cache: - name: Restore Yarn Package Cache - keys: - - node-deps-v1-{{ .Branch }} - run: pip install tox - run: command: tox -e docs diff --git a/.gitignore b/.gitignore index 9fa2a09e3d8..e3f602acfcf 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ treeherder_backup_* # Caches .eslintcache +.jest-cache # PyCharm *.iml # Perf sheriffing criteria diff --git a/.markdownlintignore b/.markdownlintignore index 9b541f55d02..b9f5af39e61 100644 --- a/.markdownlintignore +++ b/.markdownlintignore @@ -1,2 +1,4 @@ docs/index.md -node_modules \ No newline at end of file +node_modules +venv +CLAUDE.md \ No newline at end of file diff --git a/.npmrc b/.npmrc new file mode 100644 index 00000000000..06bbb7aaec6 --- /dev/null +++ b/.npmrc @@ -0,0 +1,17 @@ +# pnpm configuration for Treeherder + +# Equivalent to yarn's ignore-engines - don't check engine compatibility +engine-strict=false + +# Save exact versions instead of ranges when adding packages +save-exact=true + +# Don't run lifecycle scripts during install for security +ignore-scripts=true + +# Hoist all dependencies to node_modules root for compatibility +# This makes pnpm behavior similar to npm/yarn flat node_modules +shamefully-hoist=true + +# Auto-install peers to avoid peer dependency warnings +auto-install-peers=true diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 09448c62ff6..24dd0a6d994 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,10 +3,11 @@ repos: rev: v0.10.0.1 hooks: - id: shellcheck - - repo: https://github.com/pre-commit/mirrors-prettier - rev: v2.2.1 + - repo: https://github.com/biomejs/pre-commit + rev: v2.1.1 hooks: - - id: prettier + - id: biome-ci + additional_dependencies: ["@biomejs/biome@2.3.10"] - repo: https://github.com/igorshubovych/markdownlint-cli rev: v0.43.0 hooks: diff --git a/.prettierignore b/.prettierignore index 05de75329cb..58b5554cd97 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,5 +1,8 @@ # Ignore generated directories. .*/ +venv/ +node_modules/ +pnpm-lock.yaml # Ignore our legacy JS since it will be rewritten when converted to React. ui/js/ diff --git a/.yarnrc b/.yarnrc deleted file mode 100644 index 6b4da54605a..00000000000 --- a/.yarnrc +++ /dev/null @@ -1,20 +0,0 @@ -# Whilst in theory yarn's checking of the node/yarn version against the `engines` property -# in package.json is a great idea, in practice it causes unnecessary confusion/hassle for -# contributors, since most node/yarn versions will work fine with Treeherder anyway. -ignore-engines true - -# `--no-bin-links` is required when using Vagrant on Windows hosts (where symlinks aren't -# allowed), and so we include here to ensure that the package.json scripts aren't relying -# on symlinks that won't exist elsewhere. This alternate config form is required due to: -# https://github.com/yarnpkg/yarn/issues/4925 ---*.no-bin-links true - -# Don't run preinstall/install/postinstall hooks during yarn install, since: -# - most are not actually required -# - they often don't work with --no-bin-links (the bin scripts called may not exist) -# - they cause Yarn to "unplug" the package when using the "Plug and Play" feature -# - it's more secure to not run arbitrary code during package installation ---ignore-scripts true - -# Default to saving the exact package version in package.json and not a tilde version range. -save-exact true diff --git a/babel.config.json b/babel.config.json index 76acd15661c..89539187ba2 100644 --- a/babel.config.json +++ b/babel.config.json @@ -18,18 +18,7 @@ [ "@babel/preset-react", { - "development": true, - "useSpread": true - } - ] - ], - "plugins": [ - "@babel/plugin-syntax-dynamic-import", - "react-hot-loader/babel", - [ - "@babel/plugin-proposal-class-properties", - { - "loose": true + "runtime": "automatic" } ] ] diff --git a/biome.json b/biome.json new file mode 100644 index 00000000000..2801e064bfe --- /dev/null +++ b/biome.json @@ -0,0 +1,74 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.3.10/schema.json", + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true + }, + "files": { + "ignoreUnknown": true, + "includes": ["ui/**", "tests/ui/**"] + }, + "formatter": { + "enabled": false + }, + "javascript": { + "formatter": { + "quoteStyle": "single", + "trailingCommas": "all" + }, + "globals": ["page", "browser", "jestPuppeteer"] + }, + "css": { + "linter": { + "enabled": true + } + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "a11y": { + "useKeyWithClickEvents": "off", + "useSemanticElements": "off", + "noStaticElementInteractions": "off", + "useAriaPropsSupportedByRole": "off", + "useGenericFontNames": "off", + "noSvgWithoutTitle": "off" + }, + "complexity": { + "noUselessFragments": "off", + "useFlatMap": "off", + "noStaticOnlyClass": "off" + }, + "correctness": { + "noUnusedVariables": "error", + "noUnusedImports": "warn", + "noUnusedFunctionParameters": "off", + "useJsxKeyInIterable": "error", + "useExhaustiveDependencies": "off", + "noUnknownProperty": "off" + }, + "style": { + "noParameterAssign": "off", + "useDefaultParameterLast": "off", + "noNonNullAssertion": "off", + "useNodejsImportProtocol": "off" + }, + "suspicious": { + "noAlert": "off", + "noConsole": "off", + "noArrayIndexKey": "off", + "noImportAssign": "error", + "useIterableCallbackReturn": "off", + "noAsyncPromiseExecutor": "warn" + }, + "performance": { + "noAccumulatingSpread": "off" + } + } + }, + "assist": { + "enabled": false + } +} diff --git a/docker-compose.yml b/docker-compose.yml index 02ce9e1e2b2..bb0402e4d4a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -60,13 +60,13 @@ services: # https://hub.docker.com/_/node image: node:23.5.0-alpine3.20 # Installing JS dependencies at runtime so that they share the `node_modules` from the - # host, improving speed (both install and build due to the webpack cache) and ensuring + # host, improving speed (both install and build due to the rspack cache) and ensuring # the host copy stays in sync (for people that switch back and forth between UI-only # and full stack Treeherder development). working_dir: /app environment: BACKEND: http://backend:8000 - command: sh -c "yarn && yarn start --host 0.0.0.0" + command: sh -c "corepack enable && corepack prepare pnpm@9.15.0 --activate && pnpm install && pnpm start --host 0.0.0.0" volumes: - .:/app ports: diff --git a/docker/Dockerfile b/docker/Dockerfile index 7305fe49b80..9187ae2c966 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,14 +1,16 @@ ## Frontend stage -FROM node:22.11.0 AS frontend +FROM node:22-slim AS frontend WORKDIR /app +# Install pnpm +RUN corepack enable && corepack prepare pnpm@9.15.0 --activate + COPY ui/ /app/ui/ -COPY package.json babel.config.json webpack.config.js yarn.lock /app/ +COPY package.json rspack.config.js pnpm-lock.yaml .npmrc /app/ -RUN npm install -g --force yarn@1.22.22 -RUN yarn install -RUN yarn build +RUN pnpm install --frozen-lockfile +RUN pnpm build ## Backend stage @@ -38,7 +40,7 @@ RUN python manage.py collectstatic --noinput # WhiteNoise can then serve in preference to the originals. This is required # since WhiteNoise's Django storage backend only gzips assets handled by # collectstatic, and so does not affect files in the `.build/` directory -# since they are instead generated by webpack. +# since they are instead generated by rspack. RUN python -m whitenoise.compress .build RUN groupadd --gid 9500 treeherder && \ diff --git a/docs/backend_tasks.md b/docs/backend_tasks.md index 53d611309b7..52c3c307a26 100644 --- a/docs/backend_tasks.md +++ b/docs/backend_tasks.md @@ -16,8 +16,8 @@ docker-compose run backend bash ...which saves having to wait for docker-compose to spin up for every test run. -`yarn build` will generate a `.build` directory which will be seen within the `backend` container. -If you don't have `yarn` working on your host you can run this instead `docker-compose run frontend sh -c "yarn && yarn build"` +`pnpm build` will generate a `.build` directory which will be seen within the `backend` container. +If you don't have `pnpm` working on your host you can run this instead `docker-compose run frontend sh -c "corepack enable && pnpm install && pnpm build"` Then run the individual tools within that shell, like so: diff --git a/docs/biome-cleanup-todo.md b/docs/biome-cleanup-todo.md new file mode 100644 index 00000000000..6232391306f --- /dev/null +++ b/docs/biome-cleanup-todo.md @@ -0,0 +1,170 @@ +# Biome Code Cleanup TODO + +This document lists suggested code improvements identified during the Biome migration. Items are prioritized by impact and effort. + +## Priority 1: Quick Wins (Low effort, High value) + +### Fix Missing React Keys + +**Rule:** `useJsxKeyInIterable` +**Current:** warn +**Files:** + +- `ui/infra-compare/InfraCompareTable.jsx:74` - Add key to `
` +- `ui/infra-compare/InfraCompareTableControls.jsx:134` - Add key to `