From 0c4a22748c0f8dd04a6f53fd8ab357e3b9aa2e51 Mon Sep 17 00:00:00 2001 From: CarterPerez-dev Date: Wed, 12 Nov 2025 14:57:47 -0500 Subject: [PATCH] move workflow files - add prettier formatting and format --- .github/workflows/eslint-check.yml | 120 +++++++++++++ .github/workflows/lint.yml | 159 ++++++++++++++++++ .github/workflows/typescript-check.yml | 129 ++++++++++++++ .../frontend/.prettierignore | 24 +++ .../frontend/.prettierrc.json | 76 +++++++++ .../api-security-scanner/frontend/src/App.tsx | 11 +- .../src/components/auth/LoginForm.tsx | 40 +++-- .../src/components/auth/RegisterForm.tsx | 45 +++-- .../frontend/src/components/common/Input.tsx | 18 +- .../src/components/common/LoadingOverlay.tsx | 14 +- .../src/components/common/ProtectedRoute.tsx | 7 +- .../src/components/scan/NewScanForm.tsx | 128 +++++++------- .../src/components/scan/ScansList.tsx | 5 +- .../src/components/scan/TestResultCard.tsx | 13 +- .../frontend/src/config/constants.ts | 3 +- .../frontend/src/hooks/useAuth.ts | 22 ++- .../frontend/src/lib/api.ts | 4 +- .../frontend/src/lib/errors.ts | 10 +- .../frontend/src/pages/DashboardPage.tsx | 5 +- .../frontend/src/pages/ScanResultsPage.tsx | 24 ++- .../frontend/src/router.tsx | 7 +- .../frontend/src/store/uiStore.ts | 18 +- .../frontend/src/types/guards.ts | 10 +- 23 files changed, 771 insertions(+), 121 deletions(-) create mode 100644 .github/workflows/eslint-check.yml create mode 100755 .github/workflows/lint.yml create mode 100644 .github/workflows/typescript-check.yml create mode 100755 PROJECTS/api-security-scanner/frontend/.prettierignore create mode 100755 PROJECTS/api-security-scanner/frontend/.prettierrc.json diff --git a/.github/workflows/eslint-check.yml b/.github/workflows/eslint-check.yml new file mode 100644 index 00000000..dbef3d30 --- /dev/null +++ b/.github/workflows/eslint-check.yml @@ -0,0 +1,120 @@ +name: ESLint Check + +on: + pull_request: + branches: [ '*' ] + paths: + - 'PROJECTS/api-security-scanner/frontend/**/*.ts' + - 'PROJECTS/api-security-scanner/frontend/**/*.tsx' + - 'PROJECTS/api-security-scanner/frontend/eslint.config.js' + - 'PROJECTS/api-security-scanner/frontend/tsconfig*.json' + - 'PROJECTS/api-security-scanner/frontend/package.json' + - '.github/workflows/eslint-check.yml' + +jobs: + eslint-check: + name: ESLint TypeScript Check + runs-on: ubuntu-latest + + permissions: + pull-requests: write + contents: read + + defaults: + run: + working-directory: PROJECTS/api-security-scanner/frontend + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + cache-dependency-path: PROJECTS/api-security-scanner/frontend/package-lock.json + + - name: Install dependencies + run: npm install + + - name: Run ESLint + id: eslint_check + run: | + echo "Running ESLint on TypeScript/React files..." + if npm run lint:eslint > eslint-output.txt 2>&1; then + echo "ESLINT_PASSED=true" >> $GITHUB_ENV + echo "βœ… No ESLint errors found!" + echo "ERROR_COUNT=0" >> $GITHUB_ENV + else + echo "ESLINT_PASSED=false" >> $GITHUB_ENV + # Count error lines (lines that contain file paths with problems) + error_count=$(grep -c "^/" eslint-output.txt || echo "0") + echo "ERROR_COUNT=$error_count" >> $GITHUB_ENV + echo "⚠️ ESLint found issues in $error_count files!" + fi + cat eslint-output.txt + continue-on-error: true + + - name: Create ESLint Summary + id: create_summary + if: github.event_name == 'pull_request' + run: | + { + echo '## πŸ” ESLint Results' + echo '' + + if [[ "${{ env.ESLINT_PASSED }}" == "true" ]]; then + echo '### βœ… **Perfect! No ESLint issues found** πŸŽ‰' + echo '' + echo 'Your TypeScript and React code follows all the coding standards perfectly!' + echo '' + echo '**What was checked:**' + echo '- TypeScript strict type checking and stylistic rules' + echo '- React component patterns and hooks usage' + echo '- Code complexity, naming conventions, and best practices' + echo '- Accessibility (jsx-a11y) and React Refresh compatibility' + else + echo '### ❌ **ESLint found issues in ${{ env.ERROR_COUNT }} files**' + echo '' + echo 'Please review and fix the TypeScript/React issues below:' + echo '' + echo '
πŸ“‹ View detailed ESLint output' + echo '' + echo '```' + head -100 eslint-output.txt + echo '```' + echo '
' + echo '' + echo '**How to fix:**' + echo '1. Run `cd frontend && npm run lint:eslint` locally to see the issues' + echo '2. Fix the reported TypeScript, React, and code quality problems' + echo '3. For auto-fixable issues: `cd frontend && npx eslint . --ext .ts,.tsx --fix`' + echo '4. Push your changes to update this PR' + fi + echo '' + echo '**Commands:**' + echo '- `cd frontend && npm run lint:eslint` - Run ESLint' + echo '- `cd frontend && npx eslint . --ext .ts,.tsx --fix` - Auto-fix issues' + echo '- ESLint config: `frontend/eslint.config.js`' + echo '' + echo '' + } > eslint-report.md + + - name: Post PR Comment + if: github.event_name == 'pull_request' + uses: peter-evans/create-or-update-comment@v4 + with: + issue-number: ${{ github.event.pull_request.number }} + body-path: PROJECTS/api-security-scanner/frontend/eslint-report.md + edit-mode: replace + + - name: Exit with proper code + run: | + if [[ "${{ env.ESLINT_PASSED }}" == "false" ]]; then + echo "❌ ESLint checks failed. Please fix the issues above." + exit 1 + else + echo "βœ… All ESLint checks passed!" + exit 0 + fi diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100755 index 00000000..1c17582b --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,159 @@ +name: Lint & Type Check + +on: + push: + branches: [ 'main' ] + pull_request: + branches: [ '*' ] + workflow_dispatch: + + +jobs: + lint: + name: Run Linters + runs-on: ubuntu-latest + + permissions: + pull-requests: write + contents: read + + defaults: + run: + working-directory: PROJECTS/api-security-scanner/backend + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Cache pip dependencies + uses: actions/cache@v4 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('PROJECTS/api-security-scanner/backend/pyproject.toml') }} + restore-keys: | + ${{ runner.os }}-pip- + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -e ".[dev]" + + - name: Run pylint + id: pylint + run: | + echo "Running pylint..." + if pylint . > pylint-output.txt 2>&1; then + echo "PYLINT_PASSED=true" >> $GITHUB_ENV + echo "βœ… No pylint errors found!" + else + echo "PYLINT_PASSED=false" >> $GITHUB_ENV + echo "⚠️ Pylint found issues!" + fi + cat pylint-output.txt + continue-on-error: true + + - name: Run ruff + id: ruff + run: | + echo "Running ruff check..." + if ruff check . > ruff-output.txt 2>&1; then + echo "RUFF_PASSED=true" >> $GITHUB_ENV + echo "βœ… No ruff errors found!" + else + echo "RUFF_PASSED=false" >> $GITHUB_ENV + echo "⚠️ Ruff found issues" + fi + cat ruff-output.txt + continue-on-error: true + + - name: Run mypy + id: mypy + run: | + echo "Running mypy..." + if mypy . > mypy-output.txt 2>&1; then + echo "MYPY_PASSED=true" >> $GITHUB_ENV + echo "βœ… No mypy errors found" + else + echo "MYPY_PASSED=false" >> $GITHUB_ENV + echo "⚠️ Mypy found issues" + fi + cat mypy-output.txt + continue-on-error: true + + - name: Create Lint Summary + id: create_summary + if: github.event_name == 'pull_request' + run: | + { + echo '## πŸ” Lint & Type Check Results' + echo '' + + # Pylint Status + if [[ "${{ env.PYLINT_PASSED }}" == "true" ]]; then + echo '### βœ… Pylint: **Passed**' + echo 'No pylint issues found.' + else + echo '### ⚠️ Pylint: **Issues Found**' + echo '
View pylint output' + echo '' + echo '```' + head -100 pylint-output.txt + echo '```' + echo '
' + fi + echo '' + + # Ruff Status + if [[ "${{ env.RUFF_PASSED }}" == "true" ]]; then + echo '### βœ… Ruff: **Passed**' + echo 'No ruff issues found.' + else + echo '### ⚠️ Ruff: **Issues Found**' + echo '
View ruff output' + echo '' + echo '```' + head -100 ruff-output.txt + echo '```' + echo '
' + fi + echo '' + + # Mypy Status + if [[ "${{ env.MYPY_PASSED }}" == "true" ]]; then + echo '### βœ… Mypy: **Passed**' + echo 'No mypy issues found.' + else + echo '### ⚠️ Mypy: **Issues Found**' + echo '
View mypy output' + echo '' + echo '```' + head -100 mypy-output.txt + echo '```' + echo '
' + fi + echo '' + + # Overall Summary + if [[ "${{ env.PYLINT_PASSED }}" == "true" ]] && [[ "${{ env.RUFF_PASSED }}" == "true" ]] && [[ "${{ env.MYPY_PASSED }}" == "true" ]]; then + echo '---' + echo '### All checks passed!' + else + echo '---' + echo '### Review the issues above and consider fixing them.' + fi + echo '' + echo '' + } > ../lint-report.md + + - name: Post PR Comment + if: github.event_name == 'pull_request' + uses: peter-evans/create-or-update-comment@v4 + with: + issue-number: ${{ github.event.pull_request.number }} + body-path: PROJECTS/api-security-scanner/lint-report.md + comment-marker: lint-check-comment-marker diff --git a/.github/workflows/typescript-check.yml b/.github/workflows/typescript-check.yml new file mode 100644 index 00000000..fe81c403 --- /dev/null +++ b/.github/workflows/typescript-check.yml @@ -0,0 +1,129 @@ +name: TypeScript Type Check + +on: + pull_request: + branches: [ '*' ] + paths: + - 'PROJECTS/api-security-scanner/frontend/**/*.ts' + - 'PROJECTS/api-security-scanner/frontend/**/*.tsx' + - 'PROJECTS/api-security-scanner/frontend/tsconfig*.json' + - 'PROJECTS/api-security-scanner/frontend/package.json' + - '.github/workflows/typescript-check.yml' + +jobs: + typescript-check: + name: TypeScript Type Check + runs-on: ubuntu-latest + + permissions: + pull-requests: write + contents: read + + defaults: + run: + working-directory: PROJECTS/api-security-scanner/frontend + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + cache-dependency-path: PROJECTS/api-security-scanner/frontend/package-lock.json + + - name: Install dependencies + run: | + for i in {1..3}; do + echo "Attempt $i of 3..." + if npm install; then + echo "βœ… npm install succeeded" + break + else + echo "⚠️ npm install failed, retrying in 10 seconds..." + sleep 10 + fi + done + + - name: Run TypeScript type checking + id: typescript_check + run: | + echo "Running TypeScript type checking..." + if npm run lint:types > typescript-output.txt 2>&1; then + echo "TYPESCRIPT_PASSED=true" >> $GITHUB_ENV + echo "βœ… No TypeScript type errors found!" + echo "ERROR_COUNT=0" >> $GITHUB_ENV + else + echo "TYPESCRIPT_PASSED=false" >> $GITHUB_ENV + # Count error lines (lines that contain errors) + error_count=$(grep -c "error TS" typescript-output.txt || echo "0") + echo "ERROR_COUNT=$error_count" >> $GITHUB_ENV + echo "⚠️ TypeScript found $error_count type errors!" + fi + cat typescript-output.txt + continue-on-error: true + + - name: Create TypeScript Summary + id: create_summary + if: github.event_name == 'pull_request' + run: | + { + echo '## πŸ“ TypeScript Type Check Results' + echo '' + + if [[ "${{ env.TYPESCRIPT_PASSED }}" == "true" ]]; then + echo '### βœ… **Perfect! No TypeScript type errors found** πŸŽ‰' + echo '' + echo 'Your TypeScript code passes all strict type checking requirements!' + echo '' + echo '**What was checked:**' + echo '- Strict type checking with `exactOptionalPropertyTypes`' + echo '- No unused locals or parameters' + echo '- Proper return types and void expressions' + echo '- Module resolution and import/export syntax' + else + echo '### ❌ **TypeScript found ${{ env.ERROR_COUNT }} type errors**' + echo '' + echo 'Please review and fix the TypeScript type errors below:' + echo '' + echo '
πŸ“‹ View detailed TypeScript output' + echo '' + echo '```' + head -100 typescript-output.txt + echo '```' + echo '
' + echo '' + echo '**How to fix:**' + echo '1. Run `cd frontend && npm run lint:types` locally to see the type errors' + echo '2. Fix the reported TypeScript type issues' + echo '3. Ensure all variables have proper types and return types are explicit' + echo '4. Push your changes to update this PR' + fi + echo '' + echo '**Commands:**' + echo '- `cd frontend && npm run lint:types` - Run TypeScript type checking' + echo '- `cd frontend && npm run build` - Run full build with type checking' + echo '- TypeScript config: `frontend/tsconfig.app.json`' + echo '' + echo '' + } > typescript-report.md + + - name: Post PR Comment + if: github.event_name == 'pull_request' + uses: peter-evans/create-or-update-comment@v4 + with: + issue-number: ${{ github.event.pull_request.number }} + body-path: PROJECTS/api-security-scanner/frontend/typescript-report.md + edit-mode: replace + + - name: Exit with proper code + run: | + if [[ "${{ env.TYPESCRIPT_PASSED }}" == "false" ]]; then + echo "❌ TypeScript type checking failed. Please fix the type errors above." + exit 1 + else + echo "βœ… All TypeScript type checks passed!" + exit 0 + fi diff --git a/PROJECTS/api-security-scanner/frontend/.prettierignore b/PROJECTS/api-security-scanner/frontend/.prettierignore new file mode 100755 index 00000000..fedf8027 --- /dev/null +++ b/PROJECTS/api-security-scanner/frontend/.prettierignore @@ -0,0 +1,24 @@ +# Dependencies +node_modules/ + +# Build outputs +dist/ +build/ + +# Logs +*.log +npm-debug.log* + +# Runtime data +pids +*.pid +*.seed + +# Coverage directory used by tools like istanbul +coverage/ + +# Other +.DS_Store +.env* +.vscode/ +.idea/ diff --git a/PROJECTS/api-security-scanner/frontend/.prettierrc.json b/PROJECTS/api-security-scanner/frontend/.prettierrc.json new file mode 100755 index 00000000..de72fe39 --- /dev/null +++ b/PROJECTS/api-security-scanner/frontend/.prettierrc.json @@ -0,0 +1,76 @@ +{ + "$schema": "https://json.schemastore.org/prettierrc", + "printWidth": 77, + "tabWidth": 2, + "useTabs": false, + "semi": true, + "singleQuote": true, + "quoteProps": "consistent", + "jsxSingleQuote": false, + "trailingComma": "all", + "bracketSpacing": true, + "bracketSameLine": false, + "arrowParens": "always", + "proseWrap": "always", + "htmlWhitespaceSensitivity": "strict", + "endOfLine": "lf", + "embeddedLanguageFormatting": "auto", + "singleAttributePerLine": true, + "overrides": [ + { + "files": "*.tsx", + "options": { + "printWidth": 77, + "jsxSingleQuote": false, + "bracketSameLine": false + } + }, + { + "files": "*.ts", + "options": { + "printWidth": 77, + "parser": "typescript" + } + }, + { + "files": ["*.json", "*.jsonc"], + "options": { + "printWidth": 80, + "trailingComma": "none" + } + }, + { + "files": "*.scss", + "options": { + "singleQuote": false, + "printWidth": 100 + } + }, + { + "files": "*.md", + "options": { + "proseWrap": "always", + "printWidth": 80 + } + }, + { + "files": ["*.yml", "*.yaml"], + "options": { + "singleQuote": false, + "bracketSpacing": true + } + }, + { + "files": ".prettierrc", + "options": { + "parser": "json" + } + }, + { + "files": "package.json", + "options": { + "printWidth": 1000 + } + } + ] +} diff --git a/PROJECTS/api-security-scanner/frontend/src/App.tsx b/PROJECTS/api-security-scanner/frontend/src/App.tsx index 46df2632..e01fd519 100644 --- a/PROJECTS/api-security-scanner/frontend/src/App.tsx +++ b/PROJECTS/api-security-scanner/frontend/src/App.tsx @@ -13,7 +13,9 @@ import { router } from '@/router'; import { useAuthStore } from '@/store/authStore'; const AuthInitializer = (): null => { - const loadUserFromStorage = useAuthStore((state) => state.loadUserFromStorage); + const loadUserFromStorage = useAuthStore( + (state) => state.loadUserFromStorage, + ); useEffect(() => { loadUserFromStorage(); @@ -27,7 +29,12 @@ function App(): React.ReactElement { - + ); diff --git a/PROJECTS/api-security-scanner/frontend/src/components/auth/LoginForm.tsx b/PROJECTS/api-security-scanner/frontend/src/components/auth/LoginForm.tsx index 2b0555c9..bef790a2 100644 --- a/PROJECTS/api-security-scanner/frontend/src/components/auth/LoginForm.tsx +++ b/PROJECTS/api-security-scanner/frontend/src/components/auth/LoginForm.tsx @@ -21,9 +21,10 @@ export const LoginForm = (): React.ReactElement => { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); - const [errors, setErrors] = useState<{ email?: string; password?: string }>( - {}, - ); + const [errors, setErrors] = useState<{ + email?: string; + password?: string; + }>({}); const { mutate: login, isPending, error } = useLogin(); @@ -49,14 +50,19 @@ export const LoginForm = (): React.ReactElement => { } }; - const validateField = (field: 'email' | 'password', value: string): void => { + const validateField = ( + field: 'email' | 'password', + value: string, + ): void => { const result = loginSchema.safeParse({ email: field === 'email' ? value : email, password: field === 'password' ? value : password, }); if (!result.success) { - const fieldError = result.error.issues.find((err) => err.path[0] === field); + const fieldError = result.error.issues.find( + (err) => err.path[0] === field, + ); if (fieldError !== null && fieldError !== undefined) { setErrors((prev) => ({ ...prev, [field]: fieldError.message })); } else { @@ -120,7 +126,10 @@ export const LoginForm = (): React.ReactElement => { }; return ( -
+

