Compile regular Rust into Argo Workflow YAML.
cargo add cargo-athena --no-default-features # the library (lean — no CLI deps)
cargo install cargo-athena # the `cargo athena` subcommand
# …or get the CLI via Nix (flake):
nix profile install github:mostlymaxi/cargo-athena # install
nix run github:mostlymaxi/cargo-athena -- athena … # one-off, no installImportant
Library users: keep default-features = false. A workflow crate
needs only the proc macros + runtime; the default cli feature pulls
a heavy CLI tree (kube, reqwest, tokio, …) it doesn't use.
📖 Documentation — from
zero to adept (the same #[workflow]/#[container] reference is also in
cargo doc).
Supported Argo Workflows — every push to main submits the
examples/e2e workflow to a real Argo + MinIO per version and
asserts it Succeeded; these badges are that live result:
| Argo | Support | e2e |
|---|---|---|
| v4.0.5 | maintained (latest minor) | |
| v3.7.14 | maintained (n‑1 minor) | |
| v3.6.19 | minimum supported (EOL) |
Argo ≤ 3.5 is unsupported - older versions may still work, use at your own risk!
Annotate ordinary functions. A #[workflow] is a DAG; a #[container]
is a step that runs real Rust in a pod; a #[fragment] is a plain
helper that carries pod resources.
use cargo_athena::{workflow, container, fragment};
#[workflow]
fn run_foo() {
let a = some_other_workflow("asdf".to_string());
run_a_container(a); // data dep -> DAG edge + param wiring
}
#[container(image = "ghcr.io/acme/app:latest")]
fn run_a_container(a: String) {
let cfg = cargo_athena::host!("/etc/myapp"); // hostPath mount
load_extra();
println!("regular code, got: {a}");
}
#[fragment]
fn load_extra() { let _ = cargo_athena::host!("/var/lib/extra"); }
fn main() { cargo_athena::entrypoint::<run_foo>(); } // entrypoint = a typeEach #[workflow]/#[container] compiles to its own Argo
WorkflowTemplate, cross-referenced by templateRef (referencing a
template's type force-links its crate, so workflows compose across
modules and crates with no registry). cargo athena publish
cross-compiles one static-musl binary and uploads it to the S3
ArtifactRepository from athena.toml; emit injects that binary plus a tiny sh
bootstrap into every container template, so in-pod each step pulls the
binary, picks its arch, and runs the right function — deserialize
inputs, run the body, serialize outputs.
cargo athena emit --package my-workflows # check the YAML (no cluster)
cargo athena publish --package my-workflows # cross-compile + upload the binary
cargo athena submit my-workflows-run-foo -a seed=hi # register templates + run
# GitOps alternative (commit the manifests; run from the registered root):
# cargo athena emit --package my-workflows | kubectl apply -f -
# argo submit --from workflowtemplate/my-workflows-run-foo --watchThe full zero→running walkthrough (including uploading the binary to your bucket) is in the docs.
Full feature reference: WORKFLOW.md (every
#[workflow] arg + call form) and CONTAINER.md (every
#[container] arg, #[fragment], and in-pod macro). The same content is
on the macros in cargo doc.
nix develop # toolchain + zig/cargo-zigbuild + kubectl/argo/mc (easiest; optional)
cargo test --workspace # unit + golden + trybuild compile-fail contracts
nix build # -> ./result/bin/cargo-athena
# full e2e on real kind + Argo + MinIO (needs a Docker/Podman daemon):
scripts/deploy.sh && scripts/e2e-test.sh && scripts/teardown.sh
# ATHENA_E2E_SINGLE=1 for a 1-node cluster (hosts blocking kind cross-node networking)The dev shell pulls a prebuilt Rust toolchain from
nix-community.cachix.org (fenix) instead of compiling it. Trusted Nix
users get this automatically; otherwise pass --accept-flake-config
(or add yourself to trusted-users in nix.conf).
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.