From b7c254287c8acbb7589a018b9c330fff3e8155fa Mon Sep 17 00:00:00 2001 From: spacedevin Date: Mon, 3 Aug 2026 14:48:46 -0700 Subject: [PATCH] fix(ci): build and test the Rust crate on every PR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The crate is emitted from the same src/index.tish as dist/deck.js, and that is the whole mechanism keeping the JS host and tish-gba's build-time bake from drifting. CI never built it. So a change that broke the rust-lib emit, or that made the two targets parse the same file differently, would have gone unnoticed until release — or until a consumer hit it. The guarantee was asserted, not tested. Adds a `rust_crate` job that emits the crate and runs `cargo test` — the same conformance corpus the JS build is checked against — plus a `cargo publish --dry-run` so a crate that cannot be packaged fails on the PR rather than at publish time. `release` now depends on it, so a broken crate cannot be released. Also carries the @tishlang/tish 3.2.2 bump onto a release. That landed as `chore:`, which is not release-triggering, so the push failed the repo's "require incremental release" gate and left the bump untagged. It should have been `fix:` — the old `>=2.43.0` floor declared support for versions that cannot emit the crate at all. --- .github/workflows/ci.yml | 44 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 62a2424..6c8917d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,6 +38,48 @@ jobs: - name: Build run: npm run build + # The Rust crate is emitted from the SAME src/index.tish as dist/deck.js, which is what stops the + # JS host and tish-gba's build-time bake from drifting. Nothing verified that: a change that broke + # the rust-lib emit, or that made the two targets parse differently, would have gone unnoticed + # until release — or until a consumer hit it. `cargo test` here runs the same conformance corpus + # the JS build is checked against, so both targets are held to one contract on every PR. + rust_crate: + name: Rust crate (deckfile) + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: "22" + + - name: Install dependencies + run: npm ci + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + + - name: Cache cargo + uses: Swatinem/rust-cache@v2 + with: + workspaces: crate + + - name: Emit the crate + run: | + export PATH="$PWD/node_modules/.bin:$PATH" + npm run build:rust + + - name: Conformance corpus (from Rust) + working-directory: crate + run: cargo test + + # A crate that cannot be packaged cannot be released; catch that on the PR, not at publish. + - name: Packaging check + working-directory: crate + run: cargo publish --dry-run --allow-dirty + release_check: name: Release check (semantic-release dry-run) runs-on: ubuntu-latest @@ -80,7 +122,7 @@ jobs: release: name: Release (prerelease branch + GitHub API) - needs: [test, release_check] + needs: [test, rust_crate, release_check] if: github.ref == 'refs/heads/main' && github.event_name == 'push' runs-on: ubuntu-latest permissions: