chore(build): preparing for CI

This commit is contained in:
2026-03-08 15:44:26 +01:00
parent a45f0424f4
commit d9c3456175
6 changed files with 90 additions and 65 deletions

View File

@@ -3,4 +3,4 @@ out = ["Xml"]
target-dir = "coverage" target-dir = "coverage"
output-dir = "coverage" output-dir = "coverage"
fail-under = 60 fail-under = 60
exclude-files = ["target/*"] exclude-files = ["target/*", "private/*"]

View File

@@ -37,3 +37,10 @@ predicates = "3.1.3"
[lints.rust] [lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(tarpaulin_include)'] } unexpected_cfgs = { level = "warn", check-cfg = ['cfg(tarpaulin_include)'] }
[profile.release]
opt-level = "z"
lto = true
codegen-units = 1
panic = "abort"
strip = true

View File

@@ -1,4 +1,5 @@
{ {
pkgs,
rustPlatform, rustPlatform,
... ...
}: let }: let
@@ -8,8 +9,17 @@
rustBuild = rustPlatform.buildRustPackage { rustBuild = rustPlatform.buildRustPackage {
pname = name; pname = name;
inherit version; inherit version;
src = ../.; src = pkgs.lib.cleanSource ../.;
cargoLock.lockFile = ../Cargo.lock; cargoLock.lockFile = ../Cargo.lock;
buildInputs = [ pkgs.upx ];
useNextest = true;
meta = {
description = "Conventional commits for Jujutsu";
homepage = "https://labs.phundrak.com/phundrak/jj-cz";
};
postBuild = ''
${pkgs.upx}/bin/upx target/*/release/${name}
'';
}; };
in { in {
default = rustBuild; default = rustBuild;

View File

@@ -19,26 +19,10 @@ inputs.devenv.lib.mkShell {
}) })
bacon bacon
cargo-deny cargo-deny
cargo-nextest
cargo-tarpaulin cargo-tarpaulin
just just
]; ];
# processes.run.exec = "cargo watch -x run";
# enterShell = ''
# echo ""
# echo "Rust development environment loaded!"
# echo "Rust version: $(rustc --version)"
# echo "Cargo version: $(cargo --version)"
# echo ""
# echo "Available tools:"
# echo " - rust-analyzer (LSP)"
# echo " - clippy (linter)"
# echo " - rustfmt (formatter)"
# echo " - bacon (continuous testing/linting)"
# echo " - cargo-deny (dependency checker)"
# echo " - cargo-tarpaulin (code coverage)"
# '';
} }
]; ];
} }

View File

@@ -127,44 +127,51 @@ impl JjExecutor for JjLib {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use std::process::Command;
/// Initialize a jj repository in the given directory using `jj git init` /// Initialize a jj repository in the given directory using jj-lib directly
fn init_jj_repo(dir: &Path) -> std::io::Result<()> { async fn init_jj_repo(dir: &Path) -> Result<(), String> {
let output = Command::new("jj") let settings = JjLib::load_settings().map_err(|e| e.to_string())?;
.args(["git", "init"]) Workspace::init_internal_git(&settings, dir)
.current_dir(dir) .await
.output()?; .map(|_| ())
.map_err(|e| format!("Failed to init jj repo: {e}"))
if !output.status.success() {
return Err(std::io::Error::other(format!(
"jj git init failed: {}",
String::from_utf8_lossy(&output.stderr)
)));
}
Ok(())
} }
/// Get the current commit description from a jj repository /// Get the current commit description from a jj repository using jj-lib
fn get_commit_description(dir: &Path) -> std::io::Result<String> { async fn get_commit_description(dir: &Path) -> Result<String, String> {
let output = Command::new("jj") let settings = JjLib::load_settings().map_err(|e| e.to_string())?;
.args(["log", "-r", "@", "--no-graph", "-T", "description"]) let store_factories = StoreFactories::default();
.current_dir(dir) let wc_factories = default_working_copy_factories();
.output()?;
if !output.status.success() { let workspace = Workspace::load(&settings, dir, &store_factories, &wc_factories)
return Err(std::io::Error::other(format!( .map_err(|e| format!("Failed to load workspace: {e}"))?;
"jj log failed: {}",
String::from_utf8_lossy(&output.stderr) let repo = workspace
))); .repo_loader()
} .load_at_head()
Ok(String::from_utf8_lossy(&output.stdout).trim().to_string()) .await
.map_err(|e| format!("Failed to load repo: {e}"))?;
let wc_commit_id = repo
.view()
.get_wc_commit_id(WorkspaceName::DEFAULT)
.ok_or_else(|| "No working copy commit found".to_string())?
.clone();
let wc_commit = repo
.store()
.get_commit(&wc_commit_id)
.map_err(|e| format!("Failed to get commit: {e}"))?;
Ok(wc_commit.description().trim_end().to_string())
} }
#[tokio::test] #[tokio::test]
async fn is_repository_returns_true_inside_jj_repo() { async fn is_repository_returns_true_inside_jj_repo() {
let temp_dir = assert_fs::TempDir::new().unwrap(); let temp_dir = assert_fs::TempDir::new().unwrap();
init_jj_repo(temp_dir.path()).expect("Failed to init jj repo"); init_jj_repo(temp_dir.path())
.await
.expect("Failed to init jj repo");
let executor = JjLib::with_working_dir(temp_dir.path()); let executor = JjLib::with_working_dir(temp_dir.path());
let result = executor.is_repository().await; let result = executor.is_repository().await;
@@ -187,7 +194,9 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn describe_updates_commit_description() { async fn describe_updates_commit_description() {
let temp_dir = assert_fs::TempDir::new().unwrap(); let temp_dir = assert_fs::TempDir::new().unwrap();
init_jj_repo(temp_dir.path()).expect("Failed to init jj repo"); init_jj_repo(temp_dir.path())
.await
.expect("Failed to init jj repo");
let test_message = "test: initial commit"; let test_message = "test: initial commit";
let executor = JjLib::with_working_dir(temp_dir.path()); let executor = JjLib::with_working_dir(temp_dir.path());
@@ -195,14 +204,18 @@ mod tests {
let result = executor.describe(test_message).await; let result = executor.describe(test_message).await;
assert!(result.is_ok(), "describe failed: {result:?}"); assert!(result.is_ok(), "describe failed: {result:?}");
let actual = get_commit_description(temp_dir.path()).expect("Failed to get description"); let actual = get_commit_description(temp_dir.path())
.await
.expect("Failed to get description");
assert_eq!(actual, test_message); assert_eq!(actual, test_message);
} }
#[tokio::test] #[tokio::test]
async fn describe_handles_special_characters() { async fn describe_handles_special_characters() {
let temp_dir = assert_fs::TempDir::new().unwrap(); let temp_dir = assert_fs::TempDir::new().unwrap();
init_jj_repo(temp_dir.path()).expect("Failed to init jj repo"); init_jj_repo(temp_dir.path())
.await
.expect("Failed to init jj repo");
let test_message = "feat: add feature with special chars !@#$%^&*()"; let test_message = "feat: add feature with special chars !@#$%^&*()";
let executor = JjLib::with_working_dir(temp_dir.path()); let executor = JjLib::with_working_dir(temp_dir.path());
@@ -210,14 +223,18 @@ mod tests {
let result = executor.describe(test_message).await; let result = executor.describe(test_message).await;
assert!(result.is_ok()); assert!(result.is_ok());
let actual = get_commit_description(temp_dir.path()).expect("Failed to get description"); let actual = get_commit_description(temp_dir.path())
.await
.expect("Failed to get description");
assert_eq!(actual, test_message); assert_eq!(actual, test_message);
} }
#[tokio::test] #[tokio::test]
async fn describe_handles_unicode() { async fn describe_handles_unicode() {
let temp_dir = assert_fs::TempDir::new().unwrap(); let temp_dir = assert_fs::TempDir::new().unwrap();
init_jj_repo(temp_dir.path()).expect("Failed to init jj repo"); init_jj_repo(temp_dir.path())
.await
.expect("Failed to init jj repo");
let test_message = "docs: add unicode support 🎉 🚀"; let test_message = "docs: add unicode support 🎉 🚀";
let executor = JjLib::with_working_dir(temp_dir.path()); let executor = JjLib::with_working_dir(temp_dir.path());
@@ -225,14 +242,18 @@ mod tests {
let result = executor.describe(test_message).await; let result = executor.describe(test_message).await;
assert!(result.is_ok()); assert!(result.is_ok());
let actual = get_commit_description(temp_dir.path()).expect("Failed to get description"); let actual = get_commit_description(temp_dir.path())
.await
.expect("Failed to get description");
assert_eq!(actual, test_message); assert_eq!(actual, test_message);
} }
#[tokio::test] #[tokio::test]
async fn describe_handles_multiline_message() { async fn describe_handles_multiline_message() {
let temp_dir = assert_fs::TempDir::new().unwrap(); let temp_dir = assert_fs::TempDir::new().unwrap();
init_jj_repo(temp_dir.path()).expect("Failed to init jj repo"); init_jj_repo(temp_dir.path())
.await
.expect("Failed to init jj repo");
let test_message = "feat: add feature\n\nThis is a multiline\ndescription"; let test_message = "feat: add feature\n\nThis is a multiline\ndescription";
let executor = JjLib::with_working_dir(temp_dir.path()); let executor = JjLib::with_working_dir(temp_dir.path());
@@ -240,7 +261,9 @@ mod tests {
let result = executor.describe(test_message).await; let result = executor.describe(test_message).await;
assert!(result.is_ok()); assert!(result.is_ok());
let actual = get_commit_description(temp_dir.path()).expect("Failed to get description"); let actual = get_commit_description(temp_dir.path())
.await
.expect("Failed to get description");
assert_eq!(actual, test_message); assert_eq!(actual, test_message);
} }
@@ -258,7 +281,9 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn describe_can_be_called_multiple_times() { async fn describe_can_be_called_multiple_times() {
let temp_dir = assert_fs::TempDir::new().unwrap(); let temp_dir = assert_fs::TempDir::new().unwrap();
init_jj_repo(temp_dir.path()).expect("Failed to init jj repo"); init_jj_repo(temp_dir.path())
.await
.expect("Failed to init jj repo");
let executor = JjLib::with_working_dir(temp_dir.path()); let executor = JjLib::with_working_dir(temp_dir.path());
@@ -266,16 +291,18 @@ mod tests {
.describe("feat: first commit") .describe("feat: first commit")
.await .await
.expect("First describe failed"); .expect("First describe failed");
let desc1 = let desc1 = get_commit_description(temp_dir.path())
get_commit_description(temp_dir.path()).expect("Failed to get first description"); .await
.expect("Failed to get first description");
assert_eq!(desc1, "feat: first commit"); assert_eq!(desc1, "feat: first commit");
executor executor
.describe("feat: updated commit") .describe("feat: updated commit")
.await .await
.expect("Second describe failed"); .expect("Second describe failed");
let desc2 = let desc2 = get_commit_description(temp_dir.path())
get_commit_description(temp_dir.path()).expect("Failed to get second description"); .await
.expect("Failed to get second description");
assert_eq!(desc2, "feat: updated commit"); assert_eq!(desc2, "feat: updated commit");
} }

View File

@@ -18,7 +18,4 @@ pub use crate::{
/// ///
/// Enable with `--features test-utils` (e.g. `cargo test --features test-utils`). /// Enable with `--features test-utils` (e.g. `cargo test --features test-utils`).
#[cfg(feature = "test-utils")] #[cfg(feature = "test-utils")]
pub use crate::{ pub use crate::{jj::mock::MockJjExecutor, prompts::mock::MockPrompts};
jj::mock::MockJjExecutor,
prompts::mock::MockPrompts,
};