Skip to content

Commit 7b9347b

Browse files
authored
chore: Add linter for typescript code (#45)
- Add and configure `eslint` - Add to build pipeline - Fix lint failures
1 parent 2654a93 commit 7b9347b

File tree

13 files changed

+1332
-36
lines changed

13 files changed

+1332
-36
lines changed

.eslintrc.yaml

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
---
2+
env:
3+
browser: true
4+
commonjs: true
5+
es6: true
6+
jest: true
7+
node: true
8+
extends:
9+
- eslint:recommended
10+
- plugin:@typescript-eslint/recommended
11+
- plugin:import/recommended
12+
- plugin:import/typescript
13+
- plugin:react/recommended
14+
- plugin:jsx-a11y/strict
15+
- plugin:compat/recommended
16+
- prettier
17+
parser: "@typescript-eslint/parser"
18+
parserOptions:
19+
ecmaVersion: 2018
20+
project:
21+
- "./tsconfig.json"
22+
- "./site/tsconfig.json"
23+
sourceType: module
24+
ecmaFeatures:
25+
jsx: true
26+
tsconfigRootDir: "./"
27+
plugins:
28+
- "@typescript-eslint"
29+
- import
30+
- react-hooks
31+
- jest
32+
- no-storage
33+
root: true
34+
rules:
35+
"@typescript-eslint/brace-style":
36+
["error", "1tbs", { "allowSingleLine": false }]
37+
"@typescript-eslint/camelcase": "off"
38+
"@typescript-eslint/explicit-function-return-type": "off"
39+
"@typescript-eslint/explicit-module-boundary-types": "error"
40+
"@typescript-eslint/method-signature-style": ["error", "property"]
41+
"@typescript-eslint/no-invalid-void-type": error
42+
# We're disabling the `no-namespace` rule to use a pattern of defining an interface,
43+
# and then defining functions that operate on that data via namespace. This is helpful for
44+
# dealing with immutable objects. This is a common pattern that shows up in some other
45+
# large TypeScript projects, like VSCode.
46+
# More details: https://github.com/coder/m/pull/9720#discussion_r697609528
47+
"@typescript-eslint/no-namespace": "off"
48+
"@typescript-eslint/no-unnecessary-boolean-literal-compare": error
49+
"@typescript-eslint/no-unnecessary-condition": warn
50+
"@typescript-eslint/no-unnecessary-type-assertion": warn
51+
"@typescript-eslint/no-unused-vars":
52+
- error
53+
- argsIgnorePattern: "^_"
54+
varsIgnorePattern: "^_"
55+
"@typescript-eslint/no-use-before-define": "off"
56+
"@typescript-eslint/object-curly-spacing": ["error", "always"]
57+
"@typescript-eslint/triple-slash-reference": "off"
58+
"brace-style": "off"
59+
"curly": ["error", "all"]
60+
eqeqeq: error
61+
import/default: "off"
62+
import/namespace: "off"
63+
import/newline-after-import:
64+
- error
65+
- count: 1
66+
import/no-named-as-default: "off"
67+
import/no-named-as-default-member: "off"
68+
import/prefer-default-export: "off"
69+
jest/no-focused-tests: "error"
70+
jsx-a11y/label-has-for: "off"
71+
jsx-a11y/no-autofocus: "off"
72+
no-console:
73+
- warn
74+
- allow:
75+
- warn
76+
- error
77+
- info
78+
- debug
79+
no-dupe-class-members: "off"
80+
no-restricted-imports:
81+
- error
82+
- paths:
83+
- name: "@material-ui/core"
84+
message:
85+
"Use path imports to avoid pulling in unused modules. See:
86+
https://material-ui.com/guides/minimizing-bundle-size/"
87+
- name: "@material-ui/icons"
88+
message:
89+
"Use path imports to avoid pulling in unused modules. See:
90+
https://material-ui.com/guides/minimizing-bundle-size/"
91+
- name: "@material-ui/styles"
92+
message:
93+
"Use path imports to avoid pulling in unused modules. See:
94+
https://material-ui.com/guides/minimizing-bundle-size/"
95+
- name: "@material-ui/core/Tooltip"
96+
message: "Use the custom Tooltip on componens/Tooltip"
97+
no-storage/no-browser-storage: error
98+
no-unused-vars: "off"
99+
"object-curly-spacing": "off"
100+
react-hooks/exhaustive-deps: warn
101+
react-hooks/rules-of-hooks: error
102+
react/jsx-no-script-url:
103+
- error
104+
- - name: Link
105+
props:
106+
- to
107+
- name: Button
108+
props:
109+
- href
110+
- name: IconButton
111+
props:
112+
- href
113+
react/prop-types: "off"
114+
react/jsx-boolean-value: ["error", "never"]
115+
react/jsx-curly-brace-presence:
116+
- error
117+
- children: ignore
118+
settings:
119+
react:
120+
version: detect
121+
import/resolver:
122+
typescript: {}

.github/workflows/coder.yaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,28 @@ jobs:
3838
with:
3939
version: latest
4040

41+
style-lint-typescript:
42+
name: "style/lint/typescript"
43+
runs-on: ubuntu-latest
44+
steps:
45+
- name: Checkout
46+
uses: actions/checkout@v2
47+
48+
- name: Cache Node
49+
id: cache-node
50+
uses: actions/cache@v2
51+
with:
52+
path: |
53+
**/node_modules
54+
.eslintcache
55+
key: js-${{ runner.os }}-test-${{ hashFiles('**/yarn.lock') }}
56+
57+
- name: Install node_modules
58+
run: yarn install
59+
60+
- name: "yarn lint"
61+
run: yarn lint
62+
4163
gen:
4264
name: "style/gen"
4365
runs-on: ubuntu-latest

jest-runner.eslint.config.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Toggle eslint --fix by specifying the `FIX` env.
2+
const fix = !!process.env.FIX
3+
4+
module.exports = {
5+
cliOptions: {
6+
ext: [".js", ".ts", ".tsx"],
7+
ignorePath: ".eslintignore",
8+
cache: false,
9+
fix,
10+
resolvePluginsRelativeTo: ".",
11+
maxWarnings: 0,
12+
},
13+
}

jest.config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ module.exports = {
1313
testPathIgnorePatterns: ["/node_modules/", "/__tests__/fakes"],
1414
moduleDirectories: ["node_modules", "<rootDir>"],
1515
},
16+
{
17+
displayName: "lint",
18+
runner: "jest-runner-eslint",
19+
testMatch: ["<rootDir>/site/**/*.js", "<rootDir>/site/**/*.ts", "<rootDir>/site/**/*.tsx"],
20+
testPathIgnorePatterns: ["/.next/", "/out/"],
21+
},
1622
],
1723
collectCoverageFrom: [
1824
"<rootDir>/site/**/*.js",

package.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
"export": "next export site",
1111
"format:check": "prettier --check '**/*.{css,html,js,json,jsx,md,ts,tsx,yaml,yml}'",
1212
"format:write": "prettier --write '**/*.{css,html,js,json,jsx,md,ts,tsx,yaml,yml}' && sql-formatter -l postgresql ./database/query.sql -o ./database/query.sql",
13+
"lint": "jest --selectProjects lint",
14+
"lint:fix": "FIX=true yarn lint",
1315
"test": "jest --selectProjects test",
1416
"test:coverage": "jest --selectProjects test --collectCoverage"
1517
},
@@ -24,9 +26,23 @@
2426
"@types/react": "17.0.38",
2527
"@types/react-dom": "17.0.11",
2628
"@types/superagent": "4.1.14",
29+
"@typescript-eslint/eslint-plugin": "4.33.0",
30+
"@typescript-eslint/parser": "4.33.0",
31+
"eslint": "7.32.0",
32+
"eslint-config-prettier": "8.3.0",
33+
"eslint-import-resolver-alias": "1.1.2",
34+
"eslint-import-resolver-typescript": "2.5.0",
35+
"eslint-plugin-compat": "4.0.1",
36+
"eslint-plugin-import": "2.25.4",
37+
"eslint-plugin-jest": "25.7.0",
38+
"eslint-plugin-jsx-a11y": "6.5.1",
39+
"eslint-plugin-no-storage": "1.0.2",
40+
"eslint-plugin-react": "7.28.0",
41+
"eslint-plugin-react-hooks": "4.3.0",
2742
"express": "4.17.2",
2843
"http-proxy-middleware": "2.0.1",
2944
"jest": "27.4.7",
45+
"jest-runner-eslint": "1.0.0",
3046
"next": "12.0.7",
3147
"prettier": "2.5.1",
3248
"react": "17.0.2",

