Repository navigation
Use Context managers and closures for nicer locking flow vs inline branching #2
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: test-ts | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - stable | |
| - 'releases/**' | |
| tags: | |
| - '*' | |
| pull_request: | |
| workflow_dispatch: | |
| jobs: | |
| lint_ts: | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: bubus-ts | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| version: 10 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| cache-dependency-path: bubus-ts/pnpm-lock.yaml | |
| - run: pnpm install --frozen-lockfile | |
| - run: pnpm exec prettier --check . | |
| - run: pnpm exec eslint . | |
| - run: pnpm run typecheck | |
| find_ts_tests: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| TS_TASKS: ${{ steps.lsgrep.outputs.TS_TASKS }} | |
| # [{ "kind": "test" | "example", "name": "eventbus_basics" }, ...] | |
| TS_TEST_TASKS: ${{ steps.lsgrep.outputs.TS_TEST_TASKS }} | |
| # [{ "kind": "test", "name": "eventbus_basics" }, ...] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - id: lsgrep | |
| run: | | |
| TS_TEST_TASKS="$( | |
| find bubus-ts/tests -maxdepth 1 -type f -name '*.test.ts' \ | |
| | sort \ | |
| | sed 's|^bubus-ts/tests/||' \ | |
| | sed 's|\.test\.ts$||' \ | |
| | jq -R -s -c 'split("\n")[:-1] | map({kind: "test", name: .})' | |
| )" | |
| TS_EXAMPLE_TASKS="$( | |
| ( | |
| if [[ -d bubus-ts/examples ]]; then | |
| find bubus-ts/examples -maxdepth 1 -type f -name '*.ts' | sort | |
| fi | |
| ) \ | |
| | sed 's|^bubus-ts/examples/||' \ | |
| | sed 's|\.ts$||' \ | |
| | jq -R -s -c 'split("\n")[:-1] | map({kind: "example", name: .})' | |
| )" | |
| TS_TASKS="$(jq -cn --argjson tests "$TS_TEST_TASKS" --argjson examples "$TS_EXAMPLE_TASKS" '$tests + $examples')" | |
| echo "TS_TEST_TASKS=${TS_TEST_TASKS}" >> "$GITHUB_OUTPUT" | |
| echo "TS_TASKS=${TS_TASKS}" >> "$GITHUB_OUTPUT" | |
| echo "$TS_TASKS" | |
| - name: Check that at least one test file is found | |
| run: | | |
| if [[ -z "${{ steps.lsgrep.outputs.TS_TEST_TASKS }}" || "${{ steps.lsgrep.outputs.TS_TEST_TASKS }}" == "[]" ]]; then | |
| echo "Failed to find any *.test.ts files in bubus-ts/tests/ folder!" > /dev/stderr | |
| exit 1 | |
| fi | |
| tests: | |
| needs: | |
| - lint_ts | |
| - find_ts_tests | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| task: ${{ fromJson(needs.find_ts_tests.outputs.TS_TASKS || '[{"kind":"error","name":"FAILED_TO_DISCOVER_TASKS"}]') }} | |
| # autodiscovers all files in bubus-ts/tests/*.test.ts and bubus-ts/examples/*.ts | |
| # - { kind: "test", name: "eventbus_basics" } | |
| # - { kind: "example", name: "simple" } | |
| # ... and more | |
| name: ts-${{ matrix.task.kind }}-${{ matrix.task.name }} | |
| defaults: | |
| run: | |
| working-directory: bubus-ts | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Check that the previous step managed to find some tasks for us to run | |
| run: | | |
| if [[ "${{ matrix.task.kind }}" == "error" ]]; then | |
| echo "Failed get list of tasks from find_ts_tests job" > /dev/stderr | |
| exit 1 | |
| fi | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| version: 10 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| cache-dependency-path: bubus-ts/pnpm-lock.yaml | |
| - run: pnpm install --frozen-lockfile | |
| - name: Prepare coverage directory | |
| run: | | |
| rm -rf .v8-coverage | |
| mkdir -p .v8-coverage | |
| - name: Run test with coverage | |
| if: matrix.task.kind == 'test' | |
| run: NODE_V8_COVERAGE=.v8-coverage NODE_OPTIONS='--expose-gc' node --expose-gc --test --experimental-test-coverage --import tsx tests/${{ matrix.task.name }}.test.ts | |
| - name: Run example | |
| if: matrix.task.kind == 'example' | |
| run: NODE_V8_COVERAGE=.v8-coverage NODE_OPTIONS='--expose-gc' node --expose-gc --import tsx examples/${{ matrix.task.name }}.ts | |
| - name: Upload raw coverage data | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ts-coverage-${{ matrix.task.kind }}-${{ matrix.task.name }} | |
| path: | | |
| bubus-ts/.v8-coverage | |
| pyproject.toml | |
| retention-days: 7 | |
| include-hidden-files: true | |
| if: always() | |
| coverage: | |
| needs: tests | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| version: 10 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| cache-dependency-path: bubus-ts/pnpm-lock.yaml | |
| - run: cd bubus-ts && pnpm install --frozen-lockfile | |
| - name: Download all coverage data | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: ts-coverage-* | |
| path: coverage-data/ | |
| - name: Combine coverage data | |
| run: | | |
| mkdir -p bubus-ts/.v8-coverage-merged | |
| counter=1 | |
| while IFS= read -r -d '' coverage_file; do | |
| cp "$coverage_file" "bubus-ts/.v8-coverage-merged/$counter-$(basename "$coverage_file")" | |
| counter=$((counter + 1)) | |
| done < <(find coverage-data -type f -name "*.json" -print0) | |
| if [[ "$counter" -eq 1 ]]; then | |
| echo "No V8 coverage JSON files found in downloaded artifacts" > /dev/stderr | |
| exit 1 | |
| fi | |
| - name: Build merged coverage report | |
| run: | | |
| cd bubus-ts | |
| set -o pipefail | |
| mkdir -p coverage | |
| pnpm dlx c8 report \ | |
| --temp-directory .v8-coverage-merged \ | |
| --report-dir coverage \ | |
| --reporter=html \ | |
| --reporter=text \ | |
| --reporter=json-summary \ | |
| --exclude-after-remap \ | |
| -n 'src/**/*.ts' \ | |
| -x 'src/bridge*.ts' \ | |
| -x 'src/optional_deps.ts' | tee coverage/text-report.txt | |
| node <<'NODE' | |
| const fs = require('fs'); | |
| const summaryPath = 'coverage/coverage-summary.json'; | |
| const summary = JSON.parse(fs.readFileSync(summaryPath, 'utf8')); | |
| const entries = Object.entries(summary); | |
| const total = summary.total; | |
| const files = entries | |
| .filter(([name]) => name !== 'total') | |
| .sort((a, b) => String(a[0]).localeCompare(String(b[0]))); | |
| const esc = (s) => String(s).replace(/\|/g, '\\|'); | |
| const row = (name, m) => { | |
| const stmtsTotal = Number(m.statements.total || 0); | |
| const stmtsCovered = Number(m.statements.covered || 0); | |
| const stmtsMiss = Math.max(stmtsTotal - stmtsCovered, 0); | |
| return `| ${esc(name)} | ${stmtsTotal} | ${stmtsMiss} | ${Number(m.statements.pct || 0).toFixed(2)}% | ${Number(m.branches.pct || 0).toFixed(2)}% | ${Number(m.functions.pct || 0).toFixed(2)}% | ${Number(m.lines.pct || 0).toFixed(2)}% |`; | |
| }; | |
| const lines = []; | |
| lines.push('### TypeScript combined coverage'); | |
| lines.push(''); | |
| lines.push('| Name | Stmts | Miss | Cover | Branch | Funcs | Lines |'); | |
| lines.push('| --- | ---: | ---: | ---: | ---: | ---: | ---: |'); | |
| lines.push(row('TOTAL', total)); | |
| for (const [name, metrics] of files) { | |
| lines.push(row(name, metrics)); | |
| } | |
| lines.push(''); | |
| const summaryFile = process.env.GITHUB_STEP_SUMMARY; | |
| fs.appendFileSync(summaryFile, lines.join('\n')); | |
| NODE | |
| - name: Fail if TypeScript coverage is <50% | |
| run: | | |
| cd bubus-ts | |
| pnpm dlx c8 report \ | |
| --temp-directory .v8-coverage-merged \ | |
| --reporter=text-summary \ | |
| --exclude-after-remap \ | |
| -n 'src/**/*.ts' \ | |
| -x 'src/bridge*.ts' \ | |
| -x 'src/optional_deps.ts' \ | |
| --check-coverage \ | |
| --lines 50 > /dev/null | |
| - name: Upload merged coverage report | |
| id: upload_ts_coverage_report | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ts-coverage-report | |
| path: | | |
| bubus-ts/coverage/ | |
| pyproject.toml | |
| retention-days: 7 | |
| - name: Append TypeScript coverage artifact link | |
| run: | | |
| echo "" >> "$GITHUB_STEP_SUMMARY" | |
| echo "[Download TypeScript HTML coverage artifact (ts-coverage-report)](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts/${{ steps.upload_ts_coverage_report.outputs.artifact-id }})" >> "$GITHUB_STEP_SUMMARY" | |
| perf: | |
| needs: coverage | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: bubus-ts | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| version: 10 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| cache-dependency-path: bubus-ts/pnpm-lock.yaml | |
| - uses: oven-sh/setup-bun@v2 | |
| - uses: denoland/setup-deno@v2 | |
| with: | |
| deno-version: v2.x | |
| - run: pnpm install --frozen-lockfile | |
| - run: npx --yes --package=playwright playwright install chromium | |
| - run: pnpm run perf |