mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-08-28 05:27:41 +00:00
226 lines
5.9 KiB
Rust
226 lines
5.9 KiB
Rust
use std::path::Path;
|
|
use std::process::Command;
|
|
|
|
use super::{fabro_dev, output_text, write_file};
|
|
|
|
#[expect(
|
|
clippy::disallowed_methods,
|
|
reason = "integration tests intentionally shell out to git in temporary fixture repositories"
|
|
)]
|
|
fn git(root: &Path, args: &[&str]) {
|
|
let output = Command::new("git")
|
|
.args(args)
|
|
.current_dir(root)
|
|
.output()
|
|
.expect("git should run");
|
|
assert!(
|
|
output.status.success(),
|
|
"git {:?} failed\nstdout:\n{}\nstderr:\n{}",
|
|
args,
|
|
output_text(&output.stdout),
|
|
output_text(&output.stderr)
|
|
);
|
|
}
|
|
|
|
fn release_fixture() -> tempfile::TempDir {
|
|
let fixture = tempfile::tempdir().expect("creating fixture");
|
|
write_file(
|
|
fixture.path(),
|
|
"Cargo.toml",
|
|
r#"[workspace]
|
|
members = []
|
|
|
|
[workspace.package]
|
|
version = "0.1.0"
|
|
"#,
|
|
);
|
|
git(fixture.path(), &["init"]);
|
|
git(fixture.path(), &["config", "user.name", "Release Test"]);
|
|
git(fixture.path(), &[
|
|
"config",
|
|
"user.email",
|
|
"release-test@example.com",
|
|
]);
|
|
git(fixture.path(), &["add", "Cargo.toml"]);
|
|
git(fixture.path(), &["commit", "-m", "initial"]);
|
|
fixture
|
|
}
|
|
|
|
#[test]
|
|
fn help_lists_release_flags() {
|
|
let output = fabro_dev()
|
|
.args(["release", "--help"])
|
|
.assert()
|
|
.success()
|
|
.get_output()
|
|
.clone();
|
|
let stdout = output_text(&output.stdout);
|
|
|
|
for flag in ["--dry-run", "--skip-tests", "--release-date", "--nightly"] {
|
|
assert!(
|
|
stdout.contains(flag),
|
|
"release help should list {flag}:\n{stdout}"
|
|
);
|
|
}
|
|
|
|
assert!(
|
|
!stdout.contains("[PRERELEASE_LABEL]"),
|
|
"release help should not list a prerelease positional:\n{stdout}"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn dry_run_computes_stable_version_from_date() {
|
|
let fixture = release_fixture();
|
|
|
|
let output = fabro_dev()
|
|
.args([
|
|
"release",
|
|
"--root",
|
|
fixture
|
|
.path()
|
|
.to_str()
|
|
.expect("fixture path should be utf-8"),
|
|
"--release-date",
|
|
"2026-01-01",
|
|
"--dry-run",
|
|
])
|
|
.assert()
|
|
.success()
|
|
.get_output()
|
|
.clone();
|
|
let stdout = output_text(&output.stdout);
|
|
|
|
assert!(
|
|
stdout.contains("Releasing 0.100.0 (tag v0.100.0)"),
|
|
"dry-run should compute base version from date:\n{stdout}"
|
|
);
|
|
assert!(
|
|
stdout.contains("cargo --locked dev spa refresh"),
|
|
"dry-run should print one SPA refresh command:\n{stdout}"
|
|
);
|
|
assert!(
|
|
!stdout.contains("git diff --exit-code -- lib/apps/fabro-spa/assets"),
|
|
"dry-run should not print a separate SPA asset diff command:\n{stdout}"
|
|
);
|
|
assert!(
|
|
stdout.contains("git tag -a v0.100.0 -m v0.100.0"),
|
|
"dry-run should print release tag command:\n{stdout}"
|
|
);
|
|
assert!(
|
|
stdout.contains(
|
|
"unset GH_TOKEN GITHUB_TOKEN && SEGMENT_WRITE_KEY=fake-for-local-smoke cargo nextest run --locked"
|
|
),
|
|
"dry-run should show release tests without inherited GitHub tokens:\n{stdout}"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn dry_run_increments_existing_prerelease_number() {
|
|
let fixture = release_fixture();
|
|
git(fixture.path(), &["tag", "v0.100.0-nightly.0"]);
|
|
|
|
let output = fabro_dev()
|
|
.args([
|
|
"release",
|
|
"--root",
|
|
fixture
|
|
.path()
|
|
.to_str()
|
|
.expect("fixture path should be utf-8"),
|
|
"--release-date",
|
|
"2026-01-01",
|
|
"--dry-run",
|
|
"--nightly",
|
|
])
|
|
.assert()
|
|
.success()
|
|
.get_output()
|
|
.clone();
|
|
let stdout = output_text(&output.stdout);
|
|
|
|
assert!(
|
|
stdout.contains("Releasing 0.100.0-nightly.1 (tag v0.100.0-nightly.1)"),
|
|
"dry-run should increment existing nightly tag:\n{stdout}"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn positional_nightly_fails_with_clap_error() {
|
|
let output = fabro_dev()
|
|
.args(["release", "nightly"])
|
|
.assert()
|
|
.failure()
|
|
.code(2)
|
|
.get_output()
|
|
.clone();
|
|
let stderr = output_text(&output.stderr);
|
|
|
|
assert!(
|
|
stderr.contains("unexpected argument 'nightly'"),
|
|
"nightly positional should be rejected by clap:\n{stderr}"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn dry_run_reports_skip_tests_without_running_release_tests() {
|
|
let fixture = release_fixture();
|
|
|
|
let output = fabro_dev()
|
|
.args([
|
|
"release",
|
|
"--root",
|
|
fixture
|
|
.path()
|
|
.to_str()
|
|
.expect("fixture path should be utf-8"),
|
|
"--release-date",
|
|
"2026-01-01",
|
|
"--dry-run",
|
|
"--skip-tests",
|
|
])
|
|
.assert()
|
|
.success()
|
|
.get_output()
|
|
.clone();
|
|
let stdout = output_text(&output.stdout);
|
|
|
|
assert!(
|
|
stdout.contains("--skip-tests set, would skip release-mode test smoke"),
|
|
"dry-run should report skip-tests behavior:\n{stdout}"
|
|
);
|
|
assert!(
|
|
!stdout.contains("cargo nextest run"),
|
|
"dry-run with skip-tests should not print release test command:\n{stdout}"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn dirty_worktree_errors_unless_dry_run() {
|
|
let fixture = release_fixture();
|
|
write_file(fixture.path(), "dirty.txt", "dirty\n");
|
|
|
|
let output = fabro_dev()
|
|
.args([
|
|
"release",
|
|
"--root",
|
|
fixture
|
|
.path()
|
|
.to_str()
|
|
.expect("fixture path should be utf-8"),
|
|
"--release-date",
|
|
"2026-01-01",
|
|
"--skip-tests",
|
|
])
|
|
.assert()
|
|
.failure()
|
|
.code(1)
|
|
.get_output()
|
|
.clone();
|
|
let stderr = output_text(&output.stderr);
|
|
|
|
assert!(
|
|
stderr.contains("working tree is dirty"),
|
|
"dirty non-dry-run release should fail before mutating:\n{stderr}"
|
|
);
|
|
}
|