perf(cookies): cache strategy singletons at module level #482
Workflow file for this run
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: CI | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - "release/**" | |
| - "feature/**" | |
| - "fix/**" | |
| - "refactor/**" | |
| - "feat/**" | |
| - "docs/**" | |
| pull_request: | |
| branches: | |
| - main | |
| - "release/**" | |
| workflow_dispatch: | |
| env: | |
| HOMEBREW_NO_AUTO_UPDATE: 1 | |
| jobs: | |
| # Detect what files changed to optimize CI | |
| changes: | |
| name: Detect Changes | |
| runs-on: ubuntu-latest | |
| outputs: | |
| docs-only: ${{ steps.filter.outputs.docs-only }} | |
| has-code: ${{ steps.filter.outputs.has-code }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Detect file changes | |
| uses: dorny/paths-filter@v3 | |
| id: filter | |
| with: | |
| filters: | | |
| has-code: | |
| - 'src/**' | |
| - 'scripts/**' | |
| - 'package.json' | |
| - 'pnpm-lock.yaml' | |
| - 'tsconfig*.json' | |
| - 'jest.config.js' | |
| - 'biome.json' | |
| - '.github/workflows/**' | |
| docs-only: | |
| - 'docs/**' | |
| - '**/*.md' | |
| - 'scripts/check-vitepress-links.sh' | |
| - '!src/**' | |
| - '!package.json' | |
| - '!pnpm-lock.yaml' | |
| - '!tsconfig*.json' | |
| - '!jest.config.js' | |
| - '!biome.json' | |
| # Quick validation that runs on all platforms - runs lighter for docs-only | |
| validate: | |
| name: Validate (${{ matrix.os }}, Node ${{ matrix.node }}) | |
| runs-on: ${{ matrix.os }} | |
| needs: changes | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest, windows-latest] | |
| node: [20.x] | |
| include: | |
| # Additional Node versions only on Ubuntu for faster CI | |
| - os: ubuntu-latest | |
| node: 22.x | |
| - os: ubuntu-latest | |
| node: 24.x | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Report optimization | |
| if: needs.changes.outputs.docs-only == 'true' | |
| run: | | |
| echo "📚 Documentation-only changes detected - running lightweight validation" | |
| echo "Skipping: tests, type-check, heavy builds" | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| version: 9.15.2 | |
| - name: Setup Node.js ${{ matrix.node }} | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ matrix.node }} | |
| cache: "pnpm" | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| # Type check - skip for docs-only | |
| - name: Type check | |
| if: needs.changes.outputs.has-code == 'true' | |
| run: pnpm run type-check | |
| - name: Type check (skipped for docs) | |
| if: needs.changes.outputs.docs-only == 'true' | |
| run: echo "✅ Skipping type check for documentation-only changes" | |
| # Lint - always run but lighter for docs | |
| - name: Lint | |
| if: needs.changes.outputs.has-code == 'true' | |
| run: pnpm run lint | |
| continue-on-error: ${{ matrix.os == 'windows-latest' }} | |
| - name: Lint docs only | |
| if: needs.changes.outputs.docs-only == 'true' | |
| run: | | |
| echo "✅ Running format check for documentation files" | |
| pnpm run format:check || true | |
| # Format check | |
| - name: Format check | |
| run: pnpm run format:check | |
| continue-on-error: ${{ matrix.os == 'windows-latest' }} | |
| # Tests - skip for docs-only | |
| - name: Run tests | |
| if: needs.changes.outputs.has-code == 'true' | |
| run: pnpm test | |
| - name: Run tests (skipped for docs) | |
| if: needs.changes.outputs.docs-only == 'true' | |
| run: echo "✅ Skipping tests for documentation-only changes" | |
| # Build - skip heavy build for docs-only | |
| - name: Build | |
| if: needs.changes.outputs.has-code == 'true' | |
| run: pnpm run build | |
| - name: Build (lightweight for docs) | |
| if: needs.changes.outputs.docs-only == 'true' | |
| run: | | |
| echo "✅ Skipping full build for documentation-only changes" | |
| # Just ensure the package.json is valid | |
| node -e "require('./package.json')" | |
| - name: Upload coverage | |
| uses: actions/upload-artifact@v4 | |
| if: matrix.os == 'ubuntu-latest' && matrix.node == '20.x' && needs.changes.outputs.has-code == 'true' | |
| with: | |
| name: coverage-reports | |
| path: coverage/ | |
| retention-days: 7 | |
| # Advanced tests only run on macOS where they're most relevant | |
| advanced-tests: | |
| name: Advanced Tests (Node ${{ matrix.node }}) | |
| runs-on: macos-latest | |
| needs: [changes, validate] | |
| if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| node: [20.x, 22.x] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| # Quick pass for docs-only changes | |
| - name: Skip advanced tests for docs | |
| if: needs.changes.outputs.docs-only == 'true' | |
| run: | | |
| echo "📚 Documentation-only changes - skipping advanced tests" | |
| echo "✅ Marking as passed" | |
| exit 0 | |
| # Run actual tests only for code changes | |
| - name: Setup pnpm | |
| if: needs.changes.outputs.has-code == 'true' | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| version: 9.15.2 | |
| - name: Setup Node.js ${{ matrix.node }} | |
| if: needs.changes.outputs.has-code == 'true' | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ matrix.node }} | |
| cache: "pnpm" | |
| - name: Install dependencies | |
| if: needs.changes.outputs.has-code == 'true' | |
| run: pnpm install --frozen-lockfile | |
| - name: Build first | |
| if: needs.changes.outputs.has-code == 'true' | |
| run: pnpm run build | |
| - name: Run binary cookies test | |
| if: needs.changes.outputs.has-code == 'true' | |
| run: pnpm exec tsx scripts/test-binarycookies.ts | |
| continue-on-error: true | |
| - name: Run decoder test | |
| if: needs.changes.outputs.has-code == 'true' | |
| run: pnpm exec tsx scripts/test-decoder.ts | |
| continue-on-error: true | |
| - name: Validate cookie structure | |
| if: needs.changes.outputs.has-code == 'true' | |
| run: pnpm exec tsx scripts/validate-cookie-structure.ts | |
| continue-on-error: true | |
| # Platform-specific integration tests with real browsers | |
| integration-tests: | |
| name: Integration Tests (${{ matrix.os }}) | |
| runs-on: ${{ matrix.os }} | |
| needs: [changes, validate] | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [windows-latest, macos-latest] | |
| node: [20.x] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| # Quick pass for docs-only changes | |
| - name: Skip integration tests for docs | |
| if: needs.changes.outputs.docs-only == 'true' | |
| run: | | |
| echo "📚 Documentation-only changes - skipping integration tests" | |
| echo "✅ Marking as passed" | |
| exit 0 | |
| # Run actual tests only for code changes | |
| - name: Setup pnpm | |
| if: needs.changes.outputs.has-code == 'true' | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| version: 9.15.2 | |
| - name: Setup Node.js ${{ matrix.node }} | |
| if: needs.changes.outputs.has-code == 'true' | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ matrix.node }} | |
| cache: "pnpm" | |
| - name: Install dependencies | |
| if: needs.changes.outputs.has-code == 'true' | |
| run: pnpm install --frozen-lockfile | |
| - name: Build | |
| if: needs.changes.outputs.has-code == 'true' | |
| run: pnpm run build | |
| - name: Install Chrome (Windows) | |
| if: runner.os == 'Windows' && needs.changes.outputs.has-code == 'true' | |
| uses: nick-invision/retry@v2 | |
| with: | |
| timeout_minutes: 10 | |
| max_attempts: 2 | |
| shell: pwsh | |
| command: | | |
| Write-Host "Installing Chromium via Chocolatey..." | |
| choco install chromium -y --no-progress | |
| Start-Sleep -Seconds 10 | |
| # Verify installation | |
| $chromiumPath = "C:\Program Files\Chromium\Application\chrome.exe" | |
| if (Test-Path $chromiumPath) { | |
| Write-Host "✓ Chromium installed successfully at: $chromiumPath" | |
| & "$chromiumPath" --version | |
| } else { | |
| Write-Host "✗ Chromium installation failed" | |
| exit 1 | |
| } | |
| - name: Generate test cookies (Windows) | |
| if: runner.os == 'Windows' && needs.changes.outputs.has-code == 'true' | |
| uses: nick-invision/retry@v2 | |
| with: | |
| timeout_minutes: 5 | |
| max_attempts: 3 | |
| shell: pwsh | |
| command: | | |
| $chromeDir = "$env:LOCALAPPDATA\Google\Chrome\User Data\Default" | |
| Write-Host "Creating Chrome user data directory: $chromeDir" | |
| New-Item -ItemType Directory -Force -Path $chromeDir | Out-Null | |
| $chromiumPath = "C:\Program Files\Chromium\Application\chrome.exe" | |
| if (Test-Path $chromiumPath) { | |
| Write-Host "Launching Chromium in headless mode to generate cookies..." | |
| # Run Chrome headless to generate cookies | |
| $process = Start-Process -FilePath $chromiumPath -ArgumentList @( | |
| "--headless=new", | |
| "--disable-gpu", | |
| "--no-sandbox", | |
| "--disable-dev-shm-usage", | |
| "--user-data-dir=$env:LOCALAPPDATA\Google\Chrome\User Data", | |
| "https://github.com", | |
| "--timeout=20000" | |
| ) -PassThru -Wait -NoNewWindow | |
| Start-Sleep -Seconds 5 | |
| # Verify cookies were generated | |
| $cookieDb = "$chromeDir\Cookies" | |
| $localState = "$env:LOCALAPPDATA\Google\Chrome\User Data\Local State" | |
| if (Test-Path $cookieDb) { | |
| $size = (Get-Item $cookieDb).Length | |
| Write-Host "✓ Cookie database created: $cookieDb ($size bytes)" | |
| } else { | |
| Write-Host "⚠ Cookie database not found at: $cookieDb" | |
| } | |
| if (Test-Path $localState) { | |
| Write-Host "✓ Local State file exists: $localState" | |
| } else { | |
| Write-Host "⚠ Local State file not found" | |
| } | |
| } else { | |
| Write-Host "✗ Chromium not found at: $chromiumPath" | |
| exit 1 | |
| } | |
| - name: Generate programmatic test fixtures (Windows) | |
| if: runner.os == 'Windows' && needs.changes.outputs.has-code == 'true' | |
| run: | | |
| Write-Host "Generating programmatic test fixtures with v10 encryption..." | |
| # Create test databases using our fixture utilities | |
| node -e " | |
| const path = require('path'); | |
| const { createTestDatabases } = require('./dist/index.cjs'); | |
| // This would use our new fixture generation if exported | |
| console.log('Test fixture utilities loaded successfully'); | |
| " 2>$null || Write-Host "Note: Fixture utilities not yet exported from main package" | |
| Write-Host "✓ Programmatic fixture generation complete" | |
| shell: pwsh | |
| continue-on-error: true | |
| - name: Validate Windows test environment | |
| if: runner.os == 'Windows' && needs.changes.outputs.has-code == 'true' | |
| run: | | |
| Write-Host "=== Windows Test Environment Validation ===" | |
| # Check Chrome user data | |
| $chromeDir = "$env:LOCALAPPDATA\Google\Chrome\User Data" | |
| if (Test-Path $chromeDir) { | |
| Write-Host "✓ Chrome User Data directory exists" | |
| Get-ChildItem $chromeDir -Recurse -File | | |
| Where-Object { $_.Name -match "Cookies|Local State" } | | |
| ForEach-Object { | |
| Write-Host " - $($_.FullName) ($($_.Length) bytes)" | |
| } | |
| } else { | |
| Write-Host "⚠ Chrome User Data directory not found" | |
| } | |
| Write-Host "" | |
| Write-Host "=== Validation Complete ===" | |
| shell: pwsh | |
| - name: Test CLI (All platforms) | |
| if: needs.changes.outputs.has-code == 'true' | |
| run: | | |
| echo "=== Testing CLI ===" | |
| node dist/cli.cjs --help | |
| echo "" | |
| echo "=== Testing Chrome cookie extraction ===" | |
| node dist/cli.cjs --browser chrome "*" github.com || echo "Note: Cookie extraction may fail without real browser cookies" | |
| shell: bash | |
| # Documentation build - always thorough | |
| docs: | |
| name: Build Documentation | |
| permissions: | |
| contents: read | |
| runs-on: ubuntu-latest | |
| needs: [changes, validate] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| version: 9.15.2 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20.x | |
| cache: "pnpm" | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Check documentation links | |
| run: pnpm run check-links | |
| - name: Build documentation | |
| run: pnpm run docs | |
| - name: Upload documentation artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: documentation | |
| path: docs/.vitepress/dist/ | |
| retention-days: 7 | |
| - name: Report optimization | |
| if: needs.changes.outputs.docs-only == 'true' | |
| run: | | |
| echo "### 🚀 CI Optimization Applied!" | |
| echo "Documentation-only changes detected. Heavy tests and builds were skipped." | |
| echo "" | |
| echo "**Time saved:** ~10-15 minutes" | |
| echo "**Resources saved:** 6 parallel test runners" | |
| # Final status check for branch protection | |
| status-check: | |
| permissions: | |
| contents: read | |
| name: CI Status | |
| runs-on: ubuntu-latest | |
| needs: [validate, docs] | |
| if: always() | |
| steps: | |
| - name: Check status | |
| run: | | |
| if [[ "${{ needs.validate.result }}" != "success" || "${{ needs.docs.result }}" != "success" ]]; then | |
| echo "Required checks failed" | |
| exit 1 | |
| fi | |
| echo "All required checks passed" |