summaryrefslogtreecommitdiff
path: root/src/hook.rs
diff options
context:
space:
mode:
authorDawid Rycerz <dawid@rycerz.xyz>2026-02-15 21:27:00 +0100
committerDawid Rycerz <dawid@rycerz.xyz>2026-02-15 21:27:00 +0100
commitce0dbf6b249956700c6a1705bf4ad85a09d53e8c (patch)
treed7c3236807cfbf75d7f3a355eb5df5a5e2cc4ad7 /src/hook.rs
parent064a1d01c5c14f5ecc032fa9b8346a4a88b893f6 (diff)
feat: witryna 0.2.0HEADv0.2.0main
Switch, cleanup, and status CLI commands. Persistent build state via state.json. Post-deploy hooks on success and failure with WITRYNA_BUILD_STATUS. Dependency diet (axum→tiny_http, clap→argh, tracing→log). Drop built-in rate limiting. Nix flake with NixOS module. Arch Linux PKGBUILD. Centralized version management. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'src/hook.rs')
-rw-r--r--src/hook.rs45
1 files changed, 43 insertions, 2 deletions
diff --git a/src/hook.rs b/src/hook.rs
index 53e1e18..6cb3823 100644
--- a/src/hook.rs
+++ b/src/hook.rs
@@ -1,4 +1,5 @@
use crate::build::copy_with_tail;
+use log::debug;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::process::Stdio;
@@ -6,7 +7,6 @@ use std::time::{Duration, Instant};
use tokio::io::AsyncWriteExt as _;
use tokio::io::BufWriter;
use tokio::process::Command;
-use tracing::debug;
#[cfg(not(test))]
const HOOK_TIMEOUT: Duration = Duration::from_secs(30);
@@ -47,6 +47,7 @@ pub async fn run_post_deploy_hook(
build_dir: &Path,
public_dir: &Path,
timestamp: &str,
+ build_status: &str,
env: &HashMap<String, String>,
stdout_file: &Path,
stderr_file: &Path,
@@ -84,6 +85,7 @@ pub async fn run_post_deploy_hook(
.env("WITRYNA_BUILD_DIR", build_dir.as_os_str())
.env("WITRYNA_PUBLIC_DIR", public_dir.as_os_str())
.env("WITRYNA_BUILD_TIMESTAMP", timestamp)
+ .env("WITRYNA_BUILD_STATUS", build_status)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn();
@@ -106,7 +108,7 @@ pub async fn run_post_deploy_hook(
}
};
- debug!(cmd = ?command, "hook process spawned");
+ debug!("hook process spawned: {command:?}");
let (last_stderr, exit_code, success) =
stream_hook_output(&mut child, stdout_file, stderr_file).await;
@@ -231,6 +233,7 @@ mod tests {
tmp.path(),
&tmp.path().join("current"),
"ts",
+ "success",
&HashMap::new(),
&stdout_tmp,
&stderr_tmp,
@@ -255,6 +258,7 @@ mod tests {
tmp.path(),
&tmp.path().join("current"),
"ts",
+ "success",
&HashMap::new(),
&stdout_tmp,
&stderr_tmp,
@@ -277,6 +281,7 @@ mod tests {
tmp.path(),
&tmp.path().join("current"),
"ts",
+ "success",
&HashMap::new(),
&stdout_tmp,
&stderr_tmp,
@@ -305,6 +310,7 @@ mod tests {
tmp.path(),
&public_dir,
"20260202-120000-000000",
+ "success",
&env,
&stdout_tmp,
&stderr_tmp,
@@ -315,6 +321,7 @@ mod tests {
let stdout = fs::read_to_string(&stdout_tmp).await.unwrap();
assert!(stdout.contains("WITRYNA_SITE=my-site"));
assert!(stdout.contains("WITRYNA_BUILD_TIMESTAMP=20260202-120000-000000"));
+ assert!(stdout.contains("WITRYNA_BUILD_STATUS=success"));
assert!(stdout.contains("WITRYNA_BUILD_DIR="));
assert!(stdout.contains("WITRYNA_PUBLIC_DIR="));
assert!(stdout.contains("PATH="));
@@ -336,6 +343,7 @@ mod tests {
"WITRYNA_BUILD_DIR",
"WITRYNA_PUBLIC_DIR",
"WITRYNA_BUILD_TIMESTAMP",
+ "WITRYNA_BUILD_STATUS",
"MY_VAR",
"DEPLOY_TARGET",
]
@@ -357,6 +365,7 @@ mod tests {
tmp.path(),
&tmp.path().join("current"),
"ts",
+ "success",
&HashMap::new(),
&stdout_tmp,
&stderr_tmp,
@@ -380,6 +389,7 @@ mod tests {
tmp.path(),
&tmp.path().join("current"),
"ts",
+ "success",
&HashMap::new(),
&stdout_tmp,
&stderr_tmp,
@@ -404,6 +414,7 @@ mod tests {
tmp.path(),
&tmp.path().join("current"),
"ts",
+ "success",
&HashMap::new(),
&stdout_tmp,
&stderr_tmp,
@@ -432,6 +443,7 @@ mod tests {
tmp.path(),
&tmp.path().join("current"),
"ts",
+ "success",
&HashMap::new(),
&stdout_tmp,
&stderr_tmp,
@@ -460,6 +472,7 @@ mod tests {
tmp.path(),
&tmp.path().join("current"),
"ts",
+ "success",
&HashMap::new(),
&stdout_tmp,
&stderr_tmp,
@@ -472,6 +485,33 @@ mod tests {
}
#[tokio::test]
+ async fn hook_env_build_status_failed() {
+ let tmp = TempDir::new().unwrap();
+ let stdout_tmp = tmp.path().join("stdout.tmp");
+ let stderr_tmp = tmp.path().join("stderr.tmp");
+
+ let result = run_post_deploy_hook(
+ &cmd(&["env"]),
+ "test-site",
+ tmp.path(),
+ &tmp.path().join("current"),
+ "ts",
+ "failed",
+ &HashMap::new(),
+ &stdout_tmp,
+ &stderr_tmp,
+ )
+ .await;
+
+ assert!(result.success);
+ let stdout = fs::read_to_string(&stdout_tmp).await.unwrap();
+ assert!(
+ stdout.contains("WITRYNA_BUILD_STATUS=failed"),
+ "WITRYNA_BUILD_STATUS should be 'failed'"
+ );
+ }
+
+ #[tokio::test]
async fn hook_user_env_does_not_override_reserved() {
let tmp = TempDir::new().unwrap();
let stdout_tmp = tmp.path().join("stdout.tmp");
@@ -484,6 +524,7 @@ mod tests {
tmp.path(),
&tmp.path().join("current"),
"ts",
+ "success",
&env,
&stdout_tmp,
&stderr_tmp,