In this post we’ll create our own third-party cargo subcommand, cargo deploy. When we call our command in a Rust project, the command will send a binary to our server at Netlify, and print out the URL in the command line.
Let’s get started.
Naming
The binary of our command needs to be named cargo-${command}. In our case we’ll name it cargo-deploy.
Placement
The binary of our command needs to be stored in ~/.cargo/bin.
There’s an easy way to do this: we simply create the binary (named cargo-deploy) and then publish it to crates.io.
Then, cargo install cargo-deploy will download and place the binary in ~/.cargo/bin.
cargo-deploy also needs an HTTP client to make requests against our API, as well as some config logic to hold API keys. Finally, cargo-deploy needs to use the cargo crate to programmatically run cargo commands like cargo package.
How it works
cargo deploy runs cargo package under the hood, zipping up the current cargo project into a tarball and shipping it to our API under the /deploy endpoint with a bearer token for authentication.
-
The API receives the tarball and holds it in memory. The build is added to a job processor which acts as a build queue.
-
The job processor unpacks the tarball and writes it to disk, say under
/projects/my-app. The build system is triggered to compile the unpacked cargo project. -
The output of the build process is a shared object file (
.so) which is then dynamically loaded by the API with its own runtime. The newly born web server is assigned a free port which is not exposed to the outside world. -
We update the routing table of our reverse proxy such that requests coming in with the host
my-app.shuttleapp.rsare forwarded to the aforementioned port.