cargo-auto - automation tasks written in Rust language for the build process of Rust projects
version: 2022.618.1547 date: 2022-06-18 author: bestia.dev repository: Github
Hashtags: #rustlang #buildtool #developmenttool #cli
First, we will use cargo-auto
to create a new empty CLI Rust project similar to cargo new
, but with a more complete project structure.
```bash cargo install cargo-auto cargo auto newcli myhelloproject cd myhello_project cargo auto
cargo auto build cargo auto release cargo auto doc cargo auto test ```
We can also add automation tasks
to an existing Rust project.
Inside your Rust project directory (the one with Cargo.toml) run:
```bash cargo auto new_auto cargo auto
cargo auto build ```
Congratulations! You are already using cargo-auto
. Simple as that.
Now you can modify the tasks to your needs. It is all Rust language.
Cargo is a great tool for building Rust projects. It has all the basics: cargo build
, cargo build --release
, cargo fmt
, cargo test
, cargo doc
,...
But sometimes we need to do more things like copying some files, publish to ftp or enter long commands. These repetitive tasks must be automated.
Task automation makes work easier and faster, simplifies the workflow, while improving the consistency and accuracy of workflows.
This is also sometimes referred to as "workflow automation."
There are many different build systems and task runners there: make
, cmake
, shell scripts
, cargo-xtask
, cargo-make
, cargo-task
, cargo-script
, cargo-run-script
, runner
, python scripts
, powershell scripts
, cmd prompt scripts
, ...
Sadly there is no standard in the Rust community for now.
I want something similar to build.rs, so I can write my "tasks" in pure Rust I don't want to learn another meta language with weird syntax and difficult to debug. So I will make something really simple, easy, rusty and extensible.
I like very much that Rust has the command cargo new project_name
. It creates a super simple Rust hello project that can be build and run immediately. But this example is too simple. It lacks basic file structures of a serious CLI program.
I composed an opinionated template for a Rust CLI project. It is easy to run:
bash
cargo auto new_cli project_name
Rust is a compiled language. It is not really a scripting or interpreted language. But the compilation of small projects is really fast and can be ignored. Subsequent calls will use the already built binary and so the speed will be even faster.
This tool cargo-auto
is meant for Rust projects, so it means that all the Rust infrastructure is already in place.
The command cargo auto new_auto
will create a new directory automation_tasks_rs
with a template for a helper Rust project in the root directory of your main Rust project
. It should not interfere with the main Rust project. This directory will be added into git commits and pushed to remote repositories as part of the main project. It has its own .gitignore
to avoid committing its target directory.
The automation_tasks_rs
helper project contains user defined tasks in Rust code. Your tasks. This helper project should be opened in a new editor starting from the automation_tasks_rs
directory. It does not share dependencies with the main project. It is completely separate and independent.
You can edit it and add your dependencies and Rust code. No limits. Freedom of expression.
This is now your code, your tasks and your helper Rust project!
Because only you know what you want to automate and how to do it.
Basic example:
```rust
/// match arguments and call tasks functions
fn matchargumentsandcalltasks(mut args: std::env::Args){
// the first argument is the user defined task: (no argument for help), build, release,...
let arg1 = args.next();
match arg1 {
None => printhelp(),
Some(task) => {
println!("Running auto task: {}", &task);
if &task == "build"{
taskbuild();
} else if &task == "release" {
taskrelease();
} else if &task == "doc" {
taskdoc();
} else {
println!("Task {} is unknown.", &task);
print_help();
}
}
}
}
/// write a comprehensible help for user defined tasks fn printhelp() { println!("User defined tasks in automationtasks_rs:"); println!("cargo auto build - builds the crate in debug mode"); println!("cargo auto release - builds the crate in release mode"); println!("cargo auto docs - builds the docs"); }
// region: tasks
/// cargo build fn taskbuild() { #[rustfmt::skip] let shellcommands = [ "echo $ cargo fmt", "cargo fmt", "echo $ cargo build", "cargo build"]; runshellcommands(shellcommands.tovec()); }
/// cargo build --release fn taskrelease() { println!("$ cargo fmt"); runshellcommand("cargo fmt"); println!("$ cargo build --release"); runshell_command("cargo build --release"); }
/// cargo doc, then copies to /docs/ folder, because this is a github standard folder fn taskdoc() { #[rustfmt::skip] let shellcommands = [ "echo $ cargo doc --no-deps --document-private-items --open", "cargo doc --no-deps --document-private-items --open", // copy to /docs/ because it is github standard "echo $ rsync -a --info=progress2 --delete-after target/doc/ docs/", "rsync -a --info=progress2 --delete-after target/doc/ docs/", "echo Create simple index.html file in docs directory", &format!("echo \"\" > docs/index.html",&projectdirectoryname()) , // message to help user with next move "echo After successful doc, commit and push changes", ]; runshellcommands(shellcommands.tovec()); }
// endregion: tasks
```
The command cargo install cargo-auto
will add a new subcommand to cargo:
bash
cargo auto
This binary is super simple. It has only 3 trivial dependencies: unwrap
, termion
and lazy_static
.
The binary only reads the CLI arguments and runs the automation_tasks_rs
binary with them. If needed it will compile automation_tasks_rs
first.
The code-flow of the source code of cargo-auto
is simple, fully commented and straightforward to audit.
The source code is on GitHub with MIT open-source licensing.
With the help of the crate devbestiacargo_completion the commands cargo
and cargo auto
get bash auto-completion. Try it!
Inside the cargo-auto project there is a Rust sub-projects that is a template. I can open a new editor for this directories and build this crate independently. So it is easy to debug and develop.
Sadly, I cannot publish these directories and files to crates.io
. I can effectively publish only the source code inside my main Rust project cargo-auto
.
Therefor, before publishing I copy the content of these files into the modules template_new_auto_mod.rs
on every build. It is not difficult now that Rust has fantastic raw strings.
You can write more complex tasks in Rust language.
For example in this project I use automation to create github Releases : https://github.com/bestia-dev/dropbox_backup_to_external_disk
Here is pretty complex workspace with more sub-projects:
https://github.com/bestia-dev/cargo_crev_reviews_workspace
There is no end to your imagination. If you write something that looks it can help other developers, please share it with me and I will add it here.
Usually I compile and run the code of cargo-auto
with added arguments like this:
bash
cargo run -- new_auto
cargo run -- build
cargo run -- release
Get the username from git, to use it in Cargo.toml of new_cli
We live in times of danger with supply chain attacks.
It is recommended to always use cargo-crev
to verify the trustworthiness of each of your dependencies.
Please, spread this info.
You can also read reviews quickly on the web:
https://web.crev.dev/rust-reviews/crates/
My open-source projects are free as a beer (MIT license).
I just love programming.
But I need also to drink. If you find my projects and tutorials helpful,
please buy me a beer donating on my paypal.
You know the price of a beer in your local bar ;-)
So I can drink a free beer for your health :-)
Na zdravje! Alla salute! Prost! Nazdravlje! 🍻