site/components/EmptyState/index.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { screen } from "@testing-library/react"
22
import { render } from "../../test_helpers"
33
import React from "react"
4-
import { EmptyState, EmptyStateProps } from "./index"
4+
import { EmptyState } from "./index"
55

66
describe("EmptyState", () => {
77
it("renders (smoke test)", async () => {

site/components/Icons/index.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import React from "react"
2-
import { SvgIcon } from "@material-ui/core"
2+
import SvgIcon from "@material-ui/core/SvgIcon"
33
import { render } from "./../../test_helpers"
44

55
import * as Icons from "./index"
66

77
const getAllIcons = (): [string, typeof SvgIcon][] => {
88
let k: keyof typeof Icons
9-
let ret: [string, typeof SvgIcon][] = []
9+
const ret: [string, typeof SvgIcon][] = []
1010
for (k in Icons) {
1111
ret.push([k, Icons[k]])
1212
}

site/components/Navbar/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React from "react"
2+
import Button from "@material-ui/core/Button"
3+
import List from "@material-ui/core/List"
4+
import ListSubheader from "@material-ui/core/ListSubheader"
25
import { makeStyles } from "@material-ui/core/styles"
3-
import { Button, List, ListSubheader } from "@material-ui/core"
46

57
import Link from "next/link"
68

site/next.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ module.exports = {
1010
// Allows us to import TS files from outside product/coder/site.
1111
externalDir: true,
1212
},
13-
webpack: (config, { dev, isServer, webpack }) => {
13+
webpack: (config, { isServer, webpack }) => {
1414
// Inject CODERD_HOST environment variable for clients
1515
if (!isServer) {
1616
config.plugins.push(

site/pages/_app.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import React from "react"
2-
32
import CssBaseline from "@material-ui/core/CssBaseline"
3+
import { makeStyles } from "@material-ui/core/styles"
44
import ThemeProvider from "@material-ui/styles/ThemeProvider"
55

66
import { dark } from "../theme"
77
import { AppProps } from "next/app"
8-
import { makeStyles } from "@material-ui/core"
98
import { Navbar } from "../components/Navbar"
109
import { Footer } from "../components/Page"
1110

@@ -64,7 +63,7 @@ const MyApp: React.FC<AppProps> = (appProps) => {
6463
)
6564
}
6665

67-
const useStyles = makeStyles((theme) => ({
66+
const useStyles = makeStyles(() => ({
6867
root: {
6968
display: "flex",
7069
flexDirection: "column",

site/pages/index.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React from "react"
2-
import { makeStyles, Box, Paper } from "@material-ui/core"
3-
import { AddToQueue as AddWorkspaceIcon } from "@material-ui/icons"
2+
import Box from "@material-ui/core/Box"
3+
import { makeStyles } from "@material-ui/core/styles"
4+
import Paper from "@material-ui/core/Paper"
5+
import AddWorkspaceIcon from "@material-ui/icons/AddToQueue"
46

57
import { EmptyState, SplitButton } from "../components"
68

site/theme/theme.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ import { CustomPalette, darkPalette, lightPalette } from "./palettes"
44
import { typography } from "./typography"
55

66
const makeTheme = (palette: CustomPalette) => {
7-
// Grab defaults to re-use in overrides
8-
const { breakpoints } = createMuiTheme()
9-
107
return createMuiTheme({
118
palette,
129
typography,

0 commit comments

Comments
 (0)