use std::process::Command;
use anyhow::{Context, Result};
use clap::Parser;
use crate::commands::build::{self, BuildArgs};
use crate::commands::lint::{self, LintArgs};
use crate::ui;
#[derive(Debug, Parser)]
pub struct CheckArgs {
#[arg(long)]
pub fix: bool,
#[arg(long)]
pub skip_tests: bool,
}
pub async fn run(args: CheckArgs) -> Result<()> {
ui::header(
"portaki check",
"Formatting, lints, tests, the wasm build, and the manifest — what CI will ask.",
);
let started = std::time::Instant::now();
format_step(args.fix)?;
clippy_step(args.fix)?;
if args.skip_tests {
ui::skipped("tests skipped (--skip-tests)");
} else {
let mut cmd = Command::new("cargo");
cmd.arg("test");
ui::command("cargo test", &mut cmd).context("cargo test")?;
}
ui::blank();
build::run(BuildArgs {
release: true,
manifest_only: false,
nested: true,
})
.await?;
lint::run(LintArgs {
manifest: None,
nested: true,
})?;
ui::blank();
ui::success(format!("checked in {}", ui::elapsed(started.elapsed())));
ui::next(&[
(
"portaki dev --watch",
"run it in the hosted sandbox on every save",
),
("portaki publish", "push the artifact and announce it"),
]);
ui::blank();
Ok(())
}
fn format_step(fix: bool) -> Result<()> {
let mut cmd = Command::new("cargo");
cmd.arg("fmt");
if !fix {
cmd.arg("--check");
}
let label = if fix {
"cargo fmt"
} else {
"cargo fmt --check"
};
ui::command(label, &mut cmd).context(label.to_string())
}
fn clippy_step(fix: bool) -> Result<()> {
if fix {
let mut fixing = Command::new("cargo");
fixing
.arg("clippy")
.arg("--fix")
.arg("--allow-dirty")
.arg("--allow-staged")
.arg("--all-targets");
ui::command("cargo clippy --fix", &mut fixing).context("cargo clippy --fix")?;
}
let mut cmd = Command::new("cargo");
cmd.arg("clippy")
.arg("--all-targets")
.arg("--")
.arg("-D")
.arg("warnings");
ui::command("cargo clippy -D warnings", &mut cmd).context("cargo clippy -D warnings")
}