From 655bb77d3b6528e5f2cd322cb9724b3353228b07 Mon Sep 17 00:00:00 2001 From: Melissa Avery-Weir Date: Thu, 27 Jun 2024 23:56:43 -0400 Subject: [PATCH] WAT-4: Initial code analysis config --- .env.production | 2 +- .eslintrc.js | 29 --------- .gitignore | 2 + .pre-commit-config.yaml | 14 +++++ .secrets.baseline | 127 +++++++++++++++++++++++++++++++++++++++ CodeAnalysisJenkinsfile | 94 +++++++++++++++++++++++++++++ eslint.config.mjs | 45 ++++++++++++++ package-lock.json | 65 +++++++++++++++++--- package.json | 5 +- requirements.txt | 2 + sonar-project.properties | 3 + src/api/plexApi.js | 3 +- src/index.html | 2 +- 13 files changed, 351 insertions(+), 42 deletions(-) delete mode 100644 .eslintrc.js create mode 100644 .pre-commit-config.yaml create mode 100644 .secrets.baseline create mode 100644 CodeAnalysisJenkinsfile create mode 100644 eslint.config.mjs create mode 100644 requirements.txt create mode 100644 sonar-project.properties diff --git a/.env.production b/.env.production index fdd3ebb..40732d0 100644 --- a/.env.production +++ b/.env.production @@ -1 +1 @@ -BASE_RSS_FEED=https://example.com \ No newline at end of file +BASE_RSS_FEED=https://rss.plex.tv/ \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 98aa123..0000000 --- a/.eslintrc.js +++ /dev/null @@ -1,29 +0,0 @@ -module.exports = { - env: { - browser: true, - es2021: true, - }, - extends: [ - 'airbnb-base', - 'plugin:sonarjs/recommended', - 'plugin:react-hooks/recommended', - 'plugin:@tanstack/eslint-plugin-query/recommended' - ], - overrides: [ - { - env: { - node: true, - }, - files: ['.eslintrc.{js,cjs}'], - parserOptions: { - sourceType: 'script', - }, - }, - ], - parserOptions: { - ecmaVersion: 'latest', - sourceType: 'module', - }, - rules: {}, - ignorePatterns: ['**/libs/*.js', 'node_modules/**', 'env/**'], -}; diff --git a/.gitignore b/.gitignore index c6bba59..ea9fa00 100644 --- a/.gitignore +++ b/.gitignore @@ -128,3 +128,5 @@ dist .yarn/build-state.yml .yarn/install-state.gz .pnp.* + +.vscode \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..59c9db7 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,14 @@ +# .pre-commit-config.yaml +repos: + - repo: https://github.com/Yelp/detect-secrets + rev: v1.5.0 + hooks: + - id: detect-secrets + args: ['--baseline', '.secrets.baseline'] + exclude: package.lock.json + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 # Use the ref you want to point at + hooks: + - id: trailing-whitespace + - id: check-json + #- id: check-yaml diff --git a/.secrets.baseline b/.secrets.baseline new file mode 100644 index 0000000..bdc9990 --- /dev/null +++ b/.secrets.baseline @@ -0,0 +1,127 @@ +{ + "version": "1.5.0", + "plugins_used": [ + { + "name": "ArtifactoryDetector" + }, + { + "name": "AWSKeyDetector" + }, + { + "name": "AzureStorageKeyDetector" + }, + { + "name": "Base64HighEntropyString", + "limit": 4.5 + }, + { + "name": "BasicAuthDetector" + }, + { + "name": "CloudantDetector" + }, + { + "name": "DiscordBotTokenDetector" + }, + { + "name": "GitHubTokenDetector" + }, + { + "name": "GitLabTokenDetector" + }, + { + "name": "HexHighEntropyString", + "limit": 3.0 + }, + { + "name": "IbmCloudIamDetector" + }, + { + "name": "IbmCosHmacDetector" + }, + { + "name": "IPPublicDetector" + }, + { + "name": "JwtTokenDetector" + }, + { + "name": "KeywordDetector", + "keyword_exclude": "" + }, + { + "name": "MailchimpDetector" + }, + { + "name": "NpmDetector" + }, + { + "name": "OpenAIDetector" + }, + { + "name": "PrivateKeyDetector" + }, + { + "name": "PypiTokenDetector" + }, + { + "name": "SendGridDetector" + }, + { + "name": "SlackDetector" + }, + { + "name": "SoftlayerDetector" + }, + { + "name": "SquareOAuthDetector" + }, + { + "name": "StripeDetector" + }, + { + "name": "TelegramBotTokenDetector" + }, + { + "name": "TwilioKeyDetector" + } + ], + "filters_used": [ + { + "path": "detect_secrets.filters.allowlist.is_line_allowlisted" + }, + { + "path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies", + "min_level": 2 + }, + { + "path": "detect_secrets.filters.heuristic.is_indirect_reference" + }, + { + "path": "detect_secrets.filters.heuristic.is_likely_id_string" + }, + { + "path": "detect_secrets.filters.heuristic.is_lock_file" + }, + { + "path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string" + }, + { + "path": "detect_secrets.filters.heuristic.is_potential_uuid" + }, + { + "path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign" + }, + { + "path": "detect_secrets.filters.heuristic.is_sequential_string" + }, + { + "path": "detect_secrets.filters.heuristic.is_swagger_file" + }, + { + "path": "detect_secrets.filters.heuristic.is_templated_secret" + } + ], + "results": {}, + "generated_at": "2024-06-28T03:54:46Z" +} diff --git a/CodeAnalysisJenkinsfile b/CodeAnalysisJenkinsfile new file mode 100644 index 0000000..815a91c --- /dev/null +++ b/CodeAnalysisJenkinsfile @@ -0,0 +1,94 @@ +pipeline { + agent { + label 'python311 && amd64' + } + options { + quietPeriod(120) + disableConcurrentBuilds() + } + tools {nodejs "Node 20"} + environment { + DEPCHECK_SCAN_ACCOUNT = credentials('DEPCHECK_SCAN_ACCOUNT') + DEPCHECK_CONNSTRING = credentials('DEPCHECK_CONNSTRING') + SONATYPE_OSSINDEX_API_KEY = credentials('SONATYPE_OSSINDEX_API_KEY') + SONAR_SCANNER_OPTS = '-Xmx128m' + } + stages { + stage('Install Python Virtual Enviroment') { + steps { + sh 'echo $PATH' + sh 'python3.11 -m venv env' + } + } + + stage('Install Application Dependencies') { + steps { + sh ''' + . env/bin/activate + pip3.11 install --upgrade pip + pip3.11 install -r requirements.txt + corepack enable + npm install + mkdir reports + deactivate + ''' + } + } + + stage('ESLint') { + steps { + script { + try { + sh ". env/bin/activate && npx eslint . -c eslint.config.mjs -o reports/eslint.json --format json || true" + sh ". env/bin/activate && npx eslint . -c eslint.config.mjs -o reports/eslint-checkstyle.report --format checkstyle || true" + } + finally { + recordIssues tool: esLint(pattern: '**/reports/eslint-checkstyle.report'), aggregatingResults: true + } + } + } + } + + stage('OWASP Dependency-Check Vulnerabilities') { + steps { + sh 'curl -O https://jdbc.postgresql.org/download/postgresql-42.7.3.jar' + dependencyCheck odcInstallation: 'DepCheck', + additionalArguments: '--project "Plex Watchlist" -o ./reports -f XML -f HTML -f JSON -f CSV --noupdate --connectionString $DEPCHECK_CONNSTRING --dbDriverPath postgresql-42.7.3.jar --dbDriverName org.postgresql.Driver --dbUser $DEPCHECK_SCAN_ACCOUNT_USR --dbPassword $DEPCHECK_SCAN_ACCOUNT_PSW --ossIndexUsername averymd@irrsinn.net --ossIndexPassword $SONATYPE_OSSINDEX_API_KEY' + dependencyCheckPublisher pattern: 'reports/dependency-check-report.xml' + } + } + + stage('SonarQube Analysis') { + environment { + scannerHome = tool 'SonarQubeDefault' + } + steps { + withSonarQubeEnv('Personal SonarQube') { + sh """ + . env/bin/activate + ${scannerHome}/bin/sonar-scanner \ + -Dsonar.dependencyCheck.jsonReportPath=reports/dependency-check-report.json \ + -Dsonar.dependencyCheck.xmlReportPath=reports/dependency-check-report.xml \ + -Dsonar.dependencyCheck.htmlReportPath=reports/dependency-check-report.html \ + -Dsonar.eslint.reportPaths=reports/eslint.json + deactivate + """ + } + } + } + } + post { + cleanup { + cleanWs() + dir("${env.WORKSPACE}@tmp") { + deleteDir() + } + dir("${env.WORKSPACE}@2") { + deleteDir() + } + dir("${env.WORKSPACE}@2@tmp") { + deleteDir() + } + } + } +} diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..13e662c --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,45 @@ +import { fixupConfigRules } from '@eslint/compat'; +import globals from 'globals'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import js from '@eslint/js'; +import { FlatCompat } from '@eslint/eslintrc'; +import sonarjs from 'eslint-plugin-sonarjs'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const compat = new FlatCompat({ + baseDirectory: __dirname, + allConfig: js.configs.all, +}); + +export default [ + { + ignores: ['**/libs/*.js', 'node_modules/**/*', '.env/**/*', 'dist/**/*'], + }, + sonarjs.configs.recommended, + ...fixupConfigRules( + compat.extends( + 'plugin:react-hooks/recommended', + 'plugin:@tanstack/eslint-plugin-query/recommended' + ) + ), + { + languageOptions: { + globals: { + ...globals.browser, + }, + parserOptions: { + ecmaFeatures: { + jsx: true, + modules: true, + }, + }, + + ecmaVersion: 'latest', + sourceType: 'module', + }, + + rules: {}, + }, +]; diff --git a/package-lock.json b/package-lock.json index 3f28493..e5d4cf3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,16 +16,20 @@ "@mui/x-date-pickers": "^7.7.1", "@tanstack/react-query": "^5.45.1", "axios": "^1.7.2", + "globals": "^15.6.0", "material-react-table": "^2.13.0", "react": "^18.3.1", "react-dom": "^18.3.1", "rss-parser": "^3.13.0" }, "devDependencies": { + "@eslint/compat": "^1.1.0", "@tanstack/eslint-plugin-query": "^5.43.1", "buffer": "^6.0.3", "eslint": "^9.5.0", + "eslint-formatter-checkstyle": "^8.40.0", "eslint-plugin-react-hooks": "^5.1.0-rc-1434af3d22-20240618", + "eslint-plugin-sonarjs": "^1.0.3", "events": "^3.3.0", "https-browserify": "^1.0.0", "parcel": "^2.12.0", @@ -517,6 +521,16 @@ "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/compat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.0.tgz", + "integrity": "sha512-s9Wi/p25+KbzxKlDm3VshQdImhWk+cbdblhwGNnyCU5lpSwtWa4v7VQCxSki0FAUrGA3s8nCWgYzAH41mwQVKQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/config-array": { "version": "0.16.0", "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.16.0.tgz", @@ -1940,6 +1954,22 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/@parcel/packager-js/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@parcel/packager-raw": { "version": "2.12.0", "resolved": "https://registry.npmjs.org/@parcel/packager-raw/-/packager-raw-2.12.0.tgz", @@ -4324,6 +4354,16 @@ "url": "https://eslint.org/donate" } }, + "node_modules/eslint-formatter-checkstyle": { + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/eslint-formatter-checkstyle/-/eslint-formatter-checkstyle-8.40.0.tgz", + "integrity": "sha512-OpYAiI2yejMPUlB1O2pkfyNfBQrKNWrMK6X2eOn2vg/q94roDiHnOYExK0isdNglKeaYHA5JtgmuBtokFdj0AA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/eslint-plugin-react-hooks": { "version": "5.1.0-rc-1434af3d22-20240618", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.1.0-rc-1434af3d22-20240618.tgz", @@ -4337,6 +4377,19 @@ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, + "node_modules/eslint-plugin-sonarjs": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-1.0.3.tgz", + "integrity": "sha512-6s41HLPYPyDrp+5+7Db5yFYbod6h9pC7yx+xfcNwHRcLe1EZwbbQT/tdOAkR7ekVUkNGEvN3GmYakIoQUX7dEg==", + "dev": true, + "license": "LGPL-3.0-only", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "eslint": "^8.0.0 || ^9.0.0" + } + }, "node_modules/eslint-scope": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.1.tgz", @@ -4672,16 +4725,12 @@ } }, "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, + "version": "15.6.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.6.0.tgz", + "integrity": "sha512-UzcJi88Hw//CurUIRa9Jxb0vgOCcuD/MNjwmXp633cyaRKkCWACkoqHCtfZv43b1kqXGg/fpOa8bwgacCeXsVg==", "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" diff --git a/package.json b/package.json index b1b039d..58529a4 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,6 @@ "name": "public-plex-watchlist", "version": "0.0.1", "description": "Turn your Plex Watchlist RSS feed into an interface non-Plex folks can search and filter.", - "main": "src/index.js", "source": "src/index.html", "scripts": { "start": "parcel", @@ -31,16 +30,20 @@ "@mui/x-date-pickers": "^7.7.1", "@tanstack/react-query": "^5.45.1", "axios": "^1.7.2", + "globals": "^15.6.0", "material-react-table": "^2.13.0", "react": "^18.3.1", "react-dom": "^18.3.1", "rss-parser": "^3.13.0" }, "devDependencies": { + "@eslint/compat": "^1.1.0", "@tanstack/eslint-plugin-query": "^5.43.1", "buffer": "^6.0.3", "eslint": "^9.5.0", + "eslint-formatter-checkstyle": "^8.40.0", "eslint-plugin-react-hooks": "^5.1.0-rc-1434af3d22-20240618", + "eslint-plugin-sonarjs": "^1.0.3", "events": "^3.3.0", "https-browserify": "^1.0.0", "parcel": "^2.12.0", diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..dac0550 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +detect-secrets==1.5.0 +pre-commit==3.7.1 \ No newline at end of file diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..d653642 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,3 @@ +sonar.projectKey=averymd_public-plex-watchlist_3d43ef27-fec8-4c37-9758-6f95ec5635cc +sonar.exclusions=env/**,node_modules/** +sonar.python.version=3.11 \ No newline at end of file diff --git a/src/api/plexApi.js b/src/api/plexApi.js index ba987b7..8dd190f 100644 --- a/src/api/plexApi.js +++ b/src/api/plexApi.js @@ -12,6 +12,5 @@ export async function fetchPlexWatchlistFeed({ pageParam }) { ], }, }); - let result = rssParser.parseURL(pageParam); - return result; + return rssParser.parseURL(pageParam); } diff --git a/src/index.html b/src/index.html index 81c7b12..780aee9 100644 --- a/src/index.html +++ b/src/index.html @@ -4,7 +4,7 @@ - Document + Plex Watchlist