kettleby / semantic-release-rust

Apache License 2.0
17 stars 2 forks source link

Publish package on npmjs #26

Open sbosnick opened 3 years ago

sbosnick commented 3 years ago

semantic-release-rust leans heavily on guppy for its functionality so it would be difficult to rewrite this semantic-release plugin in JavaScript (it would require rewriting large parts of guppy and cargo_metadata on which it relies). The alternative, which would still allow us to avoid the semantic-release-exec plugin, is to publish a native Node.js package using node-bindgen or one of the alternative Node.js FFI packages on crates.io.

This can be implemented as a new subdirectory that is both a JavaScript package (it has a package.json file) and a Rust crate that implements the native Node.js package using node-bindgen.

sbosnick commented 3 years ago

The two alterative Node.js FFI packages to also consider are Neon and napi-rs. Of the three options (Neon, napi-rs, and node-bindgen) napi-rs looks the most promising.

node-bindgen looks like it gives the best embedding of the FFI into Rust, but it is the most lightly documented and does not appear to give any assistance with formulating a correct package.json file.

Neon is the most mature of the three options and the best documents. It does, though, have build dependencies beyond Rust and Node that the other two options lack. It also doesn't appear to have a good option for publishing the complied Rust package directly to npmjs (though it is being worked on).

napi-rs is almost as mature as Neon and is reasonably well documented. It does not have any build dependencies beyond Rust and Node and has a developed approach for publishing the architecture specific binaries that is produces.

Of the three options napi-rs looks the most promising. I will be trying to implement this feature with that option.

jtcarnes commented 3 years ago

@sbosnick Semantic-release plugins are generally written in JS as semantic-release is written in JS. It mentions in their documentation for creating plugins: "semantic release will require plugin via node" source

If it's a desired feature, I am happy to help transition this into a JS to make it integrate more cleaning with semantic release.

sbosnick commented 3 years ago

Thank you for your offer to help. It is true that one of reasons I initially developed this as a Rust CLI application is my limited (read almost non-existent) understanding of JS so help with the JS side of this issue would be very much appreciated.

That said, though, the other reason for implementing this in Rust was to make use of the guppy crate to do most of the heavy lifting. semantic-release-rust is designed to support Rust workspaces with multiple crates that need to be published in a specific order (this is a requirement of publishing to crates.io). guppy gathers this information for us by: 1. running cargo metadata, 2. parsing the resulting JSON and producing a graph using the inter-crate dependencies, and 3. running a topological sort on the resulting graph.

I assume that parsing JSON in JS is a no-brainier. I also assume (though I haven't checked) that JS has a decent graph library available that can do a topological sort. It would still, though, be a fair bit of work to duplicate the parts of guppy that this project needs and we would miss out on guppy's handling of certain corner cases unless we duplicated that work ourselves.

The way I designed semantic-release-rust was with a Rust library crate that does most of the work and a binary crate that acts as a CLI shim over the library. I designed it this way to allow for a future expansion of a native Node module shim over the library crate as well as the CLI shim. This issue is that "future expansion".

From my understanding of napi-rs it facilitates an approach to publishing a Node native module to npm that can then be required via node (one example of this is @node-rs/crc32).

I started some initial exploratory work on a native module using napi-rs but then got side tracked with other commitments. I will try to push a branch with what I have so far to GitHub later this weekend (it is on an old computer so it will take a small bit of work to do so).

If you have any thoughts on how to advance the napi-rs approach or if you think the "re-implementing parts of guppy" approach is less work that I have made it out to be then I would be happy to hear your suggestions.