From c42d99bf2fb9fceb4ed8fec7d333cbdfaea1aada Mon Sep 17 00:00:00 2001 From: Ernesto Date: Thu, 24 Jul 2025 18:57:24 +0200 Subject: [PATCH 1/3] feat: enhance CI pipeline by adding pnpm store directory retrieval and updating cache paths for improved dependency management --- .github/workflows/ci.yml | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 82d24ed..bfa6236 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,6 +30,12 @@ jobs: with: version: ${{ env.PNPM_VERSION }} + - name: Get pnpm store directory + id: pnpm-cache + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT + - name: Generate cache key id: cache-key run: | @@ -38,13 +44,13 @@ jobs: - name: Cache pnpm dependencies uses: actions/cache@v3 with: - path: ~/.pnpm-store + path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} key: ${{ steps.cache-key.outputs.key }} restore-keys: | pnpm- - name: Install dependencies - run: pnpm install --frozen-lockfile + run: pnpm install lint: name: Lint Code @@ -64,10 +70,16 @@ jobs: with: version: ${{ env.PNPM_VERSION }} + - name: Get pnpm store directory + id: pnpm-cache + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT + - name: Restore pnpm cache uses: actions/cache@v3 with: - path: ~/.pnpm-store + path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} key: ${{ needs.setup.outputs.cache-key }} - name: Install dependencies @@ -105,10 +117,16 @@ jobs: with: version: ${{ env.PNPM_VERSION }} + - name: Get pnpm store directory + id: pnpm-cache + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT + - name: Restore pnpm cache uses: actions/cache@v3 with: - path: ~/.pnpm-store + path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} key: ${{ needs.setup.outputs.cache-key }} - name: Install dependencies @@ -220,9 +238,6 @@ jobs: echo "📁 Backend test structure created for future use" - # Build e Deploy gestiti automaticamente da AWS Amplify - # La pipeline CI si concentra solo su qualità del codice e validazione - security-scan: name: Security Scan runs-on: ubuntu-latest @@ -325,13 +340,13 @@ jobs: echo "| Security Scan | ${{ needs.security-scan.result }} |" >> $GITHUB_STEP_SUMMARY echo "| Amplify Validation | ${{ needs.amplify-validation.result }} |" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**ℹ️ Build & Deploy**: Gestiti automaticamente da AWS Amplify ad ogni push su \`main\`" >> $GITHUB_STEP_SUMMARY + echo "**ℹ️ Build & Deploy**: Automatically managed by AWS Amplify on every push to \`main\`" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY if [[ "${{ needs.lint.result }}" == "success" && "${{ needs.test-frontend.result }}" == "success" ]]; then - echo "✅ **Pipeline CI completata con successo!**" >> $GITHUB_STEP_SUMMARY - echo "🚀 **Codice pronto per il deploy automatico Amplify**" >> $GITHUB_STEP_SUMMARY + echo "✅ **CI pipeline completed successfully!**" >> $GITHUB_STEP_SUMMARY + echo "🚀 **Code is ready for automatic Amplify deploy**" >> $GITHUB_STEP_SUMMARY else - echo "❌ **Pipeline CI fallita. Controlla i job sopra.**" >> $GITHUB_STEP_SUMMARY - echo "⚠️ **Il deploy Amplify potrebbe fallire se ci sono errori critici**" >> $GITHUB_STEP_SUMMARY + echo "❌ **CI pipeline failed. Check the jobs above.**" >> $GITHUB_STEP_SUMMARY + echo "⚠️ **Amplify deploy may fail if there are critical errors**" >> $GITHUB_STEP_SUMMARY fi From 26d58394b31c0787f6f6367c42ef78955f4fd5c6 Mon Sep 17 00:00:00 2001 From: Ernesto Date: Thu, 24 Jul 2025 19:02:25 +0200 Subject: [PATCH 2/3] fix: update CI workflow to work without pnpm-lock.yaml tracking --- .github/README.md | 382 +++++++++--------- .github/workflows/ci.yml | 704 ++++++++++++++++----------------- src/components/RootRoute.js | 48 +-- src/hooks/useKeyboardHeight.js | 54 +-- 4 files changed, 594 insertions(+), 594 deletions(-) diff --git a/.github/README.md b/.github/README.md index 2a6b238..3d1e429 100644 --- a/.github/README.md +++ b/.github/README.md @@ -1,191 +1,191 @@ -# GitHub Actions CI Pipeline - -Questo workflow automatizza la pipeline di **Continuous Integration** per il progetto HomeCloud. - -> **ℹ️ Build & Deploy**: Gestiti automaticamente da **AWS Amplify** ad ogni push su `main` -> Questa pipeline CI si concentra su **qualità del codice** e **validazione**. - -## 🚀 Trigger - -La pipeline si attiva automaticamente per: - -- ✅ **Push** su branch `main` -- ✅ **Pull Request** verso `main` - -## 🔧 Jobs della Pipeline - -### 1. **Setup & Install Dependencies** - -- Configura Node.js 18 e pnpm 8 -- Cache intelligente delle dipendenze -- Installazione con `pnpm install --frozen-lockfile` - -### 2. **Lint Code** - -- ESLint per il controllo qualità del codice -- Verifica formattazione Prettier (se configurato) -- **Fallisce** se ci sono errori di linting - -### 3. **Test Frontend** - -- Esegue tutti i test React con Jest -- Genera report di copertura del codice -- Carica artifacts per analisi - -### 4. **Test Backend Functions** - -- Valida la struttura delle funzioni Lambda AWS -- Prepara l'infrastruttura per test futuri -- **Non fallisce** la pipeline (informativo) - -### 5. **Security Scan** (parallelo, solo per main/PR) - -- Audit delle dipendenze npm/pnpm -- Scansione per secrets nel codice -- **Solo** per PR e push su main - -### 6. **Amplify Validation** (parallelo, solo per main/PR) - -- Verifica configurazione AWS Amplify -- Controlla sintassi file JSON -- Lista funzioni Lambda disponibili - -### 7. **Pipeline Summary** (finale) - -- Genera report finale con stato di tutti i job -- Visibile nella tab "Summary" di GitHub Actions - -## 📊 Status e Artifacts - -La pipeline genera: - -- **Coverage Report**: `coverage/` (7 giorni) -- **Pipeline Summary**: Report finale con tutti gli stati - -> **ℹ️ Build & Deploy**: Gestiti automaticamente da AWS Amplify - -## 🔄 Flusso di Lavoro - -````mermaid -graph TD - A[Push/PR] --> B[Setup] - B --> C[Lint] - B --> D[Frontend Tests] - B --> E[Backend Tests] - B --> F[Security Scan] - B --> G[Amplify Validation] - - C --> H[Summary] - D --> H - E --> H - F --> H - G --> H - - H --> I[AWS Amplify Auto-Deploy] - I --> J[✅ Production] -```## ⚡ Ottimizzazioni - -- **Cache pnpm**: Velocizza installazioni ripetute -- **Jobs paralleli**: Setup, lint, test e security girano in parallelo -- **Condizioni smart**: Build solo se lint/test passano -- **Artifacts ottimizzati**: Retention di 7 giorni - -## 🛠 Estensioni Future - -### Backend Testing - -```bash -# Aggiungere test per funzioni Lambda -mkdir -p .github/tests/backend/unit -# Esempio: createDeadline.test.js, readUsers.test.js, etc. -```` - -### Multi-Environment Deploy - -```yaml -# Aggiungere job per deploy staging/production -deploy-staging: - if: github.ref == 'refs/heads/develop' - # Deploy logic -``` - -### Performance Testing - -```yaml -# Aggiungere Lighthouse CI -lighthouse: - needs: build - # Performance analysis -``` - -## 🚨 Troubleshooting - -### Pipeline fallisce al Lint - -```bash -# Locale: Fix errori ESLint -npx eslint src/ --fix -``` - -### Test falliscono - -```bash -# Locale: Run test in modalità interattiva -pnpm test -``` - -### Build fallisce - -```bash -# Locale: Test build -pnpm run build -``` - -### Security scan rileva vulnerabilità - -```bash -# Fix dipendenze vulnerabili -pnpm audit --fix -``` - -## 📝 Configurazione Consigliata - -### ESLint (già configurato) - -Il progetto usa `eslint-config-react-app` - configurazione ottimale per React. - -### Prettier (opzionale) - -```json -// .prettierrc -{ - "semi": true, - "trailingComma": "all", - "singleQuote": true, - "printWidth": 80, - "tabWidth": 2 -} -``` - -### VS Code Settings - -```json -// .vscode/settings.json -{ - "editor.formatOnSave": true, - "editor.codeActionsOnSave": { - "source.fixAll.eslint": true - } -} -``` - -## 🎯 Next Steps - -1. **Commit** questo workflow -2. **Crea una PR** per testare la pipeline -3. **Verifica** che tutti i job passino -4. **Estendi** con test backend quando necessario - ---- - -> **Nota**: La pipeline è progettata per essere **non-bloccante** per il workflow di sviluppo, ma **rigorosa** per la qualità del codice in produzione. +# GitHub Actions CI Pipeline + +Questo workflow automatizza la pipeline di **Continuous Integration** per il progetto HomeCloud. + +> **ℹ️ Build & Deploy**: Gestiti automaticamente da **AWS Amplify** ad ogni push su `main` +> Questa pipeline CI si concentra su **qualità del codice** e **validazione**. + +## 🚀 Trigger + +La pipeline si attiva automaticamente per: + +- ✅ **Push** su branch `main` +- ✅ **Pull Request** verso `main` + +## 🔧 Jobs della Pipeline + +### 1. **Setup & Install Dependencies** + +- Configura Node.js 18 e pnpm 8 +- Cache intelligente delle dipendenze +- Installazione con `pnpm install --frozen-lockfile` + +### 2. **Lint Code** + +- ESLint per il controllo qualità del codice +- Verifica formattazione Prettier (se configurato) +- **Fallisce** se ci sono errori di linting + +### 3. **Test Frontend** + +- Esegue tutti i test React con Jest +- Genera report di copertura del codice +- Carica artifacts per analisi + +### 4. **Test Backend Functions** + +- Valida la struttura delle funzioni Lambda AWS +- Prepara l'infrastruttura per test futuri +- **Non fallisce** la pipeline (informativo) + +### 5. **Security Scan** (parallelo, solo per main/PR) + +- Audit delle dipendenze npm/pnpm +- Scansione per secrets nel codice +- **Solo** per PR e push su main + +### 6. **Amplify Validation** (parallelo, solo per main/PR) + +- Verifica configurazione AWS Amplify +- Controlla sintassi file JSON +- Lista funzioni Lambda disponibili + +### 7. **Pipeline Summary** (finale) + +- Genera report finale con stato di tutti i job +- Visibile nella tab "Summary" di GitHub Actions + +## 📊 Status e Artifacts + +La pipeline genera: + +- **Coverage Report**: `coverage/` (7 giorni) +- **Pipeline Summary**: Report finale con tutti gli stati + +> **ℹ️ Build & Deploy**: Gestiti automaticamente da AWS Amplify + +## 🔄 Flusso di Lavoro + +````mermaid +graph TD + A[Push/PR] --> B[Setup] + B --> C[Lint] + B --> D[Frontend Tests] + B --> E[Backend Tests] + B --> F[Security Scan] + B --> G[Amplify Validation] + + C --> H[Summary] + D --> H + E --> H + F --> H + G --> H + + H --> I[AWS Amplify Auto-Deploy] + I --> J[✅ Production] +```## ⚡ Ottimizzazioni + +- **Cache pnpm**: Velocizza installazioni ripetute +- **Jobs paralleli**: Setup, lint, test e security girano in parallelo +- **Condizioni smart**: Build solo se lint/test passano +- **Artifacts ottimizzati**: Retention di 7 giorni + +## 🛠 Estensioni Future + +### Backend Testing + +```bash +# Aggiungere test per funzioni Lambda +mkdir -p .github/tests/backend/unit +# Esempio: createDeadline.test.js, readUsers.test.js, etc. +```` + +### Multi-Environment Deploy + +```yaml +# Aggiungere job per deploy staging/production +deploy-staging: + if: github.ref == 'refs/heads/develop' + # Deploy logic +``` + +### Performance Testing + +```yaml +# Aggiungere Lighthouse CI +lighthouse: + needs: build + # Performance analysis +``` + +## 🚨 Troubleshooting + +### Pipeline fallisce al Lint + +```bash +# Locale: Fix errori ESLint +npx eslint src/ --fix +``` + +### Test falliscono + +```bash +# Locale: Run test in modalità interattiva +pnpm test +``` + +### Build fallisce + +```bash +# Locale: Test build +pnpm run build +``` + +### Security scan rileva vulnerabilità + +```bash +# Fix dipendenze vulnerabili +pnpm audit --fix +``` + +## 📝 Configurazione Consigliata + +### ESLint (già configurato) + +Il progetto usa `eslint-config-react-app` - configurazione ottimale per React. + +### Prettier (opzionale) + +```json +// .prettierrc +{ + "semi": true, + "trailingComma": "all", + "singleQuote": true, + "printWidth": 80, + "tabWidth": 2 +} +``` + +### VS Code Settings + +```json +// .vscode/settings.json +{ + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true + } +} +``` + +## 🎯 Next Steps + +1. **Commit** questo workflow +2. **Crea una PR** per testare la pipeline +3. **Verifica** che tutti i job passino +4. **Estendi** con test backend quando necessario + +--- + +> **Nota**: La pipeline è progettata per essere **non-bloccante** per il workflow di sviluppo, ma **rigorosa** per la qualità del codice in produzione. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bfa6236..a6257d4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,352 +1,352 @@ -name: CI Pipeline - -on: - push: - branches: [main] - pull_request: - branches: [main] - -env: - NODE_VERSION: "18" - PNPM_VERSION: "8" - -jobs: - setup: - name: Setup & Install Dependencies - runs-on: ubuntu-latest - outputs: - cache-key: ${{ steps.cache-key.outputs.key }} - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: ${{ env.NODE_VERSION }} - - - name: Setup pnpm - uses: pnpm/action-setup@v2 - with: - version: ${{ env.PNPM_VERSION }} - - - name: Get pnpm store directory - id: pnpm-cache - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT - - - name: Generate cache key - id: cache-key - run: | - echo "key=pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}" >> $GITHUB_OUTPUT - - - name: Cache pnpm dependencies - uses: actions/cache@v3 - with: - path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} - key: ${{ steps.cache-key.outputs.key }} - restore-keys: | - pnpm- - - - name: Install dependencies - run: pnpm install - - lint: - name: Lint Code - runs-on: ubuntu-latest - needs: setup - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: ${{ env.NODE_VERSION }} - - - name: Setup pnpm - uses: pnpm/action-setup@v2 - with: - version: ${{ env.PNPM_VERSION }} - - - name: Get pnpm store directory - id: pnpm-cache - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT - - - name: Restore pnpm cache - uses: actions/cache@v3 - with: - path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} - key: ${{ needs.setup.outputs.cache-key }} - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Run ESLint - run: npx eslint src/ --ext .js,.jsx,.ts,.tsx --max-warnings 0 - continue-on-error: false - - - name: Check code formatting (if Prettier is configured) - run: | - if [ -f ".prettierrc" ] || [ -f ".prettierrc.json" ] || [ -f "prettier.config.js" ]; then - echo "Prettier configuration found, checking formatting..." - npx prettier --check "src/**/*.{js,jsx,ts,tsx,json,css,md}" - else - echo "No Prettier configuration found, skipping formatting check" - fi - continue-on-error: true - - test-frontend: - name: Test Frontend - runs-on: ubuntu-latest - needs: setup - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: ${{ env.NODE_VERSION }} - - - name: Setup pnpm - uses: pnpm/action-setup@v2 - with: - version: ${{ env.PNPM_VERSION }} - - - name: Get pnpm store directory - id: pnpm-cache - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT - - - name: Restore pnpm cache - uses: actions/cache@v3 - with: - path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} - key: ${{ needs.setup.outputs.cache-key }} - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Run tests - run: pnpm test -- --coverage --watchAll=false - env: - CI: true - - - name: Upload coverage reports - if: always() - uses: actions/upload-artifact@v3 - with: - name: coverage-report - path: coverage/ - retention-days: 7 - - test-backend: - name: Test Backend Functions - runs-on: ubuntu-latest - needs: setup - if: always() - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: ${{ env.NODE_VERSION }} - - - name: Setup pnpm - uses: pnpm/action-setup@v2 - with: - version: ${{ env.PNPM_VERSION }} - - - name: Test Lambda Functions Structure - run: | - echo "🔍 Checking Lambda functions structure..." - - # Check if Lambda functions exist - if [ -d "amplify/backend/function" ]; then - echo "✅ Lambda functions directory found" - - # List all Lambda functions - echo "📋 Available Lambda functions:" - find amplify/backend/function -maxdepth 1 -type d -not -path "amplify/backend/function" | while read dir; do - func_name=$(basename "$dir") - echo " - $func_name" - - # Check if package.json exists - if [ -f "$dir/src/package.json" ]; then - echo " ✅ package.json found" - else - echo " ⚠️ package.json not found" - fi - - # Check if index.js exists - if [ -f "$dir/src/index.js" ]; then - echo " ✅ index.js found" - else - echo " ⚠️ index.js not found" - fi - done - else - echo "❌ No Lambda functions directory found" - exit 1 - fi - - - name: Install Lambda Dependencies (Future Test Setup) - run: | - echo "🔧 Setting up future backend testing structure..." - - # Create a test structure for future backend tests - mkdir -p .github/tests/backend - - cat > .github/tests/backend/README.md << 'EOF' - # Backend Testing Setup - - This directory is prepared for future Lambda function tests. - - ## Structure - ``` - .github/tests/backend/ - ├── unit/ # Unit tests for individual functions - ├── integration/ # Integration tests - └── utils/ # Test utilities and helpers - ``` - - ## Adding Tests - - 1. For each Lambda function in `amplify/backend/function/`, create corresponding test files - 2. Use Jest or your preferred testing framework - 3. Test both business logic and AWS integration points - - ## Example Test Structure - ```javascript - // .github/tests/backend/unit/createDeadline.test.js - const { handler } = require('../../../amplify/backend/function/createDeadline/src/index'); - - describe('createDeadline Lambda', () => { - test('should validate input correctly', () => { - // Test implementation - }); - }); - ``` - EOF - - echo "📁 Backend test structure created for future use" - - security-scan: - name: Security Scan - runs-on: ubuntu-latest - needs: setup - if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main' - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: ${{ env.NODE_VERSION }} - - - name: Setup pnpm - uses: pnpm/action-setup@v2 - with: - version: ${{ env.PNPM_VERSION }} - - - name: Run npm audit - run: pnpm audit --audit-level moderate - continue-on-error: true - - - name: Check for secrets - uses: trufflesecurity/trufflehog@main - with: - path: ./ - base: main - head: HEAD - extra_args: --debug --only-verified - - amplify-validation: - name: Validate Amplify Configuration - runs-on: ubuntu-latest - if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main' - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Validate Amplify Structure - run: | - echo "🔍 Validating Amplify project structure..." - - # Check required Amplify files - required_files=( - "amplify/cli.json" - "amplify/backend/backend-config.json" - "amplify.yml" - ) - - for file in "${required_files[@]}"; do - if [ -f "$file" ]; then - echo "✅ $file exists" - else - echo "❌ $file is missing" - exit 1 - fi - done - - # Validate backend-config.json syntax - if ! jq empty amplify/backend/backend-config.json; then - echo "❌ Invalid JSON in backend-config.json" - exit 1 - else - echo "✅ backend-config.json is valid JSON" - fi - - # Check Lambda functions - echo "📋 Lambda functions found:" - if [ -d "amplify/backend/function" ]; then - find amplify/backend/function -maxdepth 1 -type d -not -path "amplify/backend/function" | while read dir; do - echo " - $(basename "$dir")" - done - fi - - summary: - name: Pipeline Summary - runs-on: ubuntu-latest - needs: - [ - setup, - lint, - test-frontend, - test-backend, - security-scan, - amplify-validation, - ] - if: always() - steps: - - name: Generate Summary - run: | - echo "## 🚀 Pipeline Results" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "| Job | Status |" >> $GITHUB_STEP_SUMMARY - echo "|-----|--------|" >> $GITHUB_STEP_SUMMARY - echo "| Setup | ${{ needs.setup.result }} |" >> $GITHUB_STEP_SUMMARY - echo "| Lint | ${{ needs.lint.result }} |" >> $GITHUB_STEP_SUMMARY - echo "| Frontend Tests | ${{ needs.test-frontend.result }} |" >> $GITHUB_STEP_SUMMARY - echo "| Backend Tests | ${{ needs.test-backend.result }} |" >> $GITHUB_STEP_SUMMARY - echo "| Security Scan | ${{ needs.security-scan.result }} |" >> $GITHUB_STEP_SUMMARY - echo "| Amplify Validation | ${{ needs.amplify-validation.result }} |" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "**ℹ️ Build & Deploy**: Automatically managed by AWS Amplify on every push to \`main\`" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - - if [[ "${{ needs.lint.result }}" == "success" && "${{ needs.test-frontend.result }}" == "success" ]]; then - echo "✅ **CI pipeline completed successfully!**" >> $GITHUB_STEP_SUMMARY - echo "🚀 **Code is ready for automatic Amplify deploy**" >> $GITHUB_STEP_SUMMARY - else - echo "❌ **CI pipeline failed. Check the jobs above.**" >> $GITHUB_STEP_SUMMARY - echo "⚠️ **Amplify deploy may fail if there are critical errors**" >> $GITHUB_STEP_SUMMARY - fi +name: CI Pipeline + +on: + push: + branches: [main] + pull_request: + branches: [main] + +env: + NODE_VERSION: "18" + PNPM_VERSION: "8" + +jobs: + setup: + name: Setup & Install Dependencies + runs-on: ubuntu-latest + outputs: + cache-key: ${{ steps.cache-key.outputs.key }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Get pnpm store directory + id: pnpm-cache + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT + + - name: Generate cache key + id: cache-key + run: | + echo "key=pnpm-${{ hashFiles('**/package.json') }}" >> $GITHUB_OUTPUT + + - name: Cache pnpm dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} + key: ${{ steps.cache-key.outputs.key }} + restore-keys: | + pnpm- + + - name: Install dependencies + run: pnpm install + + lint: + name: Lint Code + runs-on: ubuntu-latest + needs: setup + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Get pnpm store directory + id: pnpm-cache + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT + + - name: Restore pnpm cache + uses: actions/cache@v3 + with: + path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} + key: ${{ needs.setup.outputs.cache-key }} + + - name: Install dependencies + run: pnpm install + + - name: Run ESLint + run: npx eslint src/ --ext .js,.jsx,.ts,.tsx --max-warnings 0 + continue-on-error: false + + - name: Check code formatting (if Prettier is configured) + run: | + if [ -f ".prettierrc" ] || [ -f ".prettierrc.json" ] || [ -f "prettier.config.js" ]; then + echo "Prettier configuration found, checking formatting..." + npx prettier --check "src/**/*.{js,jsx,ts,tsx,json,css,md}" + else + echo "No Prettier configuration found, skipping formatting check" + fi + continue-on-error: true + + test-frontend: + name: Test Frontend + runs-on: ubuntu-latest + needs: setup + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Get pnpm store directory + id: pnpm-cache + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT + + - name: Restore pnpm cache + uses: actions/cache@v3 + with: + path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} + key: ${{ needs.setup.outputs.cache-key }} + + - name: Install dependencies + run: pnpm install + + - name: Run tests + run: pnpm test -- --coverage --watchAll=false + env: + CI: true + + - name: Upload coverage reports + if: always() + uses: actions/upload-artifact@v3 + with: + name: coverage-report + path: coverage/ + retention-days: 7 + + test-backend: + name: Test Backend Functions + runs-on: ubuntu-latest + needs: setup + if: always() + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Test Lambda Functions Structure + run: | + echo "🔍 Checking Lambda functions structure..." + + # Check if Lambda functions exist + if [ -d "amplify/backend/function" ]; then + echo "✅ Lambda functions directory found" + + # List all Lambda functions + echo "📋 Available Lambda functions:" + find amplify/backend/function -maxdepth 1 -type d -not -path "amplify/backend/function" | while read dir; do + func_name=$(basename "$dir") + echo " - $func_name" + + # Check if package.json exists + if [ -f "$dir/src/package.json" ]; then + echo " ✅ package.json found" + else + echo " ⚠️ package.json not found" + fi + + # Check if index.js exists + if [ -f "$dir/src/index.js" ]; then + echo " ✅ index.js found" + else + echo " ⚠️ index.js not found" + fi + done + else + echo "❌ No Lambda functions directory found" + exit 1 + fi + + - name: Install Lambda Dependencies (Future Test Setup) + run: | + echo "🔧 Setting up future backend testing structure..." + + # Create a test structure for future backend tests + mkdir -p .github/tests/backend + + cat > .github/tests/backend/README.md << 'EOF' + # Backend Testing Setup + + This directory is prepared for future Lambda function tests. + + ## Structure + ``` + .github/tests/backend/ + ├── unit/ # Unit tests for individual functions + ├── integration/ # Integration tests + └── utils/ # Test utilities and helpers + ``` + + ## Adding Tests + + 1. For each Lambda function in `amplify/backend/function/`, create corresponding test files + 2. Use Jest or your preferred testing framework + 3. Test both business logic and AWS integration points + + ## Example Test Structure + ```javascript + // .github/tests/backend/unit/createDeadline.test.js + const { handler } = require('../../../amplify/backend/function/createDeadline/src/index'); + + describe('createDeadline Lambda', () => { + test('should validate input correctly', () => { + // Test implementation + }); + }); + ``` + EOF + + echo "📁 Backend test structure created for future use" + + security-scan: + name: Security Scan + runs-on: ubuntu-latest + needs: setup + if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main' + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Run npm audit + run: pnpm audit --audit-level moderate + continue-on-error: true + + - name: Check for secrets + uses: trufflesecurity/trufflehog@main + with: + path: ./ + base: main + head: HEAD + extra_args: --debug --only-verified + + amplify-validation: + name: Validate Amplify Configuration + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main' + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Validate Amplify Structure + run: | + echo "🔍 Validating Amplify project structure..." + + # Check required Amplify files + required_files=( + "amplify/cli.json" + "amplify/backend/backend-config.json" + "amplify.yml" + ) + + for file in "${required_files[@]}"; do + if [ -f "$file" ]; then + echo "✅ $file exists" + else + echo "❌ $file is missing" + exit 1 + fi + done + + # Validate backend-config.json syntax + if ! jq empty amplify/backend/backend-config.json; then + echo "❌ Invalid JSON in backend-config.json" + exit 1 + else + echo "✅ backend-config.json is valid JSON" + fi + + # Check Lambda functions + echo "📋 Lambda functions found:" + if [ -d "amplify/backend/function" ]; then + find amplify/backend/function -maxdepth 1 -type d -not -path "amplify/backend/function" | while read dir; do + echo " - $(basename "$dir")" + done + fi + + summary: + name: Pipeline Summary + runs-on: ubuntu-latest + needs: + [ + setup, + lint, + test-frontend, + test-backend, + security-scan, + amplify-validation, + ] + if: always() + steps: + - name: Generate Summary + run: | + echo "## 🚀 Pipeline Results" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "| Job | Status |" >> $GITHUB_STEP_SUMMARY + echo "|-----|--------|" >> $GITHUB_STEP_SUMMARY + echo "| Setup | ${{ needs.setup.result }} |" >> $GITHUB_STEP_SUMMARY + echo "| Lint | ${{ needs.lint.result }} |" >> $GITHUB_STEP_SUMMARY + echo "| Frontend Tests | ${{ needs.test-frontend.result }} |" >> $GITHUB_STEP_SUMMARY + echo "| Backend Tests | ${{ needs.test-backend.result }} |" >> $GITHUB_STEP_SUMMARY + echo "| Security Scan | ${{ needs.security-scan.result }} |" >> $GITHUB_STEP_SUMMARY + echo "| Amplify Validation | ${{ needs.amplify-validation.result }} |" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**ℹ️ Build & Deploy**: Automatically managed by AWS Amplify on every push to \`main\`" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [[ "${{ needs.lint.result }}" == "success" && "${{ needs.test-frontend.result }}" == "success" ]]; then + echo "✅ **CI pipeline completed successfully!**" >> $GITHUB_STEP_SUMMARY + echo "🚀 **Code is ready for automatic Amplify deploy**" >> $GITHUB_STEP_SUMMARY + else + echo "❌ **CI pipeline failed. Check the jobs above.**" >> $GITHUB_STEP_SUMMARY + echo "⚠️ **Amplify deploy may fail if there are critical errors**" >> $GITHUB_STEP_SUMMARY + fi diff --git a/src/components/RootRoute.js b/src/components/RootRoute.js index d3e732c..7a1e9f4 100644 --- a/src/components/RootRoute.js +++ b/src/components/RootRoute.js @@ -1,24 +1,24 @@ -import React, { useEffect, useState } from "react"; -import { Navigate } from "react-router-dom"; -import { getLoggedUser } from "../helpers/authHelper"; -import Dashboard from "../pages/Dashboard"; - -const RootRoute = () => { - const [checking, setChecking] = useState(true); - const [isAuthenticated, setIsAuthenticated] = useState(false); - - useEffect(() => { - const checkAuth = async () => { - const user = await getLoggedUser(); - setIsAuthenticated(!!user); - setChecking(false); - }; - checkAuth(); - }, []); - - if (checking) return null; - - return isAuthenticated ? : ; -}; - -export default RootRoute; +import React, { useEffect, useState } from "react"; +import { Navigate } from "react-router-dom"; +import { getLoggedUser } from "../helpers/authHelper"; +import Dashboard from "../pages/Dashboard"; + +const RootRoute = () => { + const [checking, setChecking] = useState(true); + const [isAuthenticated, setIsAuthenticated] = useState(false); + + useEffect(() => { + const checkAuth = async () => { + const user = await getLoggedUser(); + setIsAuthenticated(!!user); + setChecking(false); + }; + checkAuth(); + }, []); + + if (checking) return null; + + return isAuthenticated ? : ; +}; + +export default RootRoute; diff --git a/src/hooks/useKeyboardHeight.js b/src/hooks/useKeyboardHeight.js index 4def89a..b14f155 100644 --- a/src/hooks/useKeyboardHeight.js +++ b/src/hooks/useKeyboardHeight.js @@ -1,27 +1,27 @@ -import { useState, useEffect } from "react"; - -export const useKeyboardHeight = () => { - const [keyboardHeight, setKeyboardHeight] = useState(0); - const [isKeyboardVisible, setIsKeyboardVisible] = useState(false); - - useEffect(() => { - if (typeof window === "undefined") return; - - const handleResize = () => { - if (window.visualViewport) { - const heightDiff = window.screen.height - window.visualViewport.height; - setKeyboardHeight(heightDiff); - setIsKeyboardVisible(heightDiff > 150); - } - }; - - if (window.visualViewport) { - window.visualViewport.addEventListener("resize", handleResize); - return () => { - window.visualViewport.removeEventListener("resize", handleResize); - }; - } - }, []); - - return { keyboardHeight, isKeyboardVisible }; -}; +import { useState, useEffect } from "react"; + +export const useKeyboardHeight = () => { + const [keyboardHeight, setKeyboardHeight] = useState(0); + const [isKeyboardVisible, setIsKeyboardVisible] = useState(false); + + useEffect(() => { + if (typeof window === "undefined") return; + + const handleResize = () => { + if (window.visualViewport) { + const heightDiff = window.screen.height - window.visualViewport.height; + setKeyboardHeight(heightDiff); + setIsKeyboardVisible(heightDiff > 150); + } + }; + + if (window.visualViewport) { + window.visualViewport.addEventListener("resize", handleResize); + return () => { + window.visualViewport.removeEventListener("resize", handleResize); + }; + } + }, []); + + return { keyboardHeight, isKeyboardVisible }; +}; From 9d009dad5ca2266e14c70b30c4c0a9c3e7575795 Mon Sep 17 00:00:00 2001 From: Ernesto Date: Thu, 24 Jul 2025 19:28:10 +0200 Subject: [PATCH 3/3] feat: enhance UserProfileSection input validation to allow only letters, spaces, apostrophes, and hyphens in names --- .github/workflows/ci.yml | 64 +++++++++++++++++++--------- src/components/UserProfileSection.js | 23 ++++++++-- 2 files changed, 63 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a6257d4..84ff350 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,7 +42,7 @@ jobs: echo "key=pnpm-${{ hashFiles('**/package.json') }}" >> $GITHUB_OUTPUT - name: Cache pnpm dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} key: ${{ steps.cache-key.outputs.key }} @@ -77,7 +77,7 @@ jobs: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT - name: Restore pnpm cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} key: ${{ needs.setup.outputs.cache-key }} @@ -124,7 +124,7 @@ jobs: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT - name: Restore pnpm cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} key: ${{ needs.setup.outputs.cache-key }} @@ -139,7 +139,7 @@ jobs: - name: Upload coverage reports if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: coverage-report path: coverage/ @@ -241,33 +241,55 @@ jobs: security-scan: name: Security Scan runs-on: ubuntu-latest - needs: setup - if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main' + if: github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/main') steps: - name: Checkout code uses: actions/checkout@v4 + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: 8 + - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: ${{ env.NODE_VERSION }} + node-version: 18 + cache: "pnpm" - - name: Setup pnpm - uses: pnpm/action-setup@v2 - with: - version: ${{ env.PNPM_VERSION }} + - name: Install dependencies + run: pnpm install --frozen-lockfile - - name: Run npm audit - run: pnpm audit --audit-level moderate - continue-on-error: true + - name: Run security audit + run: | + echo "Running pnpm audit..." + pnpm audit --audit-level moderate || { + echo "Security vulnerabilities found. Checking severity..." + if pnpm audit --audit-level high; then + echo "High severity vulnerabilities found!" + exit 1 + else + echo "Only low/moderate vulnerabilities found - proceeding" + exit 0 + fi + } - - name: Check for secrets - uses: trufflesecurity/trufflehog@main - with: - path: ./ - base: main - head: HEAD - extra_args: --debug --only-verified + - name: Check for secrets (simple grep) + run: | + echo "Checking for potential secrets..." + # Verifica pattern comuni di secrets + if grep -r -i --exclude-dir=node_modules --exclude-dir=.git \ + -E "(password|secret|key|token|api_key).*=.*['\"][^'\"]{10,}['\"]" . || \ + grep -r --exclude-dir=node_modules --exclude-dir=.git \ + -E "AKIA[0-9A-Z]{16}" . || \ + grep -r --exclude-dir=node_modules --exclude-dir=.git \ + -E "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}" .; then + echo "⚠️ Potential secrets detected!" + echo "Please review the above matches and ensure no sensitive data is committed." + # Non facciamo fallire la pipeline, solo warning + else + echo "✅ No obvious secrets detected" + fi amplify-validation: name: Validate Amplify Configuration diff --git a/src/components/UserProfileSection.js b/src/components/UserProfileSection.js index aa2389a..7a661ea 100644 --- a/src/components/UserProfileSection.js +++ b/src/components/UserProfileSection.js @@ -18,7 +18,8 @@ const UserProfileSection = ({ user, loadingUser, onUserUpdate, onMessage }) => { const value = e.target.value; // Regex per permettere solo lettere, spazi, apostrofi e caratteri accentati - const allowedCharsRegex = /^[a-zA-ZÀ-ÿ\u0100-\u017F\u0180-\u024F\u1E00-\u1EFF\s']*$/; + const allowedCharsRegex = + /^[a-zA-ZÀ-ÿ\u0100-\u017F\u0180-\u024F\u1E00-\u1EFF\s']*$/; // Controlla se il valore contiene solo caratteri consentiti if (allowedCharsRegex.test(value)) { @@ -43,7 +44,7 @@ const UserProfileSection = ({ user, loadingUser, onUserUpdate, onMessage }) => { // Previeni l'inserimento di numeri anche tramite tastiera const char = e.key; const isNumber = /[0-9]/.test(char); - const isSpecialChar = /[!@#$%^&*()_+\-=\[\]{};:"\\|,.<>\/?]/.test(char); + const isSpecialChar = /[!@#$%^&*()_+=[\]{};:"\\|,.<>/?]/.test(char); // Permettiamo solo: lettere, spazi, backspace, delete, tab, enter, escape const allowedKeys = [ @@ -58,7 +59,13 @@ const UserProfileSection = ({ user, loadingUser, onUserUpdate, onMessage }) => { "ArrowDown", ]; - if (isNumber || (isSpecialChar && !allowedKeys.includes(char) && char !== "'" && char !== ' ')) { + if ( + isNumber || + (isSpecialChar && + !allowedKeys.includes(char) && + char !== "'" && + char !== " ") + ) { e.preventDefault(); return; } @@ -111,6 +118,16 @@ const UserProfileSection = ({ user, loadingUser, onUserUpdate, onMessage }) => { return; } + // Controllo caratteri speciali (permettiamo solo lettere, spazi, apostrofi e trattini) + const validNameRegex = /^[a-zA-ZÀ-ÿ\s'-]+$/; + if (!validNameRegex.test(trimmedName)) { + onMessage({ + type: "error", + text: "Il nome può contenere solo lettere, spazi, apostrofi e trattini.", + }); + return; + } + if (trimmedName === user?.full_name) { setIsEditingName(false); return;