Welcome Back

Sign in to your account

@@ -153,18 +162,29 @@ export const LoginForm = (): React.ReactElement => {
{error !== null && error !== undefined && isAxiosError(error) ? ( -
- {(error.response?.data as { detail?: string } | undefined)?.detail ?? 'Login failed. Please try again.'} +
+ {(error.response?.data as { detail?: string } | undefined) + ?.detail ?? 'Login failed. Please try again.'}
) : null} -

Don't have an account?{' '} - + Sign up

diff --git a/PROJECTS/api-security-scanner/frontend/src/components/auth/RegisterForm.tsx b/PROJECTS/api-security-scanner/frontend/src/components/auth/RegisterForm.tsx index 7fdefd44..4cedc2d4 100644 --- a/PROJECTS/api-security-scanner/frontend/src/components/auth/RegisterForm.tsx +++ b/PROJECTS/api-security-scanner/frontend/src/components/auth/RegisterForm.tsx @@ -15,7 +15,9 @@ import './AuthForm.css'; export const RegisterForm = (): React.ReactElement => { const registerFormState = useUIStore((state) => state.registerForm); - const setRegisterFormField = useUIStore((state) => state.setRegisterFormField); + const setRegisterFormField = useUIStore( + (state) => state.setRegisterFormField, + ); const clearRegisterForm = useUIStore((state) => state.clearRegisterForm); const clearExpiredData = useUIStore((state) => state.clearExpiredData); @@ -61,7 +63,10 @@ export const RegisterForm = (): React.ReactElement => { const handleConfirmPasswordChange = (value: string): void => { setConfirmPassword(value); setRegisterFormField('confirmPassword', value); - if (errors.confirmPassword !== null && errors.confirmPassword !== undefined) { + if ( + errors.confirmPassword !== null && + errors.confirmPassword !== undefined + ) { validateField('confirmPassword', value); } }; @@ -77,7 +82,9 @@ export const RegisterForm = (): React.ReactElement => { }); if (!result.success) { - const fieldError = result.error.issues.find((err) => err.path[0] === field); + const fieldError = result.error.issues.find( + (err) => err.path[0] === field, + ); if (fieldError !== null && fieldError !== undefined) { setErrors((prev) => ({ ...prev, [field]: fieldError.message })); } else { @@ -94,7 +101,9 @@ export const RegisterForm = (): React.ReactElement => { } }; - const handleBlur = (field: 'email' | 'password' | 'confirmPassword'): void => { + const handleBlur = ( + field: 'email' | 'password' | 'confirmPassword', + ): void => { let value: string; if (field === 'email') { value = email; @@ -153,10 +162,15 @@ export const RegisterForm = (): React.ReactElement => { }; return ( - +

Create Account

-

Get started with API Security Scanner

+

+ Get started with API Security Scanner +

@@ -198,18 +212,29 @@ export const RegisterForm = (): React.ReactElement => {
{error !== null && error !== undefined && isAxiosError(error) ? ( -
- {(error.response?.data as { detail?: string } | undefined)?.detail ?? 'Registration failed. Please try again.'} +
+ {(error.response?.data as { detail?: string } | undefined) + ?.detail ?? 'Registration failed. Please try again.'}
) : null} -

Already have an account?{' '} - + Sign in

diff --git a/PROJECTS/api-security-scanner/frontend/src/components/common/Input.tsx b/PROJECTS/api-security-scanner/frontend/src/components/common/Input.tsx index b22b9a77..f9761539 100644 --- a/PROJECTS/api-security-scanner/frontend/src/components/common/Input.tsx +++ b/PROJECTS/api-security-scanner/frontend/src/components/common/Input.tsx @@ -13,12 +13,16 @@ interface InputProps extends InputHTMLAttributes { export const Input = forwardRef( ({ label, error, id, ...props }, ref) => { - const inputId = id ?? `input-${label.toLowerCase().replace(/\s+/g, '-')}`; + const inputId = + id ?? `input-${label.toLowerCase().replace(/\s+/g, '-')}`; const errorId = `${inputId}-error`; return (
-