From 1384b880244525dab8f2454c91b7ef1e66a73ff0 Mon Sep 17 00:00:00 2001 From: Huw Wilkins Date: Tue, 30 Jul 2024 15:13:23 +1000 Subject: [PATCH] ci: set up CI for UI --- .github/workflows/ui.yaml | 77 +++++++++++++++++++ tsconfig.json | 3 + ui/.eslintrc.cjs | 3 +- ui/.prettierrc | 1 + ui/package.json | 8 +- ui/renovate.json | 2 +- ui/src/App.tsx | 39 +++++----- ui/src/index.tsx | 2 +- ui/src/pages/identities/DeleteIdentityBtn.tsx | 3 +- ui/src/util/useLocalStorage.ts | 2 +- ui/tsconfig.json | 9 +-- ui/vitest.config.ts | 20 ++--- 12 files changed, 123 insertions(+), 46 deletions(-) create mode 100644 .github/workflows/ui.yaml create mode 100644 tsconfig.json create mode 100644 ui/.prettierrc diff --git a/.github/workflows/ui.yaml b/.github/workflows/ui.yaml new file mode 100644 index 000000000..b5d077c92 --- /dev/null +++ b/.github/workflows/ui.yaml @@ -0,0 +1,77 @@ +name: UI +on: + push: + branches: + - main + pull_request: + branches: + - main +jobs: + lint: + name: Lint + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [20.x] + steps: + - uses: actions/checkout@v4 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: "yarn" + cache-dependency-path: ui/yarn.lock + - name: Install + run: yarn --cwd ui install --immutable + - run: yarn --cwd ui lint-js + test: + name: Test + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [20.x] + steps: + - uses: actions/checkout@v4 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: "yarn" + cache-dependency-path: ui/yarn.lock + - name: Install + run: yarn --cwd ui install --immutable + - run: yarn --cwd ui test-js + build: + name: Build + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [20.x] + steps: + - uses: actions/checkout@v4 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: "yarn" + cache-dependency-path: ui/yarn.lock + - name: Install + run: yarn --cwd ui install --immutable + - run: yarn --cwd ui build + dotrun: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install dotrun + run: sudo pip3 install dotrun requests==2.31.0 # requests version is pinned to avoid breaking changes, can be removed once issue is resolved: https://github.com/docker/docker-py/issues/3256 + - name: Install dependencies + run: | + cd ui + sudo chmod -R 777 . + dotrun install + - name: Build assets + run: cd ui && dotrun build + - name: Run dotrun + run: | + cd ui && dotrun & + curl --head --fail --retry-delay 1 --retry 30 --retry-connrefused http://localhost:3000 diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..81d8941e7 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,3 @@ +{ + "references": [{ "path": "./ui" }] +} diff --git a/ui/.eslintrc.cjs b/ui/.eslintrc.cjs index df08d1bb4..def297e89 100644 --- a/ui/.eslintrc.cjs +++ b/ui/.eslintrc.cjs @@ -1,6 +1,6 @@ module.exports = { parser: "@typescript-eslint/parser", - plugins: ["@typescript-eslint", "react"], + plugins: ["@typescript-eslint", "react", "prettier"], globals: {}, env: { node: true, @@ -25,6 +25,7 @@ module.exports = { parserOptions: { project: "./tsconfig.json", sourceType: "module", + tsconfigRootDir: __dirname, ecmaFeatures: { jsx: true, }, diff --git a/ui/.prettierrc b/ui/.prettierrc new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/ui/.prettierrc @@ -0,0 +1 @@ +{} diff --git a/ui/package.json b/ui/package.json index 700daa0f3..44b9e0c64 100644 --- a/ui/package.json +++ b/ui/package.json @@ -7,12 +7,12 @@ "scripts": { "clean": "rm -rf node_modules yarn-error.log *.log build/ .bundle", "build": "npx vite build", - "format-js-eslint": "eslint 'src/**/*.{json,jsx,tsx,ts}' 'tests/**/*.ts' --fix", - "format-js-prettier": "prettier 'src/**/*.{json,jsx,tsx,ts}' 'tests/**/*.ts' --write", + "format-js-eslint": "eslint 'src/**/*.{json,jsx,tsx,ts}' --fix", + "format-js-prettier": "prettier 'src/**/*.{json,jsx,tsx,ts}' --write", "format-js": "yarn format-js-eslint && yarn format-js-prettier", "lint-scss": "stylelint 'src/**/*.scss'", - "lint-js-eslint": "eslint 'src/**/*.{json,tsx,ts}' 'tests/**/*.ts' .eslintrc.cjs babel.config.js", - "lint-js-prettier": "prettier 'src/**/*.{json,tsx,ts}' 'tests/**/*.ts' .eslintrc.cjs babel.config.js --check", + "lint-js-eslint": "eslint 'src/**/*.{json,tsx,ts}' .eslintrc.cjs babel.config.js", + "lint-js-prettier": "prettier 'src/**/*.{json,tsx,ts}' .eslintrc.cjs babel.config.js --check", "lint-js": "yarn lint-js-eslint && yarn lint-js-prettier", "hooks-add": "husky install", "hooks-remove": "husky uninstall", diff --git a/ui/renovate.json b/ui/renovate.json index a686a1e9a..8f66cdbb0 100644 --- a/ui/renovate.json +++ b/ui/renovate.json @@ -1,5 +1,5 @@ { "extends": [ - "github>canonical-web-and-design/renovate-websites" + "github>canonical/renovate-apps" ] } diff --git a/ui/src/App.tsx b/ui/src/App.tsx index 4ca8008bc..03d6a989a 100644 --- a/ui/src/App.tsx +++ b/ui/src/App.tsx @@ -3,7 +3,6 @@ import { Navigate, Route, Routes } from "react-router-dom"; import { ApplicationLayout } from "@canonical/react-components"; import { ReBACAdmin } from "@canonical/rebac-admin"; import Loader from "components/Loader"; -import Login from "components/Login"; import Logo from "components/Logo"; import Navigation from "components/Navigation"; import ClientList from "pages/clients/ClientList"; @@ -40,25 +39,25 @@ const App: FC = () => { > }> - } - /> - } /> - } /> - } /> - } /> - - } - /> - } /> + } + /> + } /> + } /> + } /> + } /> + + } + /> + } /> diff --git a/ui/src/index.tsx b/ui/src/index.tsx index 0fcafb450..49b18b31f 100644 --- a/ui/src/index.tsx +++ b/ui/src/index.tsx @@ -18,5 +18,5 @@ root.render( - + , ); diff --git a/ui/src/pages/identities/DeleteIdentityBtn.tsx b/ui/src/pages/identities/DeleteIdentityBtn.tsx index 3530675f8..9cca023e7 100644 --- a/ui/src/pages/identities/DeleteIdentityBtn.tsx +++ b/ui/src/pages/identities/DeleteIdentityBtn.tsx @@ -46,7 +46,8 @@ const DeleteIdentityBtn: FC = ({ identity }) => { title: "Confirm delete", children: (

