Feature/import export subscriptions (#353) #354
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/CD Pipeline | |
| on: | |
| push: | |
| branches: [main, dev, develop, 'feature/*'] | |
| pull_request: | |
| branches: [main, dev, develop, 'feature/*'] | |
| env: | |
| NODE_VERSION: '20' | |
| RUST_VERSION: '1.85' | |
| jobs: | |
| commitlint: | |
| name: Conventional Commit Check | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| - name: Cache node modules | |
| uses: actions/cache@v4 | |
| id: cache-node-modules | |
| with: | |
| path: node_modules | |
| key: ${{ runner.os }}-node-${{ env.NODE_VERSION }}-${{ hashFiles('package-lock.json') }} | |
| - name: Install dependencies | |
| if: steps.cache-node-modules.outputs.cache-hit != 'true' | |
| run: npm ci --legacy-peer-deps | |
| - name: Validate PR commits | |
| run: npx commitlint --from ${{ github.event.pull_request.base.sha }} --to ${{ github.sha }} --verbose | |
| # ───────────────────────────────────────────────────────── | |
| # TypeScript / React Native Checks | |
| # ───────────────────────────────────────────────────────── | |
| typescript-lint: | |
| name: TypeScript Lint & Format | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| - name: Cache node modules | |
| uses: actions/cache@v4 | |
| id: cache-node-modules | |
| with: | |
| path: node_modules | |
| key: ${{ runner.os }}-node-${{ env.NODE_VERSION }}-${{ hashFiles('package-lock.json') }} | |
| - name: Install dependencies | |
| if: steps.cache-node-modules.outputs.cache-hit != 'true' | |
| run: npm ci --legacy-peer-deps | |
| - name: Check formatting (Prettier) | |
| run: npm run format:check | |
| - name: Run ESLint | |
| run: npm run lint | |
| npm-audit: | |
| name: NPM Audit (High/Critical) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci --legacy-peer-deps | |
| - name: Run NPM Audit | |
| run: npx audit-ci --config audit-ci.json | |
| typescript-typecheck: | |
| name: TypeScript Type Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| - name: Cache node modules | |
| uses: actions/cache@v4 | |
| id: cache-node-modules | |
| with: | |
| path: node_modules | |
| key: ${{ runner.os }}-node-${{ env.NODE_VERSION }}-${{ hashFiles('package-lock.json') }} | |
| - name: Install dependencies | |
| if: steps.cache-node-modules.outputs.cache-hit != 'true' | |
| run: npm ci --legacy-peer-deps | |
| - name: EVM ABI TypeChain (must match committed output) | |
| run: npm run contracts:codegen:check | |
| - name: Run TypeScript type check | |
| run: npx tsc --noEmit | |
| typescript-tests: | |
| name: TypeScript Tests (Sharded) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| shard: [1, 2, 3] | |
| env: | |
| SHARD: ${{ matrix.shard }} | |
| SHARD_COUNT: 3 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| - name: Cache node modules | |
| uses: actions/cache@v4 | |
| id: cache-node-modules | |
| with: | |
| path: node_modules | |
| key: ${{ runner.os }}-node-${{ env.NODE_VERSION }}-${{ hashFiles('package-lock.json') }} | |
| - name: Install dependencies | |
| if: steps.cache-node-modules.outputs.cache-hit != 'true' | |
| run: npm ci --legacy-peer-deps | |
| - name: Run sharded tests with coverage | |
| run: | | |
| echo "Running shard $SHARD of $SHARD_COUNT" | |
| npm run test:shard | |
| - name: Upload coverage report | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-report-${{ matrix.shard }} | |
| path: coverage/lcov.info | |
| typescript-build: | |
| name: TypeScript Build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| - name: Cache node modules | |
| uses: actions/cache@v4 | |
| id: cache-node-modules | |
| with: | |
| path: node_modules | |
| key: ${{ runner.os }}-node-${{ env.NODE_VERSION }}-${{ hashFiles('package-lock.json') }} | |
| - name: Cache Expo build cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| .expo | |
| node_modules/.cache/expo | |
| key: ${{ runner.os }}-expo-${{ hashFiles('package.json', 'app.json') }} | |
| restore-keys: | | |
| ${{ runner.os }}-expo- | |
| - name: Install dependencies | |
| if: steps.cache-node-modules.outputs.cache-hit != 'true' | |
| run: npm ci --legacy-peer-deps | |
| - name: Run Expo export | |
| run: npm run build | |
| env: | |
| EXPO_NO_TELEMETRY: 1 | |
| sonarcloud: | |
| name: SonarCloud Analysis | |
| runs-on: ubuntu-latest | |
| needs: [typescript-tests] | |
| if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main' | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Download coverage report | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: coverage-report | |
| path: coverage | |
| - name: SonarCloud Scan | |
| uses: SonarSource/sonarcloud-github-action@master | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | |
| # ───────────────────────────────────────────────────────── | |
| # Rust / Soroban Smart Contract Checks | |
| # ───────────────────────────────────────────────────────── | |
| rust-format: | |
| name: Rust Format Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: ${{ env.RUST_VERSION }} | |
| components: rustfmt | |
| - name: Check Rust formatting | |
| run: cd contracts && cargo fmt --check | |
| rust-clippy: | |
| name: Rust Clippy Lint | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: ${{ env.RUST_VERSION }} | |
| components: clippy | |
| - name: Cache Rust dependencies and target | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry/index/ | |
| ~/.cargo/registry/cache/ | |
| ~/.cargo/git/db/ | |
| contracts/target/ | |
| key: ${{ runner.os }}-cargo-${{ env.RUST_VERSION }}-${{ hashFiles('contracts/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo-${{ env.RUST_VERSION }}- | |
| - name: Run Clippy | |
| working-directory: ./contracts | |
| run: cargo clippy --all-targets -- -D warnings | |
| rust-tests: | |
| name: Rust Tests | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: ${{ env.RUST_VERSION }} | |
| - name: Cache Rust dependencies and target | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry/index/ | |
| ~/.cargo/registry/cache/ | |
| ~/.cargo/git/db/ | |
| contracts/target/ | |
| key: ${{ runner.os }}-cargo-${{ env.RUST_VERSION }}-${{ hashFiles('contracts/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo-${{ env.RUST_VERSION }}- | |
| - name: Run Rust tests | |
| working-directory: ./contracts | |
| run: cargo test --verbose | |
| rust-build: | |
| name: Rust Build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: ${{ env.RUST_VERSION }} | |
| - name: Cache Rust dependencies and target | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry/index/ | |
| ~/.cargo/registry/cache/ | |
| ~/.cargo/git/db/ | |
| contracts/target/ | |
| key: ${{ runner.os }}-cargo-${{ env.RUST_VERSION }}-${{ hashFiles('contracts/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo-${{ env.RUST_VERSION }}- | |
| - name: Build Rust contracts | |
| working-directory: ./contracts | |
| run: cargo build --release | |
| # ───────────────────────────────────────────────────────── | |
| # Load Testing | |
| # ───────────────────────────────────────────────────────── | |
| load-test: | |
| name: k6 Load Test | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Run k6 Load Test | |
| uses: grafana/[email protected] | |
| with: | |
| filename: load-tests/run.js | |
| flags: --env SCENARIO=subscription | |
| # ───────────────────────────────────────────────────────── | |
| # Bundle Size Monitoring | |
| # ───────────────────────────────────────────────────────── | |
| bundle-size: | |
| name: Bundle Size Check | |
| runs-on: ubuntu-latest | |
| env: | |
| EXPO_NO_TELEMETRY: 1 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci --legacy-peer-deps | |
| - name: Check bundle size (PR) | |
| if: github.event_name == 'pull_request' | |
| uses: andresz1/size-limit-action@v1 | |
| with: | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| build_script: 'npm run build' | |
| - name: Build app | |
| if: github.event_name != 'pull_request' | |
| run: npm run build | |
| - name: Check bundle size (Push) | |
| if: github.event_name != 'pull_request' | |
| run: npx size-limit --json > bundle-size-report.json | |
| - name: Upload bundle size report | |
| if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: bundle-size-report-${{ github.sha }} | |
| path: bundle-size-report.json | |
| # ───────────────────────────────────────────────────────── | |
| # Merge Protection (only on PRs) | |
| # ───────────────────────────────────────────────────────── | |
| merge-protection: | |
| name: Merge Protection Check | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' | |
| needs: | |
| [ | |
| commitlint, | |
| typescript-lint, | |
| typescript-typecheck, | |
| typescript-tests, | |
| typescript-build, | |
| sonarcloud, | |
| rust-format, | |
| rust-clippy, | |
| rust-tests, | |
| rust-build, | |
| load-test, | |
| bundle-size, | |
| ] | |
| steps: | |
| - name: All checks passed | |
| run: echo "All quality gates passed!" | |
| # ───────────────────────────────────────────────────────── | |
| # Full CI Summary (runs after all jobs) | |
| # ───────────────────────────────────────────────────────── | |
| ci-success: | |
| name: CI Complete | |
| runs-on: ubuntu-latest | |
| if: always() | |
| needs: | |
| [ | |
| commitlint, | |
| typescript-lint, | |
| typescript-typecheck, | |
| typescript-tests, | |
| typescript-build, | |
| sonarcloud, | |
| rust-format, | |
| rust-clippy, | |
| rust-tests, | |
| rust-build, | |
| load-test, | |
| bundle-size, | |
| ] | |
| steps: | |
| - name: Check for failures | |
| run: | | |
| if [ "${{ github.event_name }}" = "pull_request" ] && [ "${{ needs.commitlint.result }}" != "success" ]; then | |
| echo "Conventional commit check failed" | |
| exit 1 | |
| fi | |
| if [ "${{ needs.typescript-lint.result }}" != "success" ] || \ | |
| [ "${{ needs.typescript-typecheck.result }}" != "success" ] || \ | |
| [ "${{ needs.typescript-tests.result }}" != "success" ] || \ | |
| [ "${{ needs.typescript-build.result }}" != "success" ] || \ | |
| [ "${{ needs.sonarcloud.result }}" != "success" ] || \ | |
| [ "${{ needs.rust-format.result }}" != "success" ] || \ | |
| [ "${{ needs.rust-clippy.result }}" != "success" ] || \ | |
| [ "${{ needs.rust-tests.result }}" != "success" ] || \ | |
| [ "${{ needs.rust-build.result }}" != "success" ] || \ | |
| [ "${{ needs.load-test.result }}" != "success" ] || \ | |
| [ "${{ needs.bundle-size.result }}" != "success" ]; then | |
| echo "One or more CI checks failed" | |
| exit 1 | |
| fi | |
| echo "All CI checks passed successfully!" |