feat(lenses): Leviticus 1-10 lens content, batch 1 of Pentateuch-rest pilot (#820, #1782) #1446
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: Tests | |
| on: | |
| pull_request: | |
| branches: [master] | |
| push: | |
| branches: [master] | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| jobs: | |
| test: | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: app | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| lfs: false # scripture.db is not needed for tests | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| cache: npm | |
| cache-dependency-path: app/package-lock.json | |
| - run: npm ci | |
| - name: TypeScript check | |
| run: npx tsc --noEmit | |
| - name: Run tests with coverage | |
| id: tests | |
| run: | | |
| npx jest --coverage --ci --verbose --json --outputFile=test-results.json 2>&1 | tail -20 | |
| echo "TESTS_EXIT_CODE=${PIPESTATUS[0]:-$?}" >> $GITHUB_ENV | |
| continue-on-error: true | |
| - name: Generate test summary | |
| if: always() | |
| id: summary | |
| working-directory: app | |
| run: | | |
| if [ ! -f test-results.json ]; then | |
| echo "body=⚠️ **Tests**: Could not parse results" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| PASSED=$(node -e "const r=require('./test-results.json'); console.log(r.numPassedTests)") | |
| FAILED=$(node -e "const r=require('./test-results.json'); console.log(r.numFailedTests)") | |
| TOTAL=$(node -e "const r=require('./test-results.json'); console.log(r.numTotalTests)") | |
| SUITES_PASSED=$(node -e "const r=require('./test-results.json'); console.log(r.numPassedTestSuites)") | |
| SUITES_FAILED=$(node -e "const r=require('./test-results.json'); console.log(r.numFailedTestSuites)") | |
| SUITES_TOTAL=$(node -e "const r=require('./test-results.json'); console.log(r.numTotalTestSuites)") | |
| DURATION=$(node -e "const r=require('./test-results.json'); const s=((Date.now()-r.startTime)/1000).toFixed(1); console.log(s+'s')") | |
| # Extract coverage percentages from coverage-summary.json | |
| COV_STMTS="—" | |
| COV_BRANCH="—" | |
| COV_FUNCS="—" | |
| COV_LINES="—" | |
| if [ -f coverage/coverage-summary.json ]; then | |
| COV_STMTS=$(node -e "const c=require('./coverage/coverage-summary.json').total.statements.pct; console.log(c+'%')") | |
| COV_BRANCH=$(node -e "const c=require('./coverage/coverage-summary.json').total.branches.pct; console.log(c+'%')") | |
| COV_FUNCS=$(node -e "const c=require('./coverage/coverage-summary.json').total.functions.pct; console.log(c+'%')") | |
| COV_LINES=$(node -e "const c=require('./coverage/coverage-summary.json').total.lines.pct; console.log(c+'%')") | |
| fi | |
| # Build the summary body | |
| if [ "$FAILED" = "0" ]; then | |
| STATUS="✅ All tests passed" | |
| else | |
| STATUS="❌ $FAILED test(s) failed" | |
| fi | |
| BODY="## Test Results | |
| ${STATUS} | |
| | | Passed | Failed | Total | | |
| |---|---|---|---| | |
| | **Tests** | ✅ ${PASSED} | ❌ ${FAILED} | ${TOTAL} | | |
| | **Suites** | ✅ ${SUITES_PASSED} | ❌ ${SUITES_FAILED} | ${SUITES_TOTAL} | | |
| ### Coverage | |
| | Statements | Branches | Functions | Lines | | |
| |---|---|---|---| | |
| | ${COV_STMTS} | ${COV_BRANCH} | ${COV_FUNCS} | ${COV_LINES} | | |
| ⏱️ Duration: ${DURATION}" | |
| # Also write to GitHub Actions job summary | |
| echo "$BODY" >> $GITHUB_STEP_SUMMARY | |
| # Save for PR comment (use delimiter for multiline) | |
| EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64) | |
| echo "body<<$EOF" >> $GITHUB_OUTPUT | |
| echo "$BODY" >> $GITHUB_OUTPUT | |
| echo "$EOF" >> $GITHUB_OUTPUT | |
| - name: Post results to PR | |
| if: always() && github.event_name == 'pull_request' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const body = `${{ steps.summary.outputs.body }}`; | |
| if (!body) return; | |
| // Find existing bot comment to update (avoid spam) | |
| const { data: comments } = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| }); | |
| const botComment = comments.find(c => | |
| c.user.type === 'Bot' && c.body.includes('## Test Results') | |
| ); | |
| if (botComment) { | |
| await github.rest.issues.updateComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: botComment.id, | |
| body, | |
| }); | |
| } else { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body, | |
| }); | |
| } | |
| - name: Upload coverage report | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-report | |
| path: app/coverage/ | |
| retention-days: 14 | |
| - name: Fail if tests failed | |
| if: env.TESTS_EXIT_CODE != '0' | |
| run: exit 1 | |
| # ── Preflight bundle checks ────────────────────────────────────── | |
| # These catch issues that unit tests can't see: dep version drift | |
| # and Metro bundle-level resolution failures. They run only after | |
| # tests pass — no point bundling a red build. | |
| # | |
| # Added after we shipped a TestFlight binary whose JS bundle | |
| # couldn't resolve react-native-reanimated transitively; tests | |
| # passed, EAS build failed during bundling. expo-doctor + expo | |
| # export in CI would have caught both issues before merge. | |
| - name: Expo doctor — dep version check | |
| run: npx expo-doctor@latest | |
| - name: Expo export — iOS bundle resolution check | |
| run: npx expo export --platform ios --output-dir /tmp/expo-export-check |