huskies: merge 589_story_wizard_auto_detects_project_components_and_configures_scripts_accordingly
This commit is contained in:
@@ -43,6 +43,8 @@ pub(crate) fn step_output_path(
|
||||
.join("STACK.md"),
|
||||
),
|
||||
WizardStep::TestScript => Some(project_root.join("script").join("test")),
|
||||
WizardStep::BuildScript => Some(project_root.join("script").join("build")),
|
||||
WizardStep::LintScript => Some(project_root.join("script").join("lint")),
|
||||
WizardStep::ReleaseScript => Some(project_root.join("script").join("release")),
|
||||
WizardStep::TestCoverage => Some(project_root.join("script").join("test_coverage")),
|
||||
WizardStep::Scaffold => None,
|
||||
@@ -52,7 +54,11 @@ pub(crate) fn step_output_path(
|
||||
pub(crate) fn is_script_step(step: WizardStep) -> bool {
|
||||
matches!(
|
||||
step,
|
||||
WizardStep::TestScript | WizardStep::ReleaseScript | WizardStep::TestCoverage
|
||||
WizardStep::TestScript
|
||||
| WizardStep::BuildScript
|
||||
| WizardStep::LintScript
|
||||
| WizardStep::ReleaseScript
|
||||
| WizardStep::TestCoverage
|
||||
)
|
||||
}
|
||||
|
||||
@@ -256,6 +262,90 @@ pub(crate) fn generation_hint(step: WizardStep, project_root: &Path) -> String {
|
||||
}
|
||||
}
|
||||
}
|
||||
WizardStep::BuildScript => {
|
||||
if bare {
|
||||
"This is a bare project with no existing code. Read the STACK.md generated \
|
||||
in the previous step (or ask the user about their stack if it was skipped) \
|
||||
and generate a `script/build` shell script (#!/usr/bin/env bash, set -euo pipefail) \
|
||||
with appropriate build commands for their chosen language and framework."
|
||||
.to_string()
|
||||
} else {
|
||||
let has_cargo = project_root.join("Cargo.toml").exists();
|
||||
let has_pkg = project_root.join("package.json").exists();
|
||||
let has_pnpm = project_root.join("pnpm-lock.yaml").exists();
|
||||
let has_frontend_subdir =
|
||||
project_root.join("frontend").join("package.json").exists()
|
||||
|| project_root.join("client").join("package.json").exists();
|
||||
let has_go = project_root.join("go.mod").exists();
|
||||
let mut cmds = Vec::new();
|
||||
if has_cargo {
|
||||
cmds.push("cargo build --release");
|
||||
}
|
||||
if has_pkg {
|
||||
cmds.push(if has_pnpm {
|
||||
"pnpm run build"
|
||||
} else {
|
||||
"npm run build"
|
||||
});
|
||||
}
|
||||
if has_frontend_subdir {
|
||||
cmds.push("(cd frontend && npm run build)");
|
||||
}
|
||||
if has_go {
|
||||
cmds.push("go build ./...");
|
||||
}
|
||||
if cmds.is_empty() {
|
||||
"Generate a `script/build` shell script (#!/usr/bin/env bash, set -euo pipefail) that builds the project.".to_string()
|
||||
} else {
|
||||
format!(
|
||||
"Generate a `script/build` shell script (#!/usr/bin/env bash, set -euo pipefail) that runs: {}",
|
||||
cmds.join(", ")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
WizardStep::LintScript => {
|
||||
if bare {
|
||||
"This is a bare project with no existing code. Read the STACK.md generated \
|
||||
in the previous step (or ask the user about their stack if it was skipped) \
|
||||
and generate a `script/lint` shell script (#!/usr/bin/env bash, set -euo pipefail) \
|
||||
with appropriate lint commands for their chosen language and framework."
|
||||
.to_string()
|
||||
} else {
|
||||
let has_cargo = project_root.join("Cargo.toml").exists();
|
||||
let has_pkg = project_root.join("package.json").exists();
|
||||
let has_pnpm = project_root.join("pnpm-lock.yaml").exists();
|
||||
let has_python = project_root.join("pyproject.toml").exists()
|
||||
|| project_root.join("requirements.txt").exists();
|
||||
let has_go = project_root.join("go.mod").exists();
|
||||
let mut cmds = Vec::new();
|
||||
if has_cargo {
|
||||
cmds.push("cargo fmt --all --check");
|
||||
cmds.push("cargo clippy -- -D warnings");
|
||||
}
|
||||
if has_pkg {
|
||||
cmds.push(if has_pnpm {
|
||||
"pnpm run lint"
|
||||
} else {
|
||||
"npm run lint"
|
||||
});
|
||||
}
|
||||
if has_python {
|
||||
cmds.push("flake8 . (or ruff check . if ruff is configured)");
|
||||
}
|
||||
if has_go {
|
||||
cmds.push("go vet ./...");
|
||||
}
|
||||
if cmds.is_empty() {
|
||||
"Generate a `script/lint` shell script (#!/usr/bin/env bash, set -euo pipefail) that runs the project's linters.".to_string()
|
||||
} else {
|
||||
format!(
|
||||
"Generate a `script/lint` shell script (#!/usr/bin/env bash, set -euo pipefail) that runs: {}",
|
||||
cmds.join(", ")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
WizardStep::ReleaseScript => {
|
||||
if bare {
|
||||
"This is a bare project with no existing code. Read the STACK.md generated \
|
||||
@@ -554,8 +644,8 @@ mod tests {
|
||||
fn wizard_complete_returns_done_message() {
|
||||
let dir = TempDir::new().unwrap();
|
||||
let ctx = setup(&dir);
|
||||
// Skip all remaining steps.
|
||||
for _ in 0..5 {
|
||||
// Skip all remaining steps (scaffold is pre-confirmed, so 7 remaining).
|
||||
for _ in 0..7 {
|
||||
tool_wizard_skip(&ctx).unwrap();
|
||||
}
|
||||
let result = tool_wizard_status(&ctx).unwrap();
|
||||
@@ -666,4 +756,61 @@ mod tests {
|
||||
assert!(hint.contains("cargo nextest"));
|
||||
assert!(!hint.contains("bare project"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generation_hint_bare_build_script_references_stack() {
|
||||
let dir = TempDir::new().unwrap();
|
||||
std::fs::create_dir_all(dir.path().join(".huskies")).unwrap();
|
||||
let hint = generation_hint(WizardStep::BuildScript, dir.path());
|
||||
assert!(hint.contains("bare project"));
|
||||
assert!(hint.contains("STACK.md"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generation_hint_bare_lint_script_references_stack() {
|
||||
let dir = TempDir::new().unwrap();
|
||||
std::fs::create_dir_all(dir.path().join(".huskies")).unwrap();
|
||||
let hint = generation_hint(WizardStep::LintScript, dir.path());
|
||||
assert!(hint.contains("bare project"));
|
||||
assert!(hint.contains("STACK.md"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generation_hint_existing_project_build_script_detects_cargo() {
|
||||
let dir = TempDir::new().unwrap();
|
||||
std::fs::write(dir.path().join("Cargo.toml"), "[package]").unwrap();
|
||||
let hint = generation_hint(WizardStep::BuildScript, dir.path());
|
||||
assert!(hint.contains("cargo build --release"));
|
||||
assert!(!hint.contains("bare project"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generation_hint_existing_project_lint_script_detects_cargo() {
|
||||
let dir = TempDir::new().unwrap();
|
||||
std::fs::write(dir.path().join("Cargo.toml"), "[package]").unwrap();
|
||||
let hint = generation_hint(WizardStep::LintScript, dir.path());
|
||||
assert!(hint.contains("cargo fmt --all --check"));
|
||||
assert!(hint.contains("cargo clippy -- -D warnings"));
|
||||
assert!(!hint.contains("bare project"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn step_output_path_build_script_returns_script_build() {
|
||||
let dir = TempDir::new().unwrap();
|
||||
let path = step_output_path(dir.path(), WizardStep::BuildScript).unwrap();
|
||||
assert!(path.ends_with("script/build"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn step_output_path_lint_script_returns_script_lint() {
|
||||
let dir = TempDir::new().unwrap();
|
||||
let path = step_output_path(dir.path(), WizardStep::LintScript).unwrap();
|
||||
assert!(path.ends_with("script/lint"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_script_step_includes_build_and_lint() {
|
||||
assert!(is_script_step(WizardStep::BuildScript));
|
||||
assert!(is_script_step(WizardStep::LintScript));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user