323 lines
12 KiB
YAML
323 lines
12 KiB
YAML
# .github/workflows/ci.yml
|
|
# Continuous Integration Pipeline for D3RO Voice Monorepo
|
|
|
|
name: CI Pipeline
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
- develop
|
|
- 'feature/**'
|
|
- 'fix/**'
|
|
pull_request:
|
|
branches:
|
|
- main
|
|
- develop
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
# ──────────────────────────────────────────────────────────────────
|
|
# 1. Code Quality, Linting & Typecheck
|
|
# ──────────────────────────────────────────────────────────────────
|
|
code-quality:
|
|
name: Code Quality & Typecheck
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout Code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Node.js 24
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version-file: '.nvmrc'
|
|
cache: 'npm'
|
|
|
|
- name: Install Dependencies
|
|
run: npm ci
|
|
|
|
- name: Credential Scanner Self-Test
|
|
run: npm run security:secrets:test
|
|
|
|
- name: Hard-Coded Credential Scan
|
|
run: npm run security:secrets
|
|
|
|
- name: Mobile Release Boundary Self-Test
|
|
run: npm run release:mobile:boundary:test
|
|
|
|
- name: Mobile Release Configuration Self-Test
|
|
run: npm run release:mobile:config:test
|
|
|
|
- name: Mobile Build Configuration Self-Test
|
|
run: npm run release:mobile:build-config:test
|
|
|
|
- name: Play Store Asset Contract
|
|
run: npm run release:play:assets
|
|
|
|
- name: Lint Check
|
|
run: npm run lint
|
|
|
|
- name: Typecheck All Workspaces
|
|
run: npm run typecheck
|
|
|
|
api-server-tests:
|
|
name: .NET API Server Tests
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout Code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup .NET 10
|
|
uses: actions/setup-dotnet@v5
|
|
with:
|
|
dotnet-version: '10.0.302'
|
|
|
|
- name: Restore API Test Dependencies
|
|
run: dotnet restore apps/api-server.Tests/D3ROVoice.Api.Tests.csproj
|
|
|
|
- name: Run API Authorization and Gateway Tests
|
|
run: dotnet test apps/api-server.Tests/D3ROVoice.Api.Tests.csproj --configuration Release --no-restore -p:StaticWebAssetsEnabled=false
|
|
|
|
edge-functions-quality:
|
|
name: Supabase Edge Functions Typecheck & Tests
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout Code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Deno 2.8.1
|
|
uses: denoland/setup-deno@v2
|
|
with:
|
|
deno-version: v2.8.1
|
|
|
|
- name: Check Every Edge Function Entrypoint
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
for entrypoint in server/supabase/functions/*/index.ts; do
|
|
deno check --config server/supabase/functions/deno.json "$entrypoint"
|
|
done
|
|
|
|
- name: Run Edge Function Contract Tests
|
|
run: deno test --config server/supabase/functions/deno.json --allow-read --allow-env server/supabase/functions
|
|
|
|
# ──────────────────────────────────────────────────────────────────
|
|
# 2. Automated Test Matrix (Windows / macOS / Ubuntu)
|
|
# ──────────────────────────────────────────────────────────────────
|
|
test-matrix:
|
|
name: Test Suite (${{ matrix.os }})
|
|
needs: code-quality
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
os: [windows-latest, macos-latest, ubuntu-latest]
|
|
runs-on: ${{ matrix.os }}
|
|
steps:
|
|
- name: Checkout Code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Node.js 24
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version-file: '.nvmrc'
|
|
cache: 'npm'
|
|
|
|
- name: Install Dependencies
|
|
run: npm ci
|
|
|
|
- name: Run Monorepo Test Suites (Vitest)
|
|
run: npm test
|
|
|
|
# ──────────────────────────────────────────────────────────────────
|
|
# 3. Build Validation for All Workspaces
|
|
# ──────────────────────────────────────────────────────────────────
|
|
build-validation:
|
|
name: Build Validation (${{ matrix.target }})
|
|
needs: code-quality
|
|
strategy:
|
|
matrix:
|
|
include:
|
|
- target: desktop
|
|
os: windows-latest
|
|
cmd: npm run build --workspace=@d3ro/desktop
|
|
- target: admin
|
|
os: ubuntu-latest
|
|
cmd: npm run build --workspace=@d3ro/admin
|
|
runs-on: ${{ matrix.os }}
|
|
steps:
|
|
- name: Checkout Code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Node.js 24
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version-file: '.nvmrc'
|
|
cache: 'npm'
|
|
|
|
- name: Install Dependencies
|
|
run: npm ci
|
|
|
|
- name: Build Target Workspace
|
|
run: ${{ matrix.cmd }}
|
|
|
|
# ──────────────────────────────────────────────────────────────────
|
|
# 4. Android x86_64 artifacts and native dependency gate
|
|
# ──────────────────────────────────────────────────────────────────
|
|
mobile-android:
|
|
name: Mobile Android (universal debug + bundled universal E2E)
|
|
needs: code-quality
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout Code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Node.js 24
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version-file: '.nvmrc'
|
|
cache: 'npm'
|
|
|
|
- name: Setup JDK 17
|
|
uses: actions/setup-java@v5
|
|
with:
|
|
distribution: temurin
|
|
java-version: '17'
|
|
|
|
- name: Setup Android SDK
|
|
uses: android-actions/setup-android@v4
|
|
|
|
- name: Setup Gradle
|
|
uses: gradle/actions/setup-gradle@v6
|
|
with:
|
|
cache-provider: basic
|
|
|
|
- name: Install Dependencies
|
|
run: |
|
|
npm ci
|
|
npm --prefix apps/mobile-rn ci --workspaces=false
|
|
|
|
- name: Prepare Verified Whisper Model
|
|
run: node scripts/ci/prepare-whisper-model.mjs
|
|
|
|
- name: Test Mobile TypeScript and Jest
|
|
run: |
|
|
npm --prefix apps/mobile-rn run lint
|
|
npm --prefix apps/mobile-rn run typecheck
|
|
npm --prefix apps/mobile-rn run test:ci
|
|
|
|
- name: Build Universal Debug, CSPRNG Test, and Bundled Universal E2E APKs
|
|
working-directory: apps/mobile-rn/android
|
|
env:
|
|
D3RO_VERSION_NAME: 0.0.0-e2e.${{ github.run_number }}
|
|
D3RO_VERSION_CODE: ${{ github.run_number }}
|
|
run: ./gradlew :app:assembleDebug :app:assembleDebugAndroidTest :app:assembleE2e -PreactNativeArchitectures=arm64-v8a,x86_64 --no-daemon
|
|
|
|
- name: Verify BuildConfig and APK Runtime Contracts
|
|
env:
|
|
D3RO_VERSION_NAME: 0.0.0-e2e.${{ github.run_number }}
|
|
D3RO_VERSION_CODE: ${{ github.run_number }}
|
|
run: |
|
|
set -euo pipefail
|
|
DEBUG_APK=apps/mobile-rn/android/app/build/outputs/apk/debug/app-debug.apk
|
|
E2E_APK=apps/mobile-rn/android/app/build/outputs/apk/e2e/app-e2e.apk
|
|
test -f "$DEBUG_APK"
|
|
test -f "$E2E_APK"
|
|
node scripts/ci/verify-mobile-build-config.mjs debug \
|
|
| tee apps/mobile-rn/android/app/build/outputs/debug-build-config.json
|
|
node scripts/ci/verify-mobile-build-config.mjs e2e \
|
|
| tee apps/mobile-rn/android/app/build/outputs/e2e-build-config.json
|
|
node scripts/ci/verify-android-artifact.mjs --mode debug --apk "$DEBUG_APK" \
|
|
| tee apps/mobile-rn/android/app/build/outputs/debug-artifact-evidence.json
|
|
node scripts/ci/verify-android-artifact.mjs \
|
|
--mode e2e \
|
|
--apk "$E2E_APK" \
|
|
--expected-version-name "$D3RO_VERSION_NAME" \
|
|
--expected-version-code "$D3RO_VERSION_CODE" \
|
|
| tee apps/mobile-rn/android/app/build/outputs/e2e-artifact-evidence.json
|
|
node scripts/ci/verify-android-app-links.mjs \
|
|
| tee apps/mobile-rn/android/app/build/outputs/app-links-evidence.json
|
|
sha256sum "$DEBUG_APK" "$E2E_APK" | tee apps/mobile-rn/android/app/build/outputs/android-ci.sha256
|
|
|
|
- name: Upload Universal Android Artifacts
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: d3ro-mobile-android-universal-e2e
|
|
path: |
|
|
apps/mobile-rn/android/app/build/outputs/apk/debug/app-debug.apk
|
|
apps/mobile-rn/android/app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk
|
|
apps/mobile-rn/android/app/build/outputs/apk/e2e/app-e2e.apk
|
|
apps/mobile-rn/android/app/build/outputs/android-ci.sha256
|
|
apps/mobile-rn/android/app/build/outputs/*-build-config.json
|
|
apps/mobile-rn/android/app/build/outputs/*-artifact-evidence.json
|
|
apps/mobile-rn/android/app/build/outputs/app-links-evidence.json
|
|
if-no-files-found: error
|
|
|
|
# ──────────────────────────────────────────────────────────────────
|
|
# 5. Installed bundled APK on a clean API 35 x86_64 emulator
|
|
# ──────────────────────────────────────────────────────────────────
|
|
mobile-emulator-e2e:
|
|
name: Mobile Emulator E2E (API 35)
|
|
needs: mobile-android
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout Code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup JDK 17
|
|
uses: actions/setup-java@v5
|
|
with:
|
|
distribution: temurin
|
|
java-version: '17'
|
|
|
|
- name: Setup Android SDK
|
|
uses: android-actions/setup-android@v4
|
|
|
|
- name: Download Bundled Android Artifact
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: d3ro-mobile-android-universal-e2e
|
|
path: mobile-artifact
|
|
|
|
- name: Install Verified Maestro CLI 2.7.0
|
|
run: |
|
|
curl -fsSL https://github.com/mobile-dev-inc/maestro/releases/download/cli-2.7.0/maestro.zip -o /tmp/maestro.zip
|
|
echo 'a4ccab6b604617e7aef6db4f885666056eabe5cfa32befaa3bc994041b8fcbb5 /tmp/maestro.zip' | sha256sum -c -
|
|
unzip -q /tmp/maestro.zip -d "$RUNNER_TEMP/maestro"
|
|
echo "$RUNNER_TEMP/maestro/maestro/bin" >> "$GITHUB_PATH"
|
|
|
|
- name: Run Mandatory Clean-room and Optional External-account Journeys
|
|
uses: reactivecircus/android-emulator-runner@v2
|
|
env:
|
|
MOBILE_E2E_EMAIL: ${{ secrets.MOBILE_E2E_EMAIL }}
|
|
MOBILE_E2E_PASSWORD: ${{ secrets.MOBILE_E2E_PASSWORD }}
|
|
with:
|
|
api-level: 35
|
|
target: google_apis
|
|
arch: x86_64
|
|
profile: pixel_6
|
|
disable-animations: true
|
|
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
|
script: |
|
|
set -euo pipefail
|
|
DEBUG_APK="$(find mobile-artifact -path '*/apk/debug/app-debug.apk' -print -quit)"
|
|
TEST_APK="$(find mobile-artifact -name app-debug-androidTest.apk -print -quit)"
|
|
E2E_APK="$(find mobile-artifact -name app-e2e.apk -print -quit)"
|
|
test -n "$DEBUG_APK"
|
|
test -n "$TEST_APK"
|
|
test -n "$E2E_APK"
|
|
maestro --version
|
|
bash scripts/ci/run-mobile-csprng-instrumentation.sh "$DEBUG_APK" "$TEST_APK"
|
|
bash scripts/ci/run-mobile-emulator-gate.sh "$E2E_APK"
|
|
|
|
- name: Upload Emulator Evidence
|
|
if: always()
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: d3ro-mobile-emulator-e2e
|
|
path: |
|
|
apps/mobile-rn/.maestro/*.junit.xml
|
|
apps/mobile-rn/.maestro-output/
|
|
if-no-files-found: warn
|