mpalmer / action-validator

Tool to validate GitHub Action and Workflow YAML files
GNU General Public License v3.0
267 stars 25 forks source link

Proposal: Replace wasm-bindgen with WASI #40

Open bcheidemann opened 1 year ago

bcheidemann commented 1 year ago

Problem statement

The current implementation of @action-validator/core and @action-validator/cli requires JS glue code for any kind of system access (e.g. network, filesystem, and even logging). This is not ideal since it means that certain crates are not (easily) usable by the WASM and for each case we need to find an alternative implementation for JS or use a different crate. This could result in an undue maintenance burden and the features supported by @action-validator/* lagging behind the native binary.

What is currently affected?

  1. glob validation
  2. "use" validation remote-checks feature

Possible solution (WASI)

WebAssembly System Interface (WASI) is a modular system interface for WASM which allows filesystem and network access directly from WASM code. Pivoting from WASM bindgen to using WASI has the following benefits:

  1. Direct system access means more crates will "just work" without the need for additional JS glue code
  2. It allows us to trivially target more platforms, since it is set to be officially supported by Node.js, Deno, and is even supported in the browser by some third party NPM modules (e.g. wasi-js).

WASI is currently well supported by RUST via the wasm32-wasi target and I have used it in a couple of smaller projects now with some success. I would suggest compiling to the wasm32-wasi target and consuming the resulting *.wasm binary using wasi-js, since this exposes the same API as is exposed by Node.js and Deno and can be easily removed in future when these APIs stabalise.

Limitations (WASI)

The main limitation is that WASI is currently at the proposal stage and is not yet an official standard. Although relying on an unofficial standard isn't ideal, WASI seems to have a lot of momentum behind it and progress seems very unlikely to stall out.


@mpalmer I'd be interested to get your opinion on this? I think it would be worthwhile to at least do a PoC for this since it would likely solve the issue of supporting the remote-checks feature and glob validation with very little extra effort and reduce future maintenance burden of WASM/NPM support.


Update (18/03/2023)

I had some difficulty trying to expose library methods to @action-validator/core using WASI. Having looked into alternatives, it may be better (for now) to pivot to building on the Node-API. The following packages are possible solutions:

  1. NAPI-RS
  2. Node Bindgen
  3. Neon

Limitations (Node-API)

The primary limitation of using the Node-API is portability. While a WASI build would (in theory) be compatible with any target which supports WASI (Node, Deno, Python, Wasmtime etc), a Node-API would only be compatible with Node.

mpalmer commented 1 year ago

I don't really have the expertise to make the best decision on this, I think. WASI does seem like a better approach than trying to tiptoe around the great mass of crates that won't ever be WASM-compatible, and your suggestion of at least trying it out on a branch and seeing what explodes seems like a great first step.

bcheidemann commented 1 year ago

I don't really have the expertise to make the best decision on this, I think. WASI does seem like a better approach than trying to tiptoe around the great mass of crates that won't ever be WASM-compatible, and your suggestion of at least trying it out on a branch and seeing what explodes seems like a great first step.

@mpalmer I think that's a good approach :) I'll do some tinkering this weekend and see how I get on

bcheidemann commented 1 year ago

I've had some success with compiling the binary to wasm32-wasi and consuming the resulting *.wasm file from Node. It is able to log to stdout and stderr, and well as read the input file using the standard library, without any changes to the code (as are currently needed for JS support). However, I had some issues with the glob validation, which seemed to be unable to match files, and therefore always resulted in an error. Other than that issue, this seems like a promising direction for the CLI, but in order to support library usage (i.e. @action-validator/core), more investigation is needed. As I understand it, node-bindgen can be used with the wasm32-wasi compilation target and I did have some success with compiling trivial libraries, but ended up encountering a lot of nebulous build errors and haven't gotten close to being able to compile lib.rs to a usable "*.wasm" file.

Having done some more research into other options, the following may also be worth looking into:

  1. NAPI-RS
  2. Node Bindgen
  3. Neon

As far as I know, these only target Node.js, and would rule out supporting other targets such as Deno, the browser, wasmtime etc. Maybe this is an acceptable trade-off if WASI is not yet a practical solution.

bcheidemann commented 1 year ago

Following some discussion with @award28 and @mpalmer I am now leaning towards N-API as a solution to this problem and will re-focus my efforts in this direction.