diff --git a/.github/workflows/bundle-analysis.yml b/.github/workflows/bundle-analysis.yml deleted file mode 100644 index 312ac57b..00000000 --- a/.github/workflows/bundle-analysis.yml +++ /dev/null @@ -1,166 +0,0 @@ -name: Bundle Analysis - -on: - pull_request: - paths: - - 'frontend/**' - branches: [ main, master ] - push: - paths: - - 'frontend/**' - branches: [ main, master ] - -jobs: - bundle-analysis: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v5 - with: - fetch-depth: 0 - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: '18' - cache: 'npm' - cache-dependency-path: frontend/package-lock.json - - - name: Install Dependencies - run: npm install - working-directory: ./frontend - - - name: Setup EAS - uses: expo/expo-github-action@v8 - with: - eas-version: latest - token: ${{ secrets.EXPO_TOKEN }} - - - name: Build for Bundle Analysis - run: | - # Try to build with Expo for web, but handle React Native compatibility issues - if npx expo export --platform web --output-dir web-build 2>/dev/null; then - echo "✅ Expo web export successful" - else - echo "⚠️ Web export failed, using alternative bundle analysis approach" - # Create a basic bundle using Metro bundler directly - npx metro build --entry-file index.js --platform web --bundle-output web-build/bundle.js --assets-dest web-build/static || true - # If that also fails, create a minimal analysis report - if [ ! -f "web-build/bundle.js" ]; then - echo "📊 Creating basic size analysis from node_modules..." - mkdir -p web-build/static/js - # Analyze the main dependencies that would be bundled - echo "# Bundle Analysis Report (Estimated)" > bundle-analysis.md - echo "" >> bundle-analysis.md - echo "## Bundle Size Analysis" >> bundle-analysis.md - echo "- React Native web build failed due to platform-specific modules" >> bundle-analysis.md - echo "- This is common with React Native apps that use platform-specific code" >> bundle-analysis.md - echo "" >> bundle-analysis.md - echo "## Key Dependencies Analysis" >> bundle-analysis.md - du -sh node_modules/react node_modules/react-native node_modules/@expo 2>/dev/null | while read size dir; do - echo "- ${dir}: ${size}" >> bundle-analysis.md - done || echo "- Unable to analyze individual dependencies" >> bundle-analysis.md - exit 0 - fi - fi - working-directory: ./frontend - - - name: Analyze Bundle Size - working-directory: ./frontend - run: | - # Install analysis tools - npm install --no-save @expo/metro-config metro-visualizer - sudo apt-get update && sudo apt-get install -y bc - - echo "📊 Analyzing bundle size for Expo/React Native project..." - - # Check if bundle analysis report already exists (from build step failure handling) - if [ -f "bundle-analysis.md" ]; then - echo "� Using existing analysis report from build step" - cat bundle-analysis.md - exit 0 - fi - - # Check if web-build directory exists - if [ -d "web-build" ]; then - echo "✅ Web build directory found" - ls -la web-build/ - - # Look for JavaScript bundles in various locations - BUNDLE_FOUND=false - - # Check standard Expo web build structure - if [ -d "web-build/static/js" ] && [ "$(ls -A web-build/static/js 2>/dev/null)" ]; then - echo "📁 JavaScript bundle files in static/js:" - find web-build/static/js -name "*.js" -type f -exec ls -lh {} \; | awk '{print $5 " " $9}' - - # Calculate total bundle size - TOTAL_SIZE=$(find web-build/static/js -name "*.js" -type f -exec stat -c%s {} \; | awk '{sum+=$1} END {print sum}') - TOTAL_SIZE_MB=$(echo "scale=2; $TOTAL_SIZE / 1024 / 1024" | bc -l) - echo "📊 Total JavaScript bundle size: ${TOTAL_SIZE_MB} MB" - BUNDLE_FOUND=true - elif [ -f "web-build/bundle.js" ]; then - echo "📁 Single bundle file found:" - ls -lh web-build/bundle.js - BUNDLE_SIZE=$(stat -c%s web-build/bundle.js) - TOTAL_SIZE_MB=$(echo "scale=2; $BUNDLE_SIZE / 1024 / 1024" | bc -l) - echo "📊 Bundle size: ${TOTAL_SIZE_MB} MB" - BUNDLE_FOUND=true - fi - - if [ "$BUNDLE_FOUND" = true ]; then - # Create analysis report - echo "# Bundle Analysis Report" > bundle-analysis.md - echo "" >> bundle-analysis.md - echo "## Bundle Size Summary" >> bundle-analysis.md - echo "- Total JavaScript bundle size: **${TOTAL_SIZE_MB} MB**" >> bundle-analysis.md - echo "" >> bundle-analysis.md - echo "## Build Details" >> bundle-analysis.md - echo "- Platform: Web (React Native)" >> bundle-analysis.md - echo "- Bundler: Metro (Expo)" >> bundle-analysis.md - echo "" >> bundle-analysis.md - - if [ -d "web-build/static/js" ]; then - echo "## Individual Files" >> bundle-analysis.md - find web-build/static/js -name "*.js" -type f -exec ls -lh {} \; | awk '{print "- " $9 ": " $5}' >> bundle-analysis.md - fi - - cat bundle-analysis.md - else - echo "❌ No JavaScript bundles found in expected locations" - echo "📁 Available files in web-build:" - find web-build -type f -name "*.js" -o -name "*.json" | head -10 - fi - else - echo "❌ No web-build directory found" - echo "📁 Available directories:" - ls -la - - # Create fallback analysis - echo "# Bundle Analysis Report (Fallback)" > bundle-analysis.md - echo "" >> bundle-analysis.md - echo "## Analysis Status" >> bundle-analysis.md - echo "- Web build failed - this is common for React Native apps with platform-specific code" >> bundle-analysis.md - echo "- Bundle analysis skipped for this build" >> bundle-analysis.md - fi - - - name: Upload Bundle Analysis Report - if: always() && hashFiles('frontend/bundle-analysis.md') != '' - uses: actions/upload-artifact@v4 - with: - name: bundle-analysis-report - path: frontend/bundle-analysis.md - retention-days: 30 - - - name: Upload Bundle Analysis to Codecov - uses: codecov/codecov-action@v5 - if: github.actor != 'dependabot[bot]' && hashFiles('frontend/bundle-analysis.md') != '' - with: - token: ${{ secrets.CODECOV_TOKEN }} - flags: bundle,frontend,javascript - name: "Bundle Analysis" - fail_ci_if_error: false - - - name: Bundle Analysis Skipped - if: github.actor == 'dependabot[bot]' - run: echo "📦 Bundle analysis skipped for Dependabot PR" diff --git a/.github/workflows/code-analysis.yml b/.github/workflows/code-analysis.yml new file mode 100644 index 00000000..918efad2 --- /dev/null +++ b/.github/workflows/code-analysis.yml @@ -0,0 +1,141 @@ +name: Code Analysis + +on: + pull_request_target: + paths: + - 'frontend/**' + branches: [ main, master ] + workflow_dispatch: + +jobs: + web-bundle-analysis: + if: contains(github.event.pull_request.labels.*.name, 'run-analysis') || github.event_name == 'workflow_dispatch' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + with: + ref: ${{ github.event.pull_request.head.sha || github.ref }} + fetch-depth: 0 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + cache: 'npm' + cache-dependency-path: frontend/package-lock.json + + - name: Install Dependencies + run: npm install + working-directory: ./frontend + + - name: Setup EAS + uses: expo/expo-github-action@v8 + with: + eas-version: latest + token: ${{ secrets.EXPO_TOKEN }} + + - name: Build for Bundle Analysis (Web) + run: | + if npx expo export --platform web --output-dir web-build 2>/dev/null; then + echo "✅ Expo web export successful" + else + echo "⚠️ Web export failed, using alternative bundle analysis approach" + npx metro build --entry-file index.js --platform web --bundle-output web-build/bundle.js --assets-dest web-build/static || true + fi + working-directory: ./frontend + + - name: Analyze Web Bundle Size + working-directory: ./frontend + run: | + if [ ! -d "web-build" ]; then + echo "❌ No web-build directory found. Skipping analysis." + exit 0 + fi + + TOTAL_SIZE=0 + if [ -d "web-build/static/js" ]; then + TOTAL_SIZE=$(find web-build/static/js -name "*.js" -type f -exec stat -c%s {} \; | awk '{sum+=$1} END {print sum}') + elif [ -f "web-build/bundle.js" ]; then + TOTAL_SIZE=$(stat -c%s web-build/bundle.js) + fi + + if [ "$TOTAL_SIZE" -gt 0 ]; then + TOTAL_SIZE_MB=$(awk "BEGIN {printf \"%.2f\", $TOTAL_SIZE / 1024 / 1024}") + echo "📊 Total Web JavaScript bundle size: ${TOTAL_SIZE_MB} MB" + + echo "# Web Bundle Analysis Report" > bundle-analysis-web.md + echo "## Bundle Size Summary" >> bundle-analysis-web.md + echo "- Total JavaScript bundle size: **${TOTAL_SIZE_MB} MB**" >> bundle-analysis-web.md + else + echo "❌ No JavaScript bundles found in expected locations." + fi + + - name: Upload Web Bundle Analysis Report + if: always() && hashFiles('frontend/bundle-analysis-web.md') != '' + uses: actions/upload-artifact@v4 + with: + name: web-bundle-analysis-report + path: frontend/bundle-analysis-web.md + + rn-bundle-analysis: + if: contains(github.event.pull_request.labels.*.name, 'run-analysis') || github.event_name == 'workflow_dispatch' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + with: + ref: ${{ github.event.pull_request.head.sha || github.ref }} + fetch-depth: 0 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + cache: 'npm' + cache-dependency-path: frontend/package-lock.json + + - name: Install Dependencies + run: npm install + working-directory: ./frontend + + - name: Setup EAS + uses: expo/expo-github-action@v8 + with: + eas-version: latest + token: ${{ secrets.EXPO_TOKEN }} + + - name: Build for Bundle Analysis (RN) + run: | + if npx expo export --platform android --output-dir android-build --max-workers 1; then + echo "✅ Android export successful" + else + echo "⚠️ Android export failed. Skipping analysis." + fi + working-directory: ./frontend + + - name: Analyze RN Bundle Size + working-directory: ./frontend + run: | + if [ ! -d "android-build" ]; then + echo "❌ No android-build directory found. Skipping analysis." + exit 0 + fi + + BUNDLE_FILE=$(find android-build/bundles -name "android-*.js" | head -1) + if [ -f "$BUNDLE_FILE" ]; then + BUNDLE_SIZE=$(stat -c%s "$BUNDLE_FILE") + BUNDLE_SIZE_MB=$(awk "BEGIN {printf \"%.2f\", $BUNDLE_SIZE / 1024 / 1024}") + + echo "# React Native Bundle Analysis Report" > bundle-analysis-rn.md + echo "## Bundle Size Summary" >> bundle-analysis-rn.md + echo "- Platform: Android" >> bundle-analysis-rn.md + echo "- Bundle size: **${BUNDLE_SIZE_MB} MB**" >> bundle-analysis-rn.md + else + echo "❌ No Android bundle found." + fi + + - name: Upload RN Bundle Analysis Report + if: always() && hashFiles('frontend/bundle-analysis-rn.md') != '' + uses: actions/upload-artifact@v4 + with: + name: rn-bundle-analysis-report + path: frontend/bundle-analysis-rn.md diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index 11cac507..ab1ea6c1 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -1,7 +1,8 @@ name: Create EAS Preview on: - pull_request: + pull_request_target: + workflow_dispatch: permissions: contents: read @@ -9,10 +10,13 @@ permissions: jobs: preview: + if: contains(github.event.pull_request.labels.*.name, 'run-preview') || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v5 + with: + ref: ${{ github.event.pull_request.head.sha || github.ref }} - name: Setup Node.js uses: actions/setup-node@v4 @@ -32,5 +36,5 @@ jobs: - name: Create preview uses: expo/expo-github-action/preview@v8 with: - command: eas update --auto --branch ${{ github.event.pull_request.head.ref }} + command: eas update --auto --branch ${{ github.event.pull_request.head.ref || github.ref_name }} working-directory: ./frontend diff --git a/.github/workflows/rn-bundle-analysis.yml b/.github/workflows/rn-bundle-analysis.yml deleted file mode 100644 index 47a857ac..00000000 --- a/.github/workflows/rn-bundle-analysis.yml +++ /dev/null @@ -1,117 +0,0 @@ -name: React Native Bundle Analysis - -on: - pull_request: - paths: - - 'frontend/**' - branches: [ main, master ] - push: - paths: - - 'frontend/**' - branches: [ main, master ] - -jobs: - rn-bundle-analysis: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v5 - with: - fetch-depth: 0 - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: '18' - cache: 'npm' - cache-dependency-path: frontend/package-lock.json - - - name: Setup EAS - uses: expo/expo-github-action@v8 - with: - eas-version: latest - token: ${{ secrets.EXPO_TOKEN }} - - - name: Install Dependencies - run: npm install - working-directory: ./frontend - - - name: Analyze React Native Bundle Size - working-directory: ./frontend - run: | - echo "📊 Analyzing React Native bundle size..." - - # Install bundle analysis tools - npm install --no-save metro-visualizer - - # Create bundle for Android (this usually works better than web) - echo "🤖 Creating Android bundle for analysis..." - if npx expo export --platform android --output-dir android-build --max-workers 1; then - echo "✅ Android export successful" - - # Find and analyze the bundle - if [ -f "android-build/bundles/android-*.js" ]; then - BUNDLE_FILE=$(find android-build/bundles -name "android-*.js" | head -1) - BUNDLE_SIZE=$(stat -c%s "$BUNDLE_FILE") - BUNDLE_SIZE_MB=$(echo "scale=2; $BUNDLE_SIZE / 1024 / 1024" | bc -l) - - echo "# React Native Bundle Analysis Report" > bundle-analysis.md - echo "" >> bundle-analysis.md - echo "## Bundle Size Summary" >> bundle-analysis.md - echo "- Platform: Android (React Native)" >> bundle-analysis.md - echo "- Bundle size: **${BUNDLE_SIZE_MB} MB**" >> bundle-analysis.md - echo "- Bundler: Metro (Expo)" >> bundle-analysis.md - echo "" >> bundle-analysis.md - echo "## Bundle Details" >> bundle-analysis.md - echo "- File: $(basename "$BUNDLE_FILE")" >> bundle-analysis.md - echo "- Size: ${BUNDLE_SIZE_MB} MB" >> bundle-analysis.md - - echo "📊 Bundle analysis complete: ${BUNDLE_SIZE_MB} MB" - else - echo "❌ No Android bundle found" - ls -la android-build/ - fi - else - echo "⚠️ Android export failed, analyzing dependencies instead..." - - # Fallback: analyze key dependencies - echo "# React Native Bundle Analysis Report (Dependencies)" > bundle-analysis.md - echo "" >> bundle-analysis.md - echo "## Dependencies Analysis" >> bundle-analysis.md - echo "Bundle creation failed, analyzing key dependencies:" >> bundle-analysis.md - echo "" >> bundle-analysis.md - - # Get sizes of major dependencies - if command -v du >/dev/null 2>&1; then - echo "### Core Dependencies" >> bundle-analysis.md - for dep in react react-native expo @react-navigation; do - if [ -d "node_modules/$dep" ]; then - size=$(du -sh "node_modules/$dep" 2>/dev/null | cut -f1) - echo "- $dep: $size" >> bundle-analysis.md - fi - done - fi - - echo "" >> bundle-analysis.md - echo "Note: Bundle size analysis requires successful export. Check React Native compatibility." >> bundle-analysis.md - fi - - # Install bc for calculations if needed - sudo apt-get update && sudo apt-get install -y bc - - # Display the report - if [ -f "bundle-analysis.md" ]; then - cat bundle-analysis.md - fi - - - name: Upload RN Bundle Analysis Report - if: always() && hashFiles('frontend/bundle-analysis.md') != '' - uses: actions/upload-artifact@v4 - with: - name: rn-bundle-analysis-report - path: frontend/bundle-analysis.md - retention-days: 30 - - - name: RN Bundle Analysis Skipped - if: github.actor == 'dependabot[bot]' - run: echo "📦 React Native bundle analysis skipped for Dependabot PR" diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 254312af..81a9013b 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -1,24 +1,27 @@ name: Run Backend Tests & Analytics on: - pull_request: + pull_request_target: branches: [ main, master, feature/*] - push: - branches: [ main, master ] + workflow_dispatch: jobs: test-backend: + if: contains(github.event.pull_request.labels.*.name, 'run-tests') || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 with: + ref: ${{ github.event.pull_request.head.sha || github.ref }} fetch-depth: 0 # Full history for better diff analysis - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.12' + cache: 'pip' + cache-dependency-path: backend/requirements.txt - name: Install dependencies run: | @@ -66,8 +69,8 @@ jobs: fail_ci_if_error: false verbose: true working-directory: ./ - override_branch: ${{ github.head_ref }} - override_commit: ${{ github.event.pull_request.head.sha }} + override_branch: ${{ github.head_ref || github.ref_name }} + override_commit: ${{ github.event.pull_request.head.sha || github.sha }} - name: Codecov upload skipped for Dependabot if: github.actor == 'dependabot[bot]' diff --git a/frontend/package.json b/frontend/package.json index 39a8d506..202567e8 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -27,7 +27,9 @@ "react-native-web": "^0.20.0" }, "devDependencies": { - "@babel/core": "^7.20.0" + "@babel/core": "^7.20.0", + "metro-visualizer": "^0.7.0", + "@expo/metro-config": "^0.7.1" }, "private": true }