feat(codegen): generated C sync/blocking wrappers + Rust e2e suite #385
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 | |
| on: | |
| push: | |
| branches: [master, main] | |
| pull_request: | |
| branches: [master, main] | |
| jobs: | |
| # Single source of truth for Nim / Nimble versions used by every job and | |
| # every reusable workflow below. Values live in versions.env at the repo | |
| # root so they're greppable and editable in one place, next to ffi.nimble. | |
| # The job exposes them as outputs because the `with:` of a reusable-workflow | |
| # call only accepts the `needs`, `inputs`, `vars`, and `github` contexts — | |
| # `env` is not allowed there, which rules out plain workflow-level env vars. | |
| versions: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| nim-versions: ${{ steps.load.outputs.NIM_VERSIONS }} | |
| nimble: ${{ steps.load.outputs.NIMBLE_VERSION }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - id: load | |
| run: cat versions.env >> "$GITHUB_OUTPUT" | |
| alloc: | |
| name: Alloc | |
| needs: versions | |
| uses: ./.github/workflows/test.yml | |
| with: | |
| test: test_alloc | |
| nim-versions: ${{ needs.versions.outputs.nim-versions }} | |
| nimble-version: ${{ needs.versions.outputs.nimble }} | |
| ffi-context: | |
| name: FFI Context | |
| needs: versions | |
| uses: ./.github/workflows/test.yml | |
| with: | |
| test: test_ffi_context | |
| nim-versions: ${{ needs.versions.outputs.nim-versions }} | |
| nimble-version: ${{ needs.versions.outputs.nimble }} | |
| gc-compat: | |
| name: GC Compatibility | |
| needs: versions | |
| uses: ./.github/workflows/test.yml | |
| with: | |
| test: test_gc_compat | |
| nim-versions: ${{ needs.versions.outputs.nim-versions }} | |
| nimble-version: ${{ needs.versions.outputs.nimble }} | |
| serial: | |
| name: Serial | |
| needs: versions | |
| uses: ./.github/workflows/test.yml | |
| with: | |
| test: test_serial | |
| nim-versions: ${{ needs.versions.outputs.nim-versions }} | |
| nimble-version: ${{ needs.versions.outputs.nimble }} | |
| ctx-validation: | |
| name: Context Validation | |
| needs: versions | |
| uses: ./.github/workflows/test.yml | |
| with: | |
| test: test_ctx_validation | |
| nim-versions: ${{ needs.versions.outputs.nim-versions }} | |
| nimble-version: ${{ needs.versions.outputs.nimble }} | |
| abi-format: | |
| # Runs cross-OS to also guard declareLibrary's --app:lib linker-flag check: | |
| # this test compiles FFI code as a plain executable, which would fail to | |
| # link on macOS if the soname/install_name flags leaked into a non-lib build. | |
| name: ABI Format | |
| needs: versions | |
| uses: ./.github/workflows/test.yml | |
| with: | |
| test: test_abi_format | |
| nim-versions: ${{ needs.versions.outputs.nim-versions }} | |
| nimble-version: ${{ needs.versions.outputs.nimble }} | |
| c-wire: | |
| # The `c`-ABI cwire codec is layout-/allocator-sensitive (malloc/free, flat | |
| # struct packing, allocShared for seq/Option), so cover it across the full | |
| # OS matrix, not just Linux. | |
| name: C Wire Codec | |
| needs: versions | |
| uses: ./.github/workflows/test.yml | |
| with: | |
| test: test_c_wire | |
| nim-versions: ${{ needs.versions.outputs.nim-versions }} | |
| nimble-version: ${{ needs.versions.outputs.nimble }} | |
| cpp-e2e: | |
| # Native-binding e2e across the OS matrix. C++ runs on every OS; the C and | |
| # Rust suites (added below) run Linux-only, so the job id stays `cpp-e2e` | |
| # for the required-check name even though it now covers all three backends. | |
| # Codegen output doesn't vary with mm, so we matrix over OS and Nim only. | |
| # Windows runs MSVC by default and may surface codegen tweaks needed in | |
| # the generated CMake (e.g. /EHsc, dllexport) — track follow-ups as bugs | |
| # if they appear. `fail-fast: false` keeps Linux/macOS results visible. | |
| needs: versions | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-22.04, macos-15, windows-latest] | |
| nim-version: ${{ fromJSON(needs.versions.outputs.nim-versions) }} | |
| include: | |
| - os: ubuntu-22.04 | |
| label: Linux | |
| - os: macos-15 | |
| label: macOS | |
| - os: windows-latest | |
| label: Windows | |
| runs-on: ${{ matrix.os }} | |
| name: C++ E2E · ${{ matrix.label }} · Nim ${{ matrix.nim-version }} | |
| env: | |
| NIMBLE_VERSION: ${{ needs.versions.outputs.nimble }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup Nim | |
| uses: jiro4989/setup-nim-action@v2 | |
| with: | |
| nim-version: ${{ matrix.nim-version }} | |
| repo-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Install Nimble ${{ env.NIMBLE_VERSION }} | |
| shell: bash | |
| run: | | |
| if [ "$RUNNER_OS" == "Windows" ]; then | |
| export PATH="$GITHUB_WORKSPACE/.nim_runtime/bin:$PATH" | |
| fi | |
| cd /tmp && nimble install "nimble@${{ env.NIMBLE_VERSION }}" -y | |
| echo "$HOME/.nimble/bin" >> $GITHUB_PATH | |
| - name: Cache nimble deps | |
| id: cache-nimbledeps | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| nimbledeps/ | |
| nimble.paths | |
| key: ${{ runner.os }}-nimbledeps-${{ matrix.nim-version }}-${{ hashFiles('*.nimble') }} | |
| restore-keys: | | |
| ${{ runner.os }}-nimbledeps-${{ matrix.nim-version }}- | |
| ${{ runner.os }}-nimbledeps- | |
| - name: Install nimble deps | |
| if: steps.cache-nimbledeps.outputs.cache-hit != 'true' | |
| shell: bash | |
| run: | | |
| if [ "$RUNNER_OS" == "Windows" ]; then | |
| export PATH="$GITHUB_WORKSPACE/.nim_runtime/bin:$HOME/.nimble/bin:$PATH" | |
| fi | |
| nimble setup --localdeps -y | |
| - name: Cache CMake FetchContent (GoogleTest) | |
| uses: actions/cache@v4 | |
| with: | |
| path: tests/e2e/cpp/build/_deps | |
| # ImageVersion busts the cache when the toolchain (e.g. MSVC) bumps. | |
| key: ${{ runner.os }}-cpp-e2e-deps-${{ env.ImageVersion }}-${{ hashFiles('tests/e2e/cpp/CMakeLists.txt') }} | |
| - name: Run C++ e2e tests | |
| shell: bash | |
| run: | | |
| if [ "$RUNNER_OS" == "Windows" ]; then | |
| export PATH="$GITHUB_WORKSPACE/.nim_runtime/bin:$HOME/.nimble/bin:$PATH" | |
| fi | |
| nimble test_cpp_e2e -y | |
| # The CBOR-free abi=c C binding (issue #105). Linux-only: the generated | |
| # header is platform-checked by the check-bindings job, and the runtime | |
| # path only needs one OS to exercise the flat-struct dispatch. | |
| - name: Run abi=c C e2e test | |
| if: matrix.label == 'Linux' | |
| shell: bash | |
| run: nimble test_c_abi_e2e -y | |
| # CBOR C bindings: exercises the async callback API and the blocking | |
| # `_sync` wrappers. Linux-only (codegen is platform-checked by | |
| # check-bindings; one OS is enough for the runtime round-trip). | |
| - name: Run C e2e tests | |
| if: matrix.label == 'Linux' | |
| shell: bash | |
| run: nimble test_c_e2e -y | |
| # Rust bindings: drives the generated blocking + tokio-async wrappers | |
| # through the full FFI round-trip. Linux-only for the same reason. | |
| - name: Run Rust e2e tests | |
| if: matrix.label == 'Linux' | |
| shell: bash | |
| run: nimble test_rust_e2e -y | |
| check-bindings: | |
| # Single OS is enough — codegen output is platform-independent; the Nim | |
| # matrix catches version-sensitive output (the PR #39 drift class). | |
| name: Check generated bindings | |
| needs: versions | |
| uses: ./.github/workflows/nimble-job.yml | |
| with: | |
| run: nimble check_bindings -y | |
| nim-versions: ${{ needs.versions.outputs.nim-versions }} | |
| nimble-version: ${{ needs.versions.outputs.nimble }} | |
| tests-asan-ubsan: | |
| name: Tests · ASan+UBSan+LSan | |
| needs: versions | |
| uses: ./.github/workflows/tests-sanitized.yml | |
| with: | |
| sanitizer: asan-ubsan | |
| nim-versions: ${{ needs.versions.outputs.nim-versions }} | |
| nimble-version: ${{ needs.versions.outputs.nimble }} | |
| tests-tsan: | |
| name: Tests · TSan | |
| needs: versions | |
| uses: ./.github/workflows/tests-sanitized.yml | |
| with: | |
| sanitizer: tsan | |
| nim-versions: ${{ needs.versions.outputs.nim-versions }} | |
| nimble-version: ${{ needs.versions.outputs.nimble }} | |
| submit-scaling-gate: | |
| # Forcing function, red by design: asserts sendRequestToFFIThread submit | |
| # throughput scales with producer-thread count. The per-request global lock | |
| # serialises every submit, so this stays red until the lock is replaced with | |
| # MPSC ingress — a standing reminder, not a transient failure. Pinned to orc + | |
| # unsanitized because the gate is timing-based and the contention it measures | |
| # is mm-independent. Full rationale and baseline numbers: tests/bench/README.md. | |
| name: Submit Scaling Gate | |
| needs: versions | |
| uses: ./.github/workflows/nimble-job.yml | |
| with: | |
| run: NIM_FFI_MM=orc FFI_SUBMIT_PER_THREAD=20000 nimble bench_ffi_submit -y | |
| nim-versions: ${{ needs.versions.outputs.nim-versions }} | |
| nimble-version: ${{ needs.versions.outputs.nimble }} | |
| auto-assign: | |
| name: Auto-assign PR author | |
| if: github.event_name == 'pull_request' && github.event.action == 'opened' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| pull-requests: write | |
| steps: | |
| - run: gh pr edit "$PR" --repo "$REPO" --add-assignee "$AUTHOR" | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| REPO: ${{ github.repository }} | |
| PR: ${{ github.event.pull_request.number }} | |
| AUTHOR: ${{ github.event.pull_request.user.login }} |