diff --git a/.github/workflows/nodeci.yml b/.github/workflows/nodeci.yml new file mode 100644 index 0000000..a7772a1 --- /dev/null +++ b/.github/workflows/nodeci.yml @@ -0,0 +1,30 @@ +name: Node CI + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [16.x, 17.x, 18.x] + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version}} + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version}} + - name: Install + run: make install + - name: Run linter + run: make lint + # - name: Run tests + # run: make test diff --git a/Makefile b/Makefile index 1545a76..8128d20 100644 --- a/Makefile +++ b/Makefile @@ -9,3 +9,6 @@ start: deploy: git push heroku main + +lint-frontend: + make -C frontend lint diff --git a/frontend/.eslintignore b/frontend/.eslintignore new file mode 100644 index 0000000..de4d1f0 --- /dev/null +++ b/frontend/.eslintignore @@ -0,0 +1,2 @@ +dist +node_modules diff --git a/frontend/.eslintrc.yml b/frontend/.eslintrc.yml new file mode 100644 index 0000000..98ec1fc --- /dev/null +++ b/frontend/.eslintrc.yml @@ -0,0 +1,18 @@ +env: + browser: true + es2021: true +extends: + - eslint:recommended + - plugin:react/recommended + - airbnb-base +parserOptions: + ecmaFeatures: + jsx: true + ecmaVersion: latest + sourceType: module +plugins: + - react +rules: + import/extensions: 0 + no-console: 0 + diff --git a/frontend/Makefile b/frontend/Makefile index 63844c9..ee163cc 100644 --- a/frontend/Makefile +++ b/frontend/Makefile @@ -5,4 +5,8 @@ start: npm start build: - npm build \ No newline at end of file + npm build + +lint: + npx eslint . + diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 8539a94..583eefb 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -21,6 +21,11 @@ "sass": "^1.53.0", "web-vitals": "^2.1.4", "yup": "^0.32.11" + }, + "devDependencies": { + "eslint": "^8.20.0", + "eslint-config-airbnb": "^19.0.4", + "eslint-plugin-react": "^7.30.1" } }, "node_modules/@ampproject/remapping": { @@ -6489,9 +6494,9 @@ } }, "node_modules/eslint": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.18.0.tgz", - "integrity": "sha512-As1EfFMVk7Xc6/CvhssHUjsAQSkpfXvUGMFC3ce8JDe6WvqCgRrLOBQbVpsBFr1X1V+RACOadnzVvcUS5ni2bA==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.20.0.tgz", + "integrity": "sha512-d4ixhz5SKCa1D6SCPrivP7yYVi7nyD6A4vs6HIAul9ujBzcEmZVM3/0NN/yu5nKhmO1wjp5xQ46iRfmDGlOviA==", "dependencies": { "@eslint/eslintrc": "^1.3.0", "@humanwhocodes/config-array": "^0.9.2", @@ -6539,6 +6544,55 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint-config-airbnb": { + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz", + "integrity": "sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==", + "dev": true, + "dependencies": { + "eslint-config-airbnb-base": "^15.0.0", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5" + }, + "engines": { + "node": "^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.3", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-react": "^7.28.0", + "eslint-plugin-react-hooks": "^4.3.0" + } + }, + "node_modules/eslint-config-airbnb-base": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", + "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", + "dev": true, + "dependencies": { + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.2" + } + }, + "node_modules/eslint-config-airbnb-base/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/eslint-config-react-app": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-7.0.1.tgz", @@ -21280,9 +21334,9 @@ } }, "eslint": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.18.0.tgz", - "integrity": "sha512-As1EfFMVk7Xc6/CvhssHUjsAQSkpfXvUGMFC3ce8JDe6WvqCgRrLOBQbVpsBFr1X1V+RACOadnzVvcUS5ni2bA==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.20.0.tgz", + "integrity": "sha512-d4ixhz5SKCa1D6SCPrivP7yYVi7nyD6A4vs6HIAul9ujBzcEmZVM3/0NN/yu5nKhmO1wjp5xQ46iRfmDGlOviA==", "requires": { "@eslint/eslintrc": "^1.3.0", "@humanwhocodes/config-array": "^0.9.2", @@ -21397,6 +21451,37 @@ } } }, + "eslint-config-airbnb": { + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz", + "integrity": "sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==", + "dev": true, + "requires": { + "eslint-config-airbnb-base": "^15.0.0", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5" + } + }, + "eslint-config-airbnb-base": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", + "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", + "dev": true, + "requires": { + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, "eslint-config-react-app": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-7.0.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index 558d9a9..183db3e 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -41,5 +41,10 @@ "last 1 firefox version", "last 1 safari version" ] + }, + "devDependencies": { + "eslint": "^8.20.0", + "eslint-config-airbnb": "^19.0.4", + "eslint-plugin-react": "^7.30.1" } } diff --git a/frontend/src/locales/en.js b/frontend/src/locales/en.js index 4811997..9e4a763 100644 --- a/frontend/src/locales/en.js +++ b/frontend/src/locales/en.js @@ -34,7 +34,7 @@ export default { }, private: { header: 'Private page!', - message: 'Logged user: {{username}}' + message: 'Logged user: {{username}}', }, }, }; diff --git a/frontend/src/locales/ru.js b/frontend/src/locales/ru.js index 82b0c1f..73dd5e4 100644 --- a/frontend/src/locales/ru.js +++ b/frontend/src/locales/ru.js @@ -34,7 +34,7 @@ export default { }, private: { header: 'Скрытая страница!', - message: 'Авторизован пользователь: {{username}}' - } + message: 'Авторизован пользователь: {{username}}', + }, }, }; diff --git a/frontend/src/reportWebVitals.js b/frontend/src/reportWebVitals.js index 5253d3a..bb47dbb 100644 --- a/frontend/src/reportWebVitals.js +++ b/frontend/src/reportWebVitals.js @@ -1,6 +1,8 @@ -const reportWebVitals = onPerfEntry => { +const reportWebVitals = (onPerfEntry) => { if (onPerfEntry && onPerfEntry instanceof Function) { - import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { + import('web-vitals').then(({ + getCLS, getFID, getFCP, getLCP, getTTFB, + }) => { getCLS(onPerfEntry); getFID(onPerfEntry); getFCP(onPerfEntry); diff --git a/frontend/src/setupTests.js b/frontend/src/setupTests.js index 8f2609b..d75a53c 100644 --- a/frontend/src/setupTests.js +++ b/frontend/src/setupTests.js @@ -2,4 +2,5 @@ // allows you to do things like: // expect(element).toHaveTextContent(/react/i) // learn more: https://github.com/testing-library/jest-dom +// eslint-disable-next-line import/no-unresolved import '@testing-library/jest-dom';