[Docs] Migrate API Docs to Scalar #4873
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
| # This workflow will build the project on pull requests with tests | |
| # Uses: | |
| # OS: ubuntu-latest | |
| # Go: go 1.x | |
| name: 👷🛠️ PR Builder | |
| on: | |
| pull_request: | |
| workflow_dispatch: | |
| env: | |
| GOFLAGS: "-mod=readonly" | |
| jobs: | |
| security-audit: | |
| name: 🔒 Security Audit | |
| if: ${{ github.event_name == 'pull_request' }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: 📥 Checkout Code | |
| uses: actions/checkout@v4 | |
| - name: ⚙️ Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 'lts/*' | |
| - name: 📦 Install pnpm | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| version: 'latest' | |
| run_install: false | |
| - name: 🔍 Run pnpm audit (Frontend) | |
| working-directory: frontend | |
| run: | | |
| echo "🔍 Running pnpm audit for frontend dependencies..." | |
| pnpm audit --audit-level=high | |
| - name: 🔍 Run npm audit (E2E Tests) | |
| working-directory: tests/e2e | |
| run: | | |
| echo "🔍 Running npm audit for E2E test dependencies..." | |
| npm audit --audit-level=high | |
| - name: 🔍 Run npm audit (Sample Apps) | |
| run: | | |
| echo "🔍 Running npm audit for sample app dependencies..." | |
| for app in samples/apps/*/; do | |
| if [ -f "${app}package-lock.json" ]; then | |
| echo "Auditing $app..." | |
| cd "$app" | |
| npm audit --audit-level=high | |
| cd - > /dev/null | |
| fi | |
| done | |
| dependency-review: | |
| name: 🔎 Dependency Review | |
| if: ${{ github.event_name == 'pull_request' }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| steps: | |
| - name: 📥 Checkout Code | |
| uses: actions/checkout@v4 | |
| - name: 🔎 Dependency Review | |
| uses: actions/dependency-review-action@v4 | |
| with: | |
| fail-on-severity: high | |
| deny-licenses: GPL-3.0-only,GPL-3.0-or-later,AGPL-3.0-only,AGPL-3.0-or-later | |
| comment-summary-in-pr: always | |
| lint: | |
| name: 🧹 Lint Code | |
| if: ${{ github.event_name == 'pull_request' }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: 📥 Checkout Code | |
| uses: actions/checkout@v4 | |
| with: | |
| # We need to fetch all branches and commits so that Nx affected has a base to compare against. | |
| fetch-depth: 0 | |
| - name: ⚙️ Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 'lts/*' | |
| - name: 🐳 Set SHAs for Nx | |
| id: set-shas | |
| uses: nrwl/nx-set-shas@v3 | |
| with: | |
| main-branch-name: "main" | |
| - name: 📦 Install pnpm | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| version: 'latest' | |
| run_install: false | |
| cache: true | |
| cache-dependency-path: frontend/pnpm-lock.yaml | |
| - name: ⚙️ Set up Go Environment | |
| uses: ./.github/actions/setup-go | |
| - name: 📦 Prepare golangci-lint Locally | |
| run: make golangci-lint | |
| - name: 🔍 Run Backend Linter | |
| run: make lint_backend | |
| - name: 🧩 Install Dependencies & Build Frontend | |
| run: | | |
| cd frontend | |
| pnpm install --frozen-lockfile | |
| pnpm build | |
| - name: 🔍 Run Frontend Linter | |
| run: | | |
| cd frontend | |
| pnpm nx affected --target=lint --parallel=3 --base=${{ env.NX_BASE }} --head=${{ env.NX_HEAD }} | |
| build: | |
| name: 🛠️ Build Product | |
| if: ${{ github.event.label.name == 'trigger-pr-builder' || github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request'}} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: 📥 Checkout Code | |
| uses: actions/checkout@v4 | |
| - name: ⚙️ Set up Go Environment | |
| uses: ./.github/actions/setup-go | |
| - name: ⚙️ Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 'lts/*' | |
| - name: 📦 Install pnpm | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| version: 'latest' | |
| run_install: false | |
| cache-dependency-path: frontend/pnpm-lock.yaml | |
| - name: 🗄️ Cache Go Modules | |
| uses: actions/cache@v4 | |
| id: cache-go-modules | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-go-modules-${{ hashFiles('**/go.sum') }} | |
| restore-keys: | | |
| ${{ runner.os }}-go-modules- | |
| - name: 📦 Install Backend Dependencies | |
| run: | | |
| cd backend | |
| go mod download | |
| cd ../tests/integration | |
| go mod download | |
| - name: 📦 Install Frontend Dependencies | |
| run: | | |
| cd frontend | |
| pnpm install --frozen-lockfile | |
| - name: 🧹 Clean Previous Builds | |
| run: | | |
| set -e | |
| make clean | |
| - name: 🔨 Build Frontend | |
| run: | | |
| cd frontend | |
| pnpm build | |
| - name: 🔨 Build Product with Coverage | |
| run: | | |
| set -e | |
| export LOG_LEVEL=debug | |
| make build_with_coverage_only OS=$(go env GOOS) ARCH=$(go env GOARCH) | |
| # Find the built distribution | |
| DIST_PATH=$(find target/dist -name "thunder-*.zip" | head -1) | |
| echo "Built distribution: $DIST_PATH" | |
| - name: 🧪 Run Frontend Tests with Coverage | |
| run: | | |
| cd frontend/apps/thunder-develop | |
| pnpm test:coverage | |
| - name: 🧪 Run Thunder-Gate Tests with Coverage | |
| run: | | |
| cd frontend/apps/thunder-gate | |
| pnpm test:coverage | |
| - name: 📦 Upload Built Distribution | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: thunder-distribution | |
| path: target/dist/*.zip | |
| if-no-files-found: error | |
| - name: 📊 Upload Unit Test Coverage Report to Codecov | |
| uses: codecov/codecov-action@v4 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: backend/coverage_unit.out | |
| disable_search: true | |
| flags: backend-unit | |
| name: Backend Unit Tests | |
| fail_ci_if_error: false | |
| - name: 📦 Archive Unit Coverage Report | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: unit-coverage-report | |
| path: backend/coverage_unit.out | |
| if-no-files-found: error | |
| - name: 📊 Upload `@thunder/develop` Unit Test Coverage Report to Codecov | |
| uses: codecov/codecov-action@v4 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: frontend/apps/thunder-develop/coverage/lcov.info | |
| disable_search: true | |
| flags: frontend-apps-develop-unit | |
| name: Frontend Develop App Unit Tests | |
| fail_ci_if_error: false | |
| - name: 📊 Upload `@thunder/gate` Unit Test Coverage Report to Codecov | |
| uses: codecov/codecov-action@v4 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: frontend/apps/thunder-gate/coverage/lcov.info | |
| disable_search: true | |
| flags: frontend-apps-gate-unit | |
| name: Frontend Gate App Unit Tests | |
| fail_ci_if_error: false | |
| build_samples: | |
| name: 🛠️ Build Sample Apps | |
| if: ${{ github.event.label.name == 'trigger-pr-builder' || github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request'}} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: 📥 Checkout Code | |
| uses: actions/checkout@v4 | |
| - name: ⚙️ Set up Go Environment | |
| uses: ./.github/actions/setup-go | |
| - name: ⚙️ Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 'lts/*' | |
| - name: 📦 Install pnpm | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| version: 'latest' | |
| run_install: false | |
| cache-dependency-path: frontend/pnpm-lock.yaml | |
| - name: 🧩 Build and Package Sample Apps | |
| run: | | |
| make build_samples | |
| make package_samples OS=$(go env GOOS) ARCH=$(go env GOARCH) | |
| - name: 📦 Upload Built Sample App | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: sample-app-react-sdk | |
| path: target/dist/sample-app-react-sdk-*.zip | |
| test-integration: | |
| name: 🧪 Integration Tests (${{ matrix.database }}) | |
| needs: build | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| database: [sqlite, postgres] | |
| fail-fast: false | |
| services: | |
| postgres: | |
| image: postgres:latest | |
| env: | |
| POSTGRES_USER: asgthunder | |
| POSTGRES_PASSWORD: asgthunder | |
| POSTGRES_DB: thunderdb | |
| ports: | |
| - 5432:5432 | |
| options: >- | |
| --health-cmd pg_isready | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| steps: | |
| - name: 📥 Checkout Code | |
| uses: actions/checkout@v4 | |
| - name: ⚙️ Set up Go Environment | |
| uses: ./.github/actions/setup-go | |
| - name: 📥 Download Unit Coverage Report | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: unit-coverage-report | |
| path: backend/ | |
| - name: 🗄️ Cache Go Modules | |
| uses: actions/cache@v4 | |
| id: cache-go-modules | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-go-modules-${{ hashFiles('**/go.sum') }} | |
| restore-keys: | | |
| ${{ runner.os }}-go-modules- | |
| - name: 📦 Install Dependencies | |
| run: | | |
| cd backend | |
| go mod download | |
| cd ../tests/integration | |
| go mod download | |
| - name: 📝 Configure Test Database | |
| run: | | |
| chmod +x tests/integration/resources/scripts/setup-test-config.sh | |
| ./tests/integration/resources/scripts/setup-test-config.sh | |
| env: | |
| DB_TYPE: ${{ matrix.database }} | |
| - name: 🧪 Run Integration Tests (${{ matrix.database }}) | |
| uses: ./.github/actions/run-integration-tests | |
| with: | |
| database-type: ${{ matrix.database }} | |
| coverage-enabled: true | |
| - name: 📊 Upload Integration Test Coverage Report to Codecov | |
| uses: codecov/codecov-action@v4 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: target/coverage_integration.out | |
| disable_search: true | |
| flags: backend-integration-${{ matrix.database }} | |
| name: Backend Integration Tests (${{ matrix.database }}) | |
| fail_ci_if_error: false | |
| # - name: 🧩 Generate Combined Coverage Report | |
| # run: ./build.sh merge_coverage | |
| # - name: 📊 Upload Combined Coverage Report to Codecov | |
| # uses: codecov/codecov-action@v4 | |
| # with: | |
| # token: ${{ secrets.CODECOV_TOKEN }} | |
| # files: target/coverage_combined.out | |
| # disable_search: true | |
| # flags: backend-combined-${{ matrix.database }} | |
| # name: Backend-combined Coverage (${{ matrix.database }}) | |
| # fail_ci_if_error: false | |
| test-e2e: | |
| name: 🎭 Playwright E2E Tests | |
| needs: [build, build_samples] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: 📥 Checkout Code | |
| uses: actions/checkout@v4 | |
| - name: ⚙️ Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 'lts/*' | |
| - name: 📥 Download Built Distribution | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: thunder-distribution | |
| path: target/dist/ | |
| - name: 📥 Download Built Sample App | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: sample-app-react-sdk | |
| path: target/dist/ | |
| - name: 📂 Extract Server to E2E | |
| run: | | |
| mkdir -p tests/e2e/thunder-server | |
| unzip target/dist/thunder-*.zip -d tests/e2e/thunder-server | |
| cd tests/e2e/thunder-server | |
| # Find the extracted folder (name includes version and arch) and move its contents to the root of tests/e2e/thunder-server | |
| EXTRACTED_DIR=$(find . -maxdepth 1 -type d -name "thunder-*" | head -n 1) | |
| if [ -n "$EXTRACTED_DIR" ]; then | |
| mv "$EXTRACTED_DIR"/* . | |
| rmdir "$EXTRACTED_DIR" | |
| fi | |
| chmod +x setup.sh start.sh | |
| - name: 🚀 Start Thunder Server | |
| run: | | |
| cd tests/e2e/thunder-server | |
| ./setup.sh | |
| THUNDER_SKIP_SECURITY=true ./start.sh & | |
| THUNDER_PID=$! | |
| echo "THUNDER_PID=$THUNDER_PID" >> $GITHUB_ENV | |
| # Wait for server to be ready | |
| echo "Waiting for server to be ready on https://localhost:8090..." | |
| for i in {1..60}; do | |
| if curl -s -k https://localhost:8090/health/liveness > /dev/null; then | |
| echo "Server is UP!" | |
| break | |
| fi | |
| echo "Still waiting ($i/60)..." | |
| sleep 2 | |
| done | |
| # Verify server is actually running | |
| if ! curl -s -k https://localhost:8090/health/liveness > /dev/null; then | |
| echo "Server failed to start within 2 minutes" | |
| exit 1 | |
| fi | |
| echo "Server started successfully!" | |
| - name: 🔍 Extract Sample App ID | |
| id: extract-app-id | |
| run: | | |
| echo "Fetching applications from Thunder..." | |
| # Get applications list | |
| APPS_RESPONSE=$(curl -s -k https://localhost:8090/applications) | |
| # Extract Sample App ID using jq | |
| SAMPLE_APP_ID=$(echo "$APPS_RESPONSE" | jq -r '.applications[] | select(.name == "Sample App") | .id') | |
| if [ -z "$SAMPLE_APP_ID" ] || [ "$SAMPLE_APP_ID" == "null" ]; then | |
| echo "⚠️ Warning: Sample App not found in applications list" | |
| echo "Available applications:" | |
| echo "$APPS_RESPONSE" | jq -r '.applications[] | " - \(.name) (\(.id))"' | |
| echo "sample_app_id=" >> $GITHUB_OUTPUT | |
| else | |
| echo "✓ Sample App ID extracted: $SAMPLE_APP_ID" | |
| echo "sample_app_id=$SAMPLE_APP_ID" >> $GITHUB_OUTPUT | |
| fi | |
| - name: 🔄 Restart Thunder Server with Security Enabled | |
| run: | | |
| cd tests/e2e/thunder-server | |
| echo "Stopping Thunder server..." | |
| # Kill the specific Thunder server process using captured PID | |
| kill $THUNDER_PID || true | |
| # Wait for process to fully terminate | |
| sleep 5 | |
| echo "Starting Thunder server with security enabled..." | |
| ./start.sh & | |
| THUNDER_PID=$! | |
| echo "THUNDER_PID=$THUNDER_PID" >> $GITHUB_ENV | |
| # Wait for server to be ready | |
| echo "Waiting for server to be ready on https://localhost:8090..." | |
| for i in {1..60}; do | |
| if curl -s -k https://localhost:8090/health/liveness > /dev/null; then | |
| echo "Server is UP with security enabled!" | |
| break | |
| fi | |
| echo "Still waiting ($i/60)..." | |
| sleep 2 | |
| done | |
| # Verify server is actually running | |
| if ! curl -s -k https://localhost:8090/health/liveness > /dev/null; then | |
| echo "Server failed to restart within 2 minutes" | |
| exit 1 | |
| fi | |
| echo "Server restarted successfully with security enabled!" | |
| - name: 📱 Extract and Start Sample App | |
| run: | | |
| echo "Extracting Sample App..." | |
| mkdir -p tests/e2e/sample-app | |
| # Find the sample app zip file (platform-specific) | |
| SAMPLE_APP_ZIP=$(find target/dist -name "sample-app-react-sdk-*.zip" | head -n 1) | |
| if [ -z "$SAMPLE_APP_ZIP" ]; then | |
| echo "⚠️ Warning: Sample app zip not found in target/dist" | |
| echo "Available files:" | |
| ls -la target/dist/ | |
| exit 1 | |
| fi | |
| echo "Found sample app: $SAMPLE_APP_ZIP" | |
| unzip -q "$SAMPLE_APP_ZIP" -d tests/e2e/sample-app | |
| cd tests/e2e/sample-app | |
| # Find the extracted folder and move its contents | |
| EXTRACTED_DIR=$(find . -maxdepth 1 -type d -name "sample-app-*" | head -n 1) | |
| if [ -n "$EXTRACTED_DIR" ]; then | |
| mv "$EXTRACTED_DIR"/* . | |
| rmdir "$EXTRACTED_DIR" | |
| fi | |
| # Make start script executable | |
| chmod +x start.sh | |
| echo "Starting Sample App..." | |
| ./start.sh & | |
| # Wait for sample app to be ready | |
| echo "Waiting for sample app to be ready on https://localhost:3000..." | |
| for i in {1..60}; do | |
| if curl -s -k https://localhost:3000 > /dev/null 2>&1; then | |
| echo "Sample App is UP!" | |
| break | |
| fi | |
| echo "Still waiting ($i/60)..." | |
| sleep 2 | |
| done | |
| # Verify sample app is running | |
| if ! curl -s -k https://localhost:3000 > /dev/null 2>&1; then | |
| echo "Sample app failed to start within 2 minutes" | |
| exit 1 | |
| fi | |
| echo "Sample App started successfully!" | |
| - name: Install E2E dependencies | |
| run: npm ci | |
| working-directory: tests/e2e | |
| - name: Install Playwright Browsers | |
| run: npx playwright install --with-deps | |
| working-directory: tests/e2e | |
| - name: Run Playwright tests | |
| run: npx playwright test | |
| working-directory: tests/e2e | |
| env: | |
| # Configuration Priority: Secret > Variable > Hardcoded Default | |
| BASE_URL: ${{ secrets.PLAYWRIGHT_BASE_URL || vars.PLAYWRIGHT_BASE_URL || 'https://localhost:8090' }} | |
| ADMIN_USERNAME: ${{ secrets.PLAYWRIGHT_ADMIN_USERNAME || 'admin' }} | |
| ADMIN_PASSWORD: ${{ secrets.PLAYWRIGHT_ADMIN_PASSWORD || 'admin' }} | |
| TEST_USER_USERNAME: ${{ secrets.PLAYWRIGHT_TEST_USER_USERNAME || 'testuser' }} | |
| TEST_USER_PASSWORD: ${{ secrets.PLAYWRIGHT_TEST_USER_PASSWORD || 'admin' }} | |
| PLAYWRIGHT_WORKERS: ${{ vars.PLAYWRIGHT_WORKERS || 1 }} | |
| DEBUG_AUTH: ${{ vars.PLAYWRIGHT_DEBUG_AUTH || 'false' }} | |
| # MFA Test Configuration | |
| SAMPLE_APP_ID: ${{ steps.extract-app-id.outputs.sample_app_id }} | |
| SAMPLE_APP_URL: 'https://localhost:3000' | |
| THUNDER_URL: 'https://localhost:8090' | |
| AUTO_SETUP_MFA: ${{ vars.AUTO_SETUP_MFA || 'true' }} | |
| MOCK_SMS_SERVER_PORT: ${{ vars.MOCK_SMS_SERVER_PORT || 8098 }} | |
| SAMPLE_APP_USERNAME: ${{ secrets.SAMPLE_APP_USERNAME || 'e2e-test-user' }} | |
| SAMPLE_APP_PASSWORD: ${{ secrets.SAMPLE_APP_PASSWORD || 'e2e-test-password' }} | |
| - uses: actions/upload-artifact@v4 | |
| if: ${{ !cancelled() }} | |
| with: | |
| name: playwright-report | |
| path: tests/e2e/playwright-report/ | |
| retention-days: 30 | |
| detect-powershell-changes: | |
| name: 🔍 Detect PowerShell Changes | |
| if: github.event_name == 'pull_request' | |
| runs-on: ubuntu-latest | |
| outputs: | |
| should-run: ${{ steps.filter.outputs.powershell }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dorny/paths-filter@v3 | |
| id: filter | |
| with: | |
| filters: | | |
| powershell: | |
| - '**.ps1' | |
| - '.github/workflows/windows-powershell-validation.yml' | |
| - name: ✅ PowerShell files detected | |
| if: steps.filter.outputs.powershell == 'true' | |
| run: echo "PowerShell files changed - validation will run" | |
| - name: ⏭️ No PowerShell changes | |
| if: steps.filter.outputs.powershell != 'true' | |
| run: echo "No PowerShell changes - skipping validation" | |
| validate-windows: | |
| name: 🪟 Validate Windows PowerShell | |
| needs: detect-powershell-changes | |
| if: needs.detect-powershell-changes.outputs.should-run == 'true' | |
| uses: ./.github/workflows/windows-powershell-validation.yml | |