Repository navigation
feat: stream large submission exports directly from db without memory… #384
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: Backend CI | |
| # Triggered on push/PR for main/master when BackEnd files or this workflow change. | |
| # Jobs: | |
| # 1. build-and-lint – TypeScript compilation, linting, formatting | |
| # 2. openapi-check – headless OpenAPI spec generation + artifact upload | |
| # 3. backend-ci-gate – aggregate gate: fails if either upstream job fails | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| on: | |
| push: | |
| branches: [main, master] | |
| paths: | |
| - "BackEnd/**" | |
| - ".github/workflows/backend-ci.yml" | |
| pull_request: | |
| paths: | |
| - "BackEnd/**" | |
| - ".github/workflows/backend-ci.yml" | |
| jobs: | |
| # --------------------------------------------------------------------------- | |
| # Job 0: Toolchain Preflight Check [BE-136] | |
| # --------------------------------------------------------------------------- | |
| toolchain-check: | |
| name: Toolchain Preflight Check | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: BackEnd | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| # The preflight script (check:toolchain) verifies Rust/Cargo versions because | |
| # some backend workflows interact with the Soroban contract workspace. | |
| # Match contract-ci.yml's toolchain choice so requirements stay in sync. | |
| - name: Setup Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache npm dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.npm | |
| key: ${{ runner.os }}-backend-npm-${{ hashFiles('BackEnd/package-lock.json') }} | |
| restore-keys: | | |
| ${{ runner.os }}-backend-npm- | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Validate toolchain versions | |
| run: npm run check:toolchain | |
| # --------------------------------------------------------------------------- | |
| # Job 1: Build, Lint & Format | |
| # --------------------------------------------------------------------------- | |
| build-and-lint: | |
| name: Build, Lint & Format | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: BackEnd | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| - name: Cache npm dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.npm | |
| key: ${{ runner.os }}-backend-npm-${{ hashFiles('BackEnd/package-lock.json') }} | |
| restore-keys: | | |
| ${{ runner.os }}-backend-npm- | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: TypeScript compilation | |
| run: npm run build | |
| - name: Upload build artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: backend-dist | |
| path: BackEnd/dist/ | |
| retention-days: 7 | |
| - name: Lint | |
| run: npm run lint | |
| - name: Format check | |
| run: npx prettier --check "src/**/*.ts" "test/**/*.ts" | |
| # --------------------------------------------------------------------------- | |
| # Job 2: OpenAPI Spec Generation & Artifact Upload [BE-116] | |
| # --------------------------------------------------------------------------- | |
| openapi-check: | |
| name: OpenAPI Generation Check | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: BackEnd | |
| # Minimal stubs so the NestJS app module can bootstrap without real services. | |
| # The generate-openapi.ts script also sets these itself, but declaring them | |
| # here makes the CI environment explicit and auditable. | |
| env: | |
| NODE_ENV: openapi-gen | |
| DB_HOST: localhost | |
| DB_PORT: "5432" | |
| DB_USERNAME: postgres | |
| DB_PASSWORD: password | |
| DB_DATABASE: stellar_earn | |
| DATABASE_URL: postgresql://postgres:password@localhost:5432/stellar_earn | |
| REDIS_HOST: localhost | |
| REDIS_PORT: "6379" | |
| REDIS_URL: redis://localhost:6379 | |
| JWT_SECRET: openapi-gen-secret | |
| JWT_PRIVATE_KEY: dummy | |
| JWT_PUBLIC_KEY: dummy | |
| STELLAR_NETWORK: testnet | |
| HORIZON_URL: https://horizon-testnet.stellar.org | |
| SOROBAN_RPC_URL: https://soroban-testnet.stellar.org | |
| SOROBAN_SECRET_KEY: SAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | |
| SENDGRID_API_KEY: SG.dummy | |
| EMAIL_FROM_ADDRESS: noreply@stellarearn.com | |
| EMAIL_FROM_NAME: StellarEarn | |
| APP_URL: http://localhost:3000 | |
| STELLAR_MOCK_CURRENT_LEDGER: "60000000" | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| - name: Cache npm dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.npm | |
| key: ${{ runner.os }}-backend-npm-${{ hashFiles('BackEnd/package-lock.json') }} | |
| restore-keys: | | |
| ${{ runner.os }}-backend-npm- | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Generate OpenAPI specification | |
| run: npm run openapi:generate | |
| - name: Validate generated spec | |
| # Confirm the file exists, is valid JSON, has an "openapi" field, | |
| # and exposes at least one path. | |
| run: | | |
| SPEC_FILE="dist/openapi/openapi.json" | |
| if [ ! -f "$SPEC_FILE" ]; then | |
| echo "❌ OpenAPI spec file not found at $SPEC_FILE" | |
| exit 1 | |
| fi | |
| # Validate JSON syntax | |
| if ! python3 -c "import json,sys; json.load(open('$SPEC_FILE'))" 2>/dev/null; then | |
| echo "❌ $SPEC_FILE is not valid JSON" | |
| exit 1 | |
| fi | |
| OPENAPI_VERSION=$(python3 -c "import json; d=json.load(open('$SPEC_FILE')); print(d.get('openapi',''))") | |
| PATH_COUNT=$(python3 -c "import json; d=json.load(open('$SPEC_FILE')); print(len(d.get('paths',{})))") | |
| echo "openapi field : $OPENAPI_VERSION" | |
| echo "path count : $PATH_COUNT" | |
| if [ -z "$OPENAPI_VERSION" ]; then | |
| echo "❌ 'openapi' field is missing or empty in the spec" | |
| exit 1 | |
| fi | |
| if [ "$PATH_COUNT" -eq 0 ]; then | |
| echo "❌ Generated spec contains no paths – check that controllers are wired up correctly" | |
| exit 1 | |
| fi | |
| echo "✅ OpenAPI spec is valid (openapi=$OPENAPI_VERSION, paths=$PATH_COUNT)" | |
| - name: Upload OpenAPI spec artifact | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: openapi-spec-${{ github.sha }} | |
| path: BackEnd/dist/openapi/openapi.json | |
| retention-days: 30 | |
| # --------------------------------------------------------------------------- | |
| # Job 3: Aggregate CI Gate | |
| # --------------------------------------------------------------------------- | |
| backend-ci-gate: | |
| name: Backend CI Gate | |
| runs-on: ubuntu-latest | |
| needs: [toolchain-check, build-and-lint, openapi-check] | |
| if: always() | |
| steps: | |
| - name: Validate all checks passed | |
| run: | | |
| toolchain_status="${{ needs.toolchain-check.result }}" | |
| build_status="${{ needs.build-and-lint.result }}" | |
| openapi_status="${{ needs.openapi-check.result }}" | |
| echo "Toolchain check : $toolchain_status" | |
| echo "Build & lint : $build_status" | |
| echo "OpenAPI check : $openapi_status" | |
| if [ "$toolchain_status" != "success" ]; then | |
| echo "❌ Toolchain preflight check failed" | |
| exit 1 | |
| fi | |
| if [ "$build_status" != "success" ]; then | |
| echo "❌ Build or lint failed" | |
| exit 1 | |
| fi | |
| if [ "$openapi_status" != "success" ]; then | |
| echo "❌ OpenAPI generation check failed" | |
| exit 1 | |
| fi | |
| echo "✅ All backend CI checks passed" | |
| exit 0 | |
| - name: Workflow Summary | |
| if: always() | |
| run: | | |
| echo "## Backend CI Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "| Job | Status |" >> $GITHUB_STEP_SUMMARY | |
| echo "|-----|--------|" >> $GITHUB_STEP_SUMMARY | |
| echo "| Toolchain Check | ${{ needs.toolchain-check.result }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Build & Lint | ${{ needs.build-and-lint.result }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| OpenAPI Check | ${{ needs.openapi-check.result }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [ "${{ needs.toolchain-check.result }}" != "success" ] || \ | |
| [ "${{ needs.build-and-lint.result }}" != "success" ] || \ | |
| [ "${{ needs.openapi-check.result }}" != "success" ]; then | |
| echo "### ❌ Failed Checks" >> $GITHUB_STEP_SUMMARY | |
| echo "One or more backend CI checks failed. Please review the job logs above." >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "### ✅ All Checks Passed" >> $GITHUB_STEP_SUMMARY | |
| echo "All backend CI checks completed successfully." >> $GITHUB_STEP_SUMMARY | |
| fi |