CodeQL #243
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: "CodeQL" | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| schedule: | |
| # Run weekly on Monday at 2:00 UTC | |
| - cron: "0 2 * * 1" | |
| jobs: | |
| analyze: | |
| name: Analyze | |
| runs-on: ${{ matrix.runner }} | |
| permissions: | |
| actions: read | |
| contents: read | |
| security-events: write | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - language: "javascript" | |
| runner: "ubuntu-latest" | |
| - language: "typescript" | |
| runner: "ubuntu-latest" | |
| - language: "kotlin" | |
| runner: "ubuntu-latest" | |
| - language: "swift" | |
| runner: "macos-15" | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v7 | |
| - name: Initialize CodeQL | |
| uses: github/codeql-action/init@v4 | |
| with: | |
| languages: ${{ matrix.language }} | |
| config-file: .github/codeql/codeql-config.yml | |
| # Use the linked CodeQL bundle (renamed from 'latest') | |
| tools: linked | |
| # Autobuild for JavaScript/TypeScript (optional - CodeQL can analyze source directly) | |
| - name: Autobuild (JavaScript/TypeScript) | |
| if: matrix.language == 'javascript' || matrix.language == 'typescript' | |
| uses: github/codeql-action/autobuild@v4 | |
| # Setup for Kotlin (Android) - React Native requires Node.js dependencies | |
| - name: Setup Node.js for Kotlin | |
| if: matrix.language == 'kotlin' | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 20 | |
| cache: "npm" | |
| - name: Cache node_modules for Kotlin | |
| if: matrix.language == 'kotlin' | |
| uses: actions/cache@v5 | |
| with: | |
| path: node_modules | |
| key: ${{ runner.os }}-node-modules-${{ hashFiles('package-lock.json') }} | |
| restore-keys: | | |
| ${{ runner.os }}-node-modules- | |
| - name: Install Node dependencies for Kotlin | |
| if: matrix.language == 'kotlin' | |
| run: npm ci | |
| - name: Setup Java for Kotlin | |
| if: matrix.language == 'kotlin' | |
| uses: actions/setup-java@v5 | |
| with: | |
| distribution: "temurin" | |
| java-version: "17" | |
| cache: "gradle" | |
| - name: Setup Android SDK for Kotlin | |
| if: matrix.language == 'kotlin' | |
| uses: android-actions/setup-android@v4 | |
| - name: Cache Metro bundler for Kotlin | |
| if: matrix.language == 'kotlin' | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/.cache/metro | |
| node_modules/.cache | |
| key: ${{ runner.os }}-metro-${{ hashFiles('package-lock.json', 'metro.config.js', 'babel.config.js') }} | |
| restore-keys: | | |
| ${{ runner.os }}-metro- | |
| - name: Setup Gradle Build Action for Kotlin | |
| if: matrix.language == 'kotlin' | |
| uses: gradle/gradle-build-action@v3 | |
| with: | |
| gradle-version: wrapper | |
| cache-read-only: false | |
| - name: Free up disk space for Kotlin | |
| if: matrix.language == 'kotlin' | |
| run: | | |
| # Free up disk space before building | |
| echo "Disk space before cleanup:" | |
| df -h | |
| # Clean Gradle cache if needed (keep recent entries) | |
| if [ -d ~/.gradle/caches ]; then | |
| echo "Cleaning old Gradle cache entries..." | |
| find ~/.gradle/caches -type f -atime +7 -delete 2>/dev/null || true | |
| find ~/.gradle/caches -type d -empty -delete 2>/dev/null || true | |
| fi | |
| # Clean Android build directories from previous runs | |
| if [ -d android/app/build ]; then | |
| echo "Cleaning previous Android build artifacts..." | |
| rm -rf android/app/build/outputs || true | |
| rm -rf android/app/build/intermediates/merged_assets || true | |
| rm -rf android/app/build/intermediates/merged_res || true | |
| fi | |
| echo "Disk space after cleanup:" | |
| df -h | |
| - name: Build for CodeQL (Kotlin) | |
| if: matrix.language == 'kotlin' | |
| run: | | |
| # Build Android project for CodeQL analysis | |
| # CodeQL needs to trace source files during build from repository root | |
| # Optimized for minimal disk space: only debug variant, single architecture | |
| # List source files first to verify they exist | |
| echo "Kotlin source files:" | |
| find android/app/src/main -name "*.kt" || echo "No Kotlin source files found" | |
| # Build the app module's debug variant with single architecture (arm64-v8a) | |
| # This ensures CodeQL can trace Kotlin source files during compilation | |
| # We use assembleDebug to build the full module, but limit to single architecture | |
| # CodeQL's build tracer will automatically intercept compiler invocations | |
| # Building from repository root ensures CodeQL can properly trace file paths | |
| cd android | |
| ./gradlew :app:assembleDebug \ | |
| -PreactNativeArchitectures=arm64-v8a \ | |
| --parallel \ | |
| --build-cache \ | |
| -Dorg.gradle.caching=true \ | |
| -Dorg.gradle.parallel=true \ | |
| -Dorg.gradle.configureondemand=true \ | |
| -Dorg.gradle.daemon=false \ | |
| --no-daemon | |
| cd .. | |
| # Verify Kotlin files were compiled (this is critical for CodeQL) | |
| echo "Checking for compiled Kotlin classes..." | |
| KOTLIN_CLASSES=$(find android/app/build -name "*.class" -path "*/kotlin/*" | wc -l) | |
| JAVA_CLASSES=$(find android/app/build -name "*.class" -path "*/java/*" | wc -l) | |
| echo "Found $KOTLIN_CLASSES Kotlin classes and $JAVA_CLASSES Java classes" | |
| if [ "$KOTLIN_CLASSES" -eq 0 ] && [ "$JAVA_CLASSES" -eq 0 ]; then | |
| echo "ERROR: No compiled classes found! CodeQL will not be able to analyze the code." | |
| echo "Build output directories:" | |
| ls -la android/app/build/ || true | |
| exit 1 | |
| fi | |
| # Show some example compiled classes | |
| echo "Sample compiled classes:" | |
| find android/app/build -name "*.class" -path "*/kotlin/*" | head -5 || true | |
| find android/app/build -name "*.class" -path "*/java/*" | head -5 || true | |
| # Clean up large artifacts after compilation (keep classes for CodeQL) | |
| echo "Cleaning up large build artifacts..." | |
| find android/app/build -name "*.apk" -delete 2>/dev/null || true | |
| find android/app/build -name "*.aab" -delete 2>/dev/null || true | |
| find android/app/build -path "*/merged_assets/*" -delete 2>/dev/null || true | |
| find android/app/build -path "*/merged_res/*" -delete 2>/dev/null || true | |
| echo "Final disk space:" | |
| df -h | |
| # Setup for Swift (iOS) - React Native requires Node.js and CocoaPods | |
| - name: Setup Node.js for Swift | |
| if: matrix.language == 'swift' | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 20 | |
| cache: "npm" | |
| - name: Cache node_modules for Swift | |
| if: matrix.language == 'swift' | |
| uses: actions/cache@v5 | |
| with: | |
| path: node_modules | |
| key: ${{ runner.os }}-node-modules-${{ hashFiles('package-lock.json') }} | |
| restore-keys: | | |
| ${{ runner.os }}-node-modules- | |
| - name: Install Node dependencies for Swift | |
| if: matrix.language == 'swift' | |
| run: npm ci | |
| - name: Setup Ruby and Bundler for Swift | |
| if: matrix.language == 'swift' | |
| uses: ruby/setup-ruby@v1 | |
| with: | |
| ruby-version: "3.2" | |
| bundler-cache: true | |
| - name: Setup Xcode for Swift | |
| if: matrix.language == 'swift' | |
| uses: maxim-lobanov/setup-xcode@v1 | |
| with: | |
| xcode-version: "26.0" | |
| - name: Cache CocoaPods for Swift | |
| if: matrix.language == 'swift' | |
| uses: actions/cache@v5 | |
| with: | |
| path: ios/Pods | |
| key: ${{ runner.os }}-pods-v2-${{ hashFiles('ios/Podfile.lock') }}-${{ hashFiles('ios/Podfile') }} | |
| restore-keys: | | |
| ${{ runner.os }}-pods-v2-${{ hashFiles('ios/Podfile.lock') }}- | |
| ${{ runner.os }}-pods-v2- | |
| - name: Cache CocoaPods cache for Swift | |
| if: matrix.language == 'swift' | |
| uses: actions/cache@v5 | |
| with: | |
| path: ~/Library/Caches/CocoaPods | |
| key: ${{ runner.os }}-cocoapods-cache-v2-${{ hashFiles('ios/Podfile.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cocoapods-cache-v2- | |
| - name: Cache Xcode Derived Data for Swift | |
| if: matrix.language == 'swift' | |
| uses: actions/cache@v5 | |
| with: | |
| path: ios/build | |
| key: ${{ runner.os }}-xcode-deriveddata-${{ hashFiles('ios/**/*.swift', 'ios/**/*.m', 'ios/**/*.h', 'ios/Podfile.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-xcode-deriveddata- | |
| - name: Install iOS pods for Swift | |
| if: matrix.language == 'swift' | |
| working-directory: ios | |
| run: | | |
| EXPECTED_VERSION=$(cat ../.cocoapods-version | tr -d '[:space:]') | |
| ACTUAL_VERSION=$(bundle exec pod --version) | |
| echo "Expected CocoaPods version: $EXPECTED_VERSION" | |
| echo "Actual CocoaPods version: $ACTUAL_VERSION" | |
| if [ "$ACTUAL_VERSION" != "$EXPECTED_VERSION" ]; then | |
| echo "CocoaPods version mismatch. Updating to $EXPECTED_VERSION..." | |
| bundle update cocoapods | |
| ACTUAL_VERSION=$(bundle exec pod --version) | |
| echo "Updated CocoaPods version: $ACTUAL_VERSION" | |
| if [ "$ACTUAL_VERSION" != "$EXPECTED_VERSION" ]; then | |
| echo "Error: Failed to update CocoaPods. Expected $EXPECTED_VERSION but got $ACTUAL_VERSION" | |
| exit 1 | |
| fi | |
| fi | |
| # Clear local podspecs cache to avoid version mismatches | |
| if [ -d "Pods/Local Podspecs" ]; then | |
| echo "Clearing local podspecs cache..." | |
| rm -rf "Pods/Local Podspecs" | |
| fi | |
| # Try pod install first | |
| if ! bundle exec pod install --repo-update; then | |
| echo "Pod install failed, attempting to update hermes-engine..." | |
| # Update hermes-engine specifically to resolve version mismatch | |
| bundle exec pod update hermes-engine --no-repo-update || true | |
| # Retry pod install | |
| echo "Retrying pod install..." | |
| bundle exec pod install --repo-update | |
| fi | |
| - name: Build for CodeQL (Swift) | |
| if: matrix.language == 'swift' | |
| run: | | |
| # Build the iOS workspace for CodeQL analysis | |
| # Optimized for speed: Debug configuration, parallel builds, single architecture | |
| # CodeQL can analyze Swift source code directly, but building ensures code compiles | |
| # Debug is much faster than Release (no optimizations) and sufficient for static analysis | |
| # Get available simulator (prefer x86_64 for faster builds on Intel runners) | |
| SIMULATOR_DEVICE=$(xcrun simctl list devices available | grep -i "iPhone.*x86_64\|iPhone.*Simulator" | head -1 | sed -n 's/.* (\([0-9A-Fa-f-]\{36\}\)) .*/\1/p') | |
| # Fallback to any available iPhone simulator | |
| [ -z "$SIMULATOR_DEVICE" ] && SIMULATOR_DEVICE=$(xcrun simctl list devices available | grep "^ iPhone" | sed -n 's/.* (\([0-9A-Fa-f-]\{36\}\)) .*/\1/p' | head -1) | |
| # Final fallback: any iOS simulator | |
| [ -z "$SIMULATOR_DEVICE" ] && SIMULATOR_DEVICE=$(xcrun simctl list devices available | sed -n 's/.* (\([0-9A-Fa-f-]\{36\}\)) .*/\1/p' | head -1) | |
| if [ -z "$SIMULATOR_DEVICE" ]; then | |
| echo "No simulators found, building without specific destination" | |
| xcodebuild \ | |
| -workspace ios/WorkTrack.xcworkspace \ | |
| -scheme WorkTrack \ | |
| -configuration Debug \ | |
| -sdk iphonesimulator \ | |
| -derivedDataPath ios/build \ | |
| -parallelizeTargets \ | |
| -jobs 4 \ | |
| ONLY_ACTIVE_ARCH=YES \ | |
| CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY="" \ | |
| build \ | |
| 2>&1 | grep -v -E "(warning:|note:)" || true | |
| else | |
| echo "Using simulator UDID: $SIMULATOR_DEVICE" | |
| xcodebuild \ | |
| -workspace ios/WorkTrack.xcworkspace \ | |
| -scheme WorkTrack \ | |
| -configuration Debug \ | |
| -sdk iphonesimulator \ | |
| -destination "platform=iOS Simulator,id=$SIMULATOR_DEVICE" \ | |
| -derivedDataPath ios/build \ | |
| -parallelizeTargets \ | |
| -jobs 4 \ | |
| ONLY_ACTIVE_ARCH=YES \ | |
| CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY="" \ | |
| build \ | |
| 2>&1 | grep -v -E "(warning:|note:)" || true | |
| fi | |
| # Clean up large build artifacts after compilation (keep compiled objects for CodeQL) | |
| echo "Cleaning up large build artifacts..." | |
| find ios/build -name "*.app" -type d -exec rm -rf {} + 2>/dev/null || true | |
| find ios/build -name "*.dSYM" -type d -exec rm -rf {} + 2>/dev/null || true | |
| find ios/build -name "*.ipa" -delete 2>/dev/null || true | |
| - name: Perform CodeQL Analysis | |
| uses: github/codeql-action/analyze@v4 | |
| with: | |
| category: "/language:${{ matrix.language }}" |