- This will permanently delete identity {identity.traits?.email}. + This will permanently delete identity{" "} + {identity.traits?.email}.

), confirmButtonLabel: "Delete identity", diff --git a/ui/src/util/useLocalStorage.ts b/ui/src/util/useLocalStorage.ts index 6b365112a..0d790e162 100644 --- a/ui/src/util/useLocalStorage.ts +++ b/ui/src/util/useLocalStorage.ts @@ -9,7 +9,7 @@ function useLocalStorage( const [storedValue, setStoredValue] = useState(() => { try { const item = window.localStorage.getItem(key); - return item ? JSON.parse(item) : initialValue; + return item ? (JSON.parse(item) as V) : initialValue; } catch (error) { // Not shown in UI. Logged for debugging purposes. console.error("Unable to parse local storage:", error); diff --git a/ui/tsconfig.json b/ui/tsconfig.json index 4af39aaae..4c1d03207 100644 --- a/ui/tsconfig.json +++ b/ui/tsconfig.json @@ -1,14 +1,7 @@ { "compilerOptions": { "outDir": "./public/js/dist", - "baseUrl": ".", - "paths": { - "api/*": ["src/api/*"], - "components/*": ["src/components/*"], - "pages/*": ["src/pages/*"], - "types/*": ["src/types/*"], - "util/*": ["src/util/*"] - }, + "baseUrl": "src", "target": "ES2020", "module": "esnext", "jsx": "react-jsx", diff --git a/ui/vitest.config.ts b/ui/vitest.config.ts index c62b78712..5e6b4da04 100644 --- a/ui/vitest.config.ts +++ b/ui/vitest.config.ts @@ -1,13 +1,15 @@ import { mergeConfig, defineConfig } from "vitest/config"; import viteConfig from "./vite.config"; -export default mergeConfig( - viteConfig({ mode: "development" }), - defineConfig({ - test: { - environment: "jsdom", - globals: true, - include: ["./src/**/*.spec.{ts,tsx}"], - }, - }), +export default defineConfig((configEnv) => + mergeConfig( + viteConfig({ ...configEnv, mode: "development" }), + defineConfig({ + test: { + environment: "jsdom", + globals: true, + include: ["./src/**/*.{test,spec}.{ts,tsx}"], + }, + }), + ), );