Skip to content

[Docs] Migrate API Docs to Scalar #4873

[Docs] Migrate API Docs to Scalar

[Docs] Migrate API Docs to Scalar #4873

Workflow file for this run

# 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