chore(dev): isolate worktree builds and wire nextest into dev-test

scripts/dev-test.sh only mapped an area onto cargo test -p; a new
worktree still compiled into a private cold ./target. Add
scripts/dev-cache.sh and scripts/dev-cargo.sh so the measured isolated
build-dir topology is actually applied.

New worktrees get CARGO_BUILD_BUILD_DIR under
${CODEWHALE_CACHE_ROOT:-${XDG_CACHE_HOME:-$HOME/.cache}/codewhale}
with Cargo's {workspace-path-hash} (passed as --config so the
template expands). sccache wraps rustc only when incremental is
already off; a missing binary is a printed fallback, not an error.
Cargo older than 1.91 falls back to a per-workspace CARGO_TARGET_DIR.
Already-set CARGO_TARGET_DIR / CARGO_BUILD_BUILD_DIR / RUSTC_WRAPPER
are left alone. Defaults contain no machine-local path.

dev-test.sh now routes every workspace crate, prefers cargo-nextest
when installed (CODEWHALE_DEV_NEXTEST=0 forces libtest), and exports
RUST_MIN_STACK=16MiB when unset. nextest retries stay 0. Hermetic
checks: scripts/dev-cache.test.sh (22) and scripts/dev-test.test.sh
(27), passing under both /bin/sh and dash.
This commit is contained in:
CodeWhale Bot
2026-08-15 20:57:11 -07:00
parent cca48046f7
commit 178a2f5a01
6 changed files with 1070 additions and 33 deletions
+2
View File
@@ -19,6 +19,8 @@ slow-timeout = { period = "30s" }
retries = 0
fail-fast = false
final-status-level = "slow"
# RUST_MIN_STACK is not a nextest.toml key. CI and scripts/dev-test.sh
# export 16 MiB so local nextest matches the product thread stack.
[test-groups]
pty = { max-threads = 1 }
+437
View File
@@ -0,0 +1,437 @@
#!/bin/sh
# Portable opt-in Cargo cache topology for Codewhale worktrees.
#
# Isolated per-workspace intermediates (Cargo build-dir + {workspace-path-hash})
# plus optional shared sccache. Never hard-codes a machine path. Does not
# change product behavior. This file is safe to source from other /bin/sh
# helpers; the CLI path is the only one that calls `set -eu` and `exit`.
#
# Usage:
# . scripts/dev-cache.sh && codewhale_dev_cache_apply
# scripts/dev-cache.sh --status
# scripts/dev-cache.sh --self-check
# scripts/dev-cache.sh --print-exports
# scripts/dev-cache.sh --help
#
# Environment:
# CODEWHALE_CACHE_ROOT cache root (default:
# ${XDG_CACHE_HOME:-$HOME/.cache}/codewhale)
# CODEWHALE_DEV_CACHE auto|1|force|0 (default auto)
# auto = isolated build-dir only when ./target
# is absent (new worktree)
# 1/force = always isolated (still respects an
# already-set CARGO_TARGET_DIR /
# CARGO_BUILD_BUILD_DIR)
# 0 = do nothing
# CODEWHALE_SCCACHE auto|1|0 (default auto)
# auto = wrap rustc only when incremental is
# already off and sccache is on PATH
# 1 = request CARGO_INCREMENTAL=0 (unless
# the caller already set it to on) and
# wrap if sccache exists
# 0 = never wrap
# CODEWHALE_DEV_CACHE_QUIET 1 to suppress the one-line status
# CODEWHALE_DEV_CACHE_REPO_ROOT
# workspace root used for ./target detection
# (default: $PWD)
# CODEWHALE_RUSTC_COMMIT override the rustc commit used to namespace
# SCCACHE_DIR (tests / offline hosts)
#
# sccache cannot cache incremental units. This helper never enables the
# wrapper while CARGO_INCREMENTAL is on, and it never turns incremental off
# unless CODEWHALE_SCCACHE=1. Everyday edits stay on cargo's incremental
# default. New-worktree / CI-like rebuilds that already set
# CARGO_INCREMENTAL=0 get the measured shared-compiler-output path.
codewhale_dev_cache_truthy() {
case ${1:-} in
1|true|yes|on|force) return 0 ;;
*) return 1 ;;
esac
}
codewhale_dev_cache_falsey() {
case ${1:-} in
0|false|no|off|never|disabled) return 0 ;;
*) return 1 ;;
esac
}
codewhale_dev_cache_root() {
if [ -n "${CODEWHALE_CACHE_ROOT:-}" ]; then
printf '%s\n' "$CODEWHALE_CACHE_ROOT"
return
fi
if [ -n "${XDG_CACHE_HOME:-}" ]; then
printf '%s\n' "$XDG_CACHE_HOME/codewhale"
return
fi
if [ -n "${HOME:-}" ]; then
printf '%s\n' "$HOME/.cache/codewhale"
return
fi
printf '%s\n' "${TMPDIR:-/tmp}/codewhale-cache"
}
codewhale_dev_cache_repo_root() {
if [ -n "${CODEWHALE_DEV_CACHE_REPO_ROOT:-}" ]; then
printf '%s\n' "$CODEWHALE_DEV_CACHE_REPO_ROOT"
return
fi
pwd
}
codewhale_dev_cache_rustc_commit() {
if [ -n "${CODEWHALE_RUSTC_COMMIT:-}" ]; then
printf '%s\n' "$CODEWHALE_RUSTC_COMMIT"
return
fi
# rustc -vV is cheap and does not start a compile.
_cw_out=$(rustc -vV 2>/dev/null || true)
_cw_commit=$(printf '%s\n' "$_cw_out" | awk '/^commit-hash:/{print $2; exit}')
if [ -n "$_cw_commit" ]; then
printf '%s\n' "$_cw_commit"
else
printf '%s\n' "unknown"
fi
}
codewhale_dev_cache_cargo_version_mm() {
# cargo 1.97.0 -> 1097. Empty if cargo is missing or unparsable.
cargo --version 2>/dev/null | awk '{
split($2, a, ".")
if (a[1] ~ /^[0-9]+$/ && a[2] ~ /^[0-9]+$/)
printf "%d\n", a[1]*1000+a[2]
}'
}
# Stable 16-hex-char fingerprint of a path. Used only for the pre-1.91
# CARGO_TARGET_DIR fallback; Cargo 1.91+ expands {workspace-path-hash}.
codewhale_dev_cache_path_fingerprint() {
if command -v sha256sum >/dev/null 2>&1; then
printf '%s' "$1" | sha256sum | awk '{print substr($1,1,16)}'
elif command -v shasum >/dev/null 2>&1; then
printf '%s' "$1" | shasum -a 256 | awk '{print substr($1,1,16)}'
elif command -v openssl >/dev/null 2>&1; then
printf '%s' "$1" | openssl dgst -sha256 | awk '{print substr($NF,1,16)}'
else
printf '%s' "$1" | cksum | awk '{printf "%s%08s\n", $1, $2}' | tr ' ' '0'
fi
}
codewhale_dev_cache_has_local_target() {
_cw_repo=$(codewhale_dev_cache_repo_root)
[ -d "$_cw_repo/target" ]
}
codewhale_dev_cache_incremental_off() {
case ${CARGO_INCREMENTAL:-} in
0|false|no|off) return 0 ;;
*) return 1 ;;
esac
}
codewhale_dev_cache_incremental_on() {
case ${CARGO_INCREMENTAL:-} in
1|true|yes|on) return 0 ;;
*) return 1 ;;
esac
}
codewhale_dev_cache_sccache_bin() {
command -v sccache 2>/dev/null || true
}
codewhale_dev_cache_log() {
if [ "${CODEWHALE_DEV_CACHE_QUIET:-}" = 1 ]; then
return 0
fi
printf 'dev-cache: %s\n' "$*" >&2
}
# Apply the topology to the current shell. Idempotent. Never overrides an
# already-set CARGO_TARGET_DIR, CARGO_BUILD_BUILD_DIR, RUSTC_WRAPPER, or
# SCCACHE_DIR.
codewhale_dev_cache_apply() {
CODEWHALE_DEV_CACHE_MODE=${CODEWHALE_DEV_CACHE_MODE:-}
# Re-entry after a previous apply in this shell: keep the first decision
# unless the caller unset the mode (tests do that between cases).
if [ -n "${CODEWHALE_DEV_CACHE_APPLIED:-}" ] && [ -n "${CODEWHALE_DEV_CACHE_MODE:-}" ]; then
return 0
fi
_cw_want=${CODEWHALE_DEV_CACHE:-auto}
_cw_root=$(codewhale_dev_cache_root)
_cw_sccache_want=${CODEWHALE_SCCACHE:-auto}
_cw_commit=$(codewhale_dev_cache_rustc_commit)
CODEWHALE_DEV_CACHE_SCCACHE_DIR=${SCCACHE_DIR:-${_cw_root}/sccache/${_cw_commit}}
CODEWHALE_DEV_CACHE_BUILD_DIR=${_cw_root}/build/'{workspace-path-hash}'
CODEWHALE_DEV_CACHE_LEGACY_TARGET_DIR=${_cw_root}/target/$(codewhale_dev_cache_path_fingerprint "$(codewhale_dev_cache_repo_root)")
if codewhale_dev_cache_falsey "$_cw_want"; then
CODEWHALE_DEV_CACHE_MODE=disabled
CODEWHALE_DEV_CACHE_SCCACHE=disabled
CODEWHALE_DEV_CACHE_APPLIED=1
export CODEWHALE_DEV_CACHE_MODE CODEWHALE_DEV_CACHE_SCCACHE
codewhale_dev_cache_log "disabled (CODEWHALE_DEV_CACHE=${_cw_want})"
return 0
fi
if [ -n "${CARGO_TARGET_DIR:-}" ]; then
CODEWHALE_DEV_CACHE_MODE=inherited-target-dir
elif [ -n "${CARGO_BUILD_BUILD_DIR:-}" ]; then
CODEWHALE_DEV_CACHE_MODE=inherited-build-dir
elif codewhale_dev_cache_truthy "$_cw_want"; then
CODEWHALE_DEV_CACHE_MODE=force-isolated
elif codewhale_dev_cache_has_local_target; then
CODEWHALE_DEV_CACHE_MODE=existing-target
else
CODEWHALE_DEV_CACHE_MODE=isolated-build-dir
fi
case $CODEWHALE_DEV_CACHE_MODE in
force-isolated|isolated-build-dir)
_cw_mm=$(codewhale_dev_cache_cargo_version_mm)
if [ -n "$_cw_mm" ] && [ "$_cw_mm" -lt 1091 ]; then
# Cargo 1.91 introduced build.build-dir. Older cargo only isolates
# via CARGO_TARGET_DIR; keep that fallback per-workspace.
if [ -z "${CARGO_TARGET_DIR:-}" ]; then
CARGO_TARGET_DIR=$CODEWHALE_DEV_CACHE_LEGACY_TARGET_DIR
export CARGO_TARGET_DIR
fi
CODEWHALE_DEV_CACHE_MODE=${CODEWHALE_DEV_CACHE_MODE}-legacy-target-dir
else
CARGO_BUILD_BUILD_DIR=$CODEWHALE_DEV_CACHE_BUILD_DIR
export CARGO_BUILD_BUILD_DIR
mkdir -p "$_cw_root/build" 2>/dev/null || true
fi
;;
esac
# sccache: never wrap incremental rustc. Missing binary is a fallback,
# not an error.
if codewhale_dev_cache_falsey "$_cw_sccache_want"; then
CODEWHALE_DEV_CACHE_SCCACHE=disabled
elif [ -n "${RUSTC_WRAPPER:-}" ]; then
case $RUSTC_WRAPPER in
*sccache*) CODEWHALE_DEV_CACHE_SCCACHE=external-sccache ;;
*) CODEWHALE_DEV_CACHE_SCCACHE=external-wrapper ;;
esac
else
if codewhale_dev_cache_truthy "$_cw_sccache_want" && ! codewhale_dev_cache_incremental_on; then
# Request the measured new-worktree / CI-like topology.
if [ -z "${CARGO_INCREMENTAL:-}" ]; then
CARGO_INCREMENTAL=0
export CARGO_INCREMENTAL
fi
fi
if ! codewhale_dev_cache_incremental_off; then
CODEWHALE_DEV_CACHE_SCCACHE=skipped-incremental
else
_cw_bin=$(codewhale_dev_cache_sccache_bin)
if [ -z "$_cw_bin" ]; then
CODEWHALE_DEV_CACHE_SCCACHE=not-found
else
RUSTC_WRAPPER=$_cw_bin
export RUSTC_WRAPPER
if [ -z "${SCCACHE_DIR:-}" ]; then
SCCACHE_DIR=$CODEWHALE_DEV_CACHE_SCCACHE_DIR
export SCCACHE_DIR
fi
mkdir -p "$SCCACHE_DIR" 2>/dev/null || true
CODEWHALE_DEV_CACHE_SCCACHE=enabled
fi
fi
fi
CODEWHALE_DEV_CACHE_APPLIED=1
export CODEWHALE_DEV_CACHE_MODE CODEWHALE_DEV_CACHE_SCCACHE
export CODEWHALE_DEV_CACHE_SCCACHE_DIR
_cw_line="mode=${CODEWHALE_DEV_CACHE_MODE} sccache=${CODEWHALE_DEV_CACHE_SCCACHE}"
case $CODEWHALE_DEV_CACHE_MODE in
isolated-build-dir*|force-isolated*)
_cw_line="${_cw_line} build-dir=${CARGO_BUILD_BUILD_DIR:-${CARGO_TARGET_DIR:-unset}}"
;;
inherited-target-dir)
_cw_line="${_cw_line} CARGO_TARGET_DIR=${CARGO_TARGET_DIR}"
;;
inherited-build-dir)
_cw_line="${_cw_line} CARGO_BUILD_BUILD_DIR=${CARGO_BUILD_BUILD_DIR}"
;;
existing-target)
_cw_line="${_cw_line} using ./target (set CODEWHALE_DEV_CACHE=1 to isolate)"
;;
esac
if [ "${CODEWHALE_DEV_CACHE_SCCACHE}" = enabled ]; then
_cw_line="${_cw_line} SCCACHE_DIR=${SCCACHE_DIR} rustc=${_cw_commit}"
fi
codewhale_dev_cache_log "$_cw_line"
}
codewhale_dev_cache_status() {
_cw_tmpl=${CODEWHALE_DEV_CACHE_BUILD_DIR:-}
if [ -z "$_cw_tmpl" ]; then
_cw_tmpl=$(codewhale_dev_cache_root)/build/'{workspace-path-hash}'
fi
printf '%s\n' \
"cache_root=$(codewhale_dev_cache_root)" \
"repo_root=$(codewhale_dev_cache_repo_root)" \
"mode=${CODEWHALE_DEV_CACHE_MODE:-unset}" \
"sccache=${CODEWHALE_DEV_CACHE_SCCACHE:-unset}" \
"build_dir_template=${_cw_tmpl}" \
"CARGO_BUILD_BUILD_DIR=${CARGO_BUILD_BUILD_DIR:-<unset>}" \
"CARGO_TARGET_DIR=${CARGO_TARGET_DIR:-<unset>}" \
"CARGO_INCREMENTAL=${CARGO_INCREMENTAL:-<unset>}" \
"RUSTC_WRAPPER=${RUSTC_WRAPPER:-<unset>}" \
"SCCACHE_DIR=${SCCACHE_DIR:-<unset>}" \
"rustc_commit=$(codewhale_dev_cache_rustc_commit)" \
"sccache_bin=$(codewhale_dev_cache_sccache_bin)"
}
# Extra cargo CLI flags that force template expansion of build-dir.
# CARGO_BUILD_BUILD_DIR is still exported for nested tools; --config is
# what Cargo documents as supporting {workspace-path-hash}.
codewhale_dev_cache_exec_cargo() {
case ${CODEWHALE_DEV_CACHE_MODE:-} in
isolated-build-dir|force-isolated)
if [ -n "${CARGO_BUILD_BUILD_DIR:-}" ]; then
exec cargo --config "build.build-dir = \"${CARGO_BUILD_BUILD_DIR}\"" "$@"
fi
;;
esac
exec cargo "$@"
}
codewhale_dev_cache_print_exports() {
[ -n "${CARGO_BUILD_BUILD_DIR:-}" ] && printf 'export CARGO_BUILD_BUILD_DIR=%s\n' "$CARGO_BUILD_BUILD_DIR"
[ -n "${CARGO_TARGET_DIR:-}" ] && printf 'export CARGO_TARGET_DIR=%s\n' "$CARGO_TARGET_DIR"
[ -n "${CARGO_INCREMENTAL:-}" ] && printf 'export CARGO_INCREMENTAL=%s\n' "$CARGO_INCREMENTAL"
[ -n "${RUSTC_WRAPPER:-}" ] && printf 'export RUSTC_WRAPPER=%s\n' "$RUSTC_WRAPPER"
[ -n "${SCCACHE_DIR:-}" ] && printf 'export SCCACHE_DIR=%s\n' "$SCCACHE_DIR"
[ -n "${CODEWHALE_DEV_CACHE_MODE:-}" ] && printf 'export CODEWHALE_DEV_CACHE_MODE=%s\n' "$CODEWHALE_DEV_CACHE_MODE"
[ -n "${CODEWHALE_DEV_CACHE_SCCACHE:-}" ] && printf 'export CODEWHALE_DEV_CACHE_SCCACHE=%s\n' "$CODEWHALE_DEV_CACHE_SCCACHE"
}
codewhale_dev_cache_self_check() {
_cw_fail=0
_cw_root=$(codewhale_dev_cache_root)
_cw_home=${HOME:-}
_cw_xdg=${XDG_CACHE_HOME:-}
if [ -z "${CODEWHALE_CACHE_ROOT:-}" ]; then
if [ -n "$_cw_xdg" ]; then
case $_cw_root in
"$_cw_xdg"/codewhale) ;;
*)
printf 'self-check: expected XDG default %s/codewhale, got %s\n' "$_cw_xdg" "$_cw_root" >&2
_cw_fail=1
;;
esac
elif [ -n "$_cw_home" ]; then
case $_cw_root in
"$_cw_home"/.cache/codewhale) ;;
*)
printf 'self-check: expected HOME default %s/.cache/codewhale, got %s\n' "$_cw_home" "$_cw_root" >&2
_cw_fail=1
;;
esac
fi
fi
case ${CARGO_BUILD_BUILD_DIR:-} in
*'{workspace-path-hash}'*)
;;
'')
case ${CODEWHALE_DEV_CACHE_MODE:-} in
isolated-build-dir|force-isolated)
printf 'self-check: isolated mode did not set CARGO_BUILD_BUILD_DIR\n' >&2
_cw_fail=1
;;
esac
;;
*)
case ${CODEWHALE_DEV_CACHE_MODE:-} in
isolated-build-dir|force-isolated)
printf 'self-check: isolated build-dir lacks {workspace-path-hash}: %s\n' "$CARGO_BUILD_BUILD_DIR" >&2
_cw_fail=1
;;
esac
;;
esac
if [ "${CODEWHALE_DEV_CACHE_SCCACHE:-}" = enabled ]; then
if ! codewhale_dev_cache_incremental_off; then
printf 'self-check: sccache enabled while incremental is not off\n' >&2
_cw_fail=1
fi
case ${RUSTC_WRAPPER:-} in
*sccache*) ;;
*)
printf 'self-check: sccache enabled but RUSTC_WRAPPER=%s\n' "${RUSTC_WRAPPER:-<unset>}" >&2
_cw_fail=1
;;
esac
fi
if [ "${CODEWHALE_DEV_CACHE_SCCACHE:-}" = not-found ]; then
if [ -n "${RUSTC_WRAPPER:-}" ]; then
printf 'self-check: missing sccache must not set RUSTC_WRAPPER (%s)\n' "$RUSTC_WRAPPER" >&2
_cw_fail=1
fi
fi
if [ "$_cw_fail" -eq 0 ]; then
printf 'dev-cache: self-check ok\n'
return 0
fi
printf 'dev-cache: self-check FAILED\n' >&2
return 1
}
codewhale_dev_cache_usage() {
cat <<'EOF'
usage: scripts/dev-cache.sh --status|--self-check|--print-exports|--help
Portable opt-in Cargo cache topology. Source this file and call
codewhale_dev_cache_apply from scripts/dev-test.sh / scripts/dev-cargo.sh.
--status apply (if needed) and print key=value status
--self-check apply and check portable defaults / sccache fallback
--print-exports apply and print export statements for eval
--help this message
Environment overrides are documented at the top of this file. Defaults
never contain a machine-specific absolute path.
EOF
}
# CLI only when this file is the executed program, not when sourced.
case ${0##*/} in
dev-cache.sh)
set -eu
_cw_cmd=${1:---status}
case $_cw_cmd in
--status|-s)
codewhale_dev_cache_apply
codewhale_dev_cache_status
;;
--self-check)
codewhale_dev_cache_apply
codewhale_dev_cache_status
codewhale_dev_cache_self_check
;;
--print-exports)
codewhale_dev_cache_apply
codewhale_dev_cache_print_exports
;;
--help|-h)
codewhale_dev_cache_usage
;;
*)
codewhale_dev_cache_usage >&2
exit 2
;;
esac
;;
esac
+294
View File
@@ -0,0 +1,294 @@
#!/bin/sh
# Hermetic tests for scripts/dev-cache.sh. No cargo compile, no cache
# deletion. Exercises portable defaults, overrides, missing-sccache
# fallback, incremental gating, and new-vs-existing worktree policy.
set -eu
repo_root=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd)
DEV_CACHE=$repo_root/scripts/dev-cache.sh
DEV_CARGO=$repo_root/scripts/dev-cargo.sh
fail=0
pass=0
ok() {
pass=$((pass + 1))
printf 'ok - %s\n' "$1"
}
bad() {
fail=$((fail + 1))
printf 'FAIL - %s\n' "$1"
if [ -n "${2:-}" ]; then
printf '%s\n' "$2" | sed 's/^/ /'
fi
}
work=$(mktemp -d "${TMPDIR:-/tmp}/codewhale-dev-cache.XXXXXX")
cleanup() { rm -rf "$work"; }
trap cleanup EXIT INT HUP TERM
HOME_DIR=$work/home
mkdir -p "$HOME_DIR"
FAKEBIN=$work/bin
mkdir -p "$FAKEBIN"
NEW_WT=$work/new-wt
OLD_WT=$work/old-wt
mkdir -p "$NEW_WT" "$OLD_WT/target"
# cargo/rustc/sccache are injected per case. Keep the base PATH hermetic.
BASE_PATH=$FAKEBIN:/usr/bin:/bin
run_apply() {
env -i \
PATH="$BASE_PATH" \
HOME="$HOME_DIR" \
CODEWHALE_DEV_CACHE_QUIET=1 \
DEV_CACHE="$DEV_CACHE" \
"$@" \
/bin/sh -c '
set -eu
. "$DEV_CACHE"
codewhale_dev_cache_apply
codewhale_dev_cache_status
' # shellcheck disable=SC2016 -- $DEV_CACHE expands in the child.
}
contains() {
printf '%s' "$1" | grep -qF -- "$2"
}
# 1. Portable default root is $HOME/.cache/codewhale, never a desk path.
out=$(run_apply CODEWHALE_DEV_CACHE=0 CODEWHALE_DEV_CACHE_REPO_ROOT="$NEW_WT")
if contains "$out" "cache_root=$HOME_DIR/.cache/codewhale"; then
ok "default cache root is HOME/.cache/codewhale"
else
bad "default cache root is HOME/.cache/codewhale" "$out"
fi
if printf '%s\n' "$out" | grep -v '^repo_root=' | grep -qF /Volumes/VIXinSSD; then
bad "default paths must not mention /Volumes/VIXinSSD" "$out"
else
ok "default paths do not mention /Volumes/VIXinSSD"
fi
if grep -E '/Users/hunterbown|/Volumes/VIXinSSD' "$DEV_CACHE" "$DEV_CARGO" >/dev/null; then
bad "helper source must not hard-code a desk path"
else
ok "helper source has no desk-local absolute paths"
fi
# 2. XDG_CACHE_HOME and CODEWHALE_CACHE_ROOT win in that documented order.
out=$(run_apply CODEWHALE_DEV_CACHE=0 XDG_CACHE_HOME="$work/xdg")
if contains "$out" "cache_root=$work/xdg/codewhale"; then
ok "XDG_CACHE_HOME/codewhale is the default when set"
else
bad "XDG_CACHE_HOME/codewhale is the default when set" "$out"
fi
out=$(run_apply CODEWHALE_DEV_CACHE=0 \
XDG_CACHE_HOME="$work/xdg" \
CODEWHALE_CACHE_ROOT="$work/explicit-root")
if contains "$out" "cache_root=$work/explicit-root"; then
ok "CODEWHALE_CACHE_ROOT overrides XDG and HOME"
else
bad "CODEWHALE_CACHE_ROOT overrides XDG and HOME" "$out"
fi
# 3. Disabled mode leaves Cargo/sccache vars alone.
out=$(run_apply CODEWHALE_DEV_CACHE=0)
if contains "$out" "mode=disabled" \
&& contains "$out" "CARGO_BUILD_BUILD_DIR=<unset>" \
&& contains "$out" "RUSTC_WRAPPER=<unset>"; then
ok "CODEWHALE_DEV_CACHE=0 does not set cargo or sccache vars"
else
bad "CODEWHALE_DEV_CACHE=0 does not set cargo or sccache vars" "$out"
fi
# 4. New worktree (no ./target) gets isolated build-dir with the cargo template.
out=$(run_apply \
CODEWHALE_DEV_CACHE_REPO_ROOT="$NEW_WT" \
CODEWHALE_CACHE_ROOT="$work/cache")
if contains "$out" "mode=isolated-build-dir" \
&& contains "$out" "CARGO_BUILD_BUILD_DIR=$work/cache/build/{workspace-path-hash}"; then
ok "new worktree uses isolated build-dir template"
else
bad "new worktree uses isolated build-dir template" "$out"
fi
if contains "$out" "CARGO_INCREMENTAL=<unset>"; then
ok "isolated default does not turn incremental off"
else
bad "isolated default does not turn incremental off" "$out"
fi
if contains "$out" "sccache=skipped-incremental"; then
ok "sccache stays off while incremental is on"
else
bad "sccache stays off while incremental is on" "$out"
fi
# 5. Existing ./target is left alone under auto.
out=$(run_apply \
CODEWHALE_DEV_CACHE_REPO_ROOT="$OLD_WT" \
CODEWHALE_CACHE_ROOT="$work/cache")
if contains "$out" "mode=existing-target" \
&& contains "$out" "CARGO_BUILD_BUILD_DIR=<unset>"; then
ok "existing ./target is not moved under auto"
else
bad "existing ./target is not moved under auto" "$out"
fi
# 6. CODEWHALE_DEV_CACHE=1 isolates even when ./target exists.
out=$(run_apply \
CODEWHALE_DEV_CACHE=1 \
CODEWHALE_DEV_CACHE_REPO_ROOT="$OLD_WT" \
CODEWHALE_CACHE_ROOT="$work/cache")
if contains "$out" "mode=force-isolated" \
&& contains "$out" "CARGO_BUILD_BUILD_DIR=$work/cache/build/{workspace-path-hash}"; then
ok "CODEWHALE_DEV_CACHE=1 isolates an existing worktree"
else
bad "CODEWHALE_DEV_CACHE=1 isolates an existing worktree" "$out"
fi
# 7. Already-set CARGO_TARGET_DIR / CARGO_BUILD_BUILD_DIR are respected.
out=$(run_apply \
CODEWHALE_DEV_CACHE=1 \
CARGO_TARGET_DIR="$work/user-target" \
CODEWHALE_DEV_CACHE_REPO_ROOT="$NEW_WT")
if contains "$out" "mode=inherited-target-dir" \
&& contains "$out" "CARGO_TARGET_DIR=$work/user-target" \
&& contains "$out" "CARGO_BUILD_BUILD_DIR=<unset>"; then
ok "existing CARGO_TARGET_DIR is not overwritten"
else
bad "existing CARGO_TARGET_DIR is not overwritten" "$out"
fi
out=$(run_apply \
CARGO_BUILD_BUILD_DIR="$work/user-build" \
CODEWHALE_DEV_CACHE_REPO_ROOT="$NEW_WT")
if contains "$out" "mode=inherited-build-dir" \
&& contains "$out" "CARGO_BUILD_BUILD_DIR=$work/user-build"; then
ok "existing CARGO_BUILD_BUILD_DIR is not overwritten"
else
bad "existing CARGO_BUILD_BUILD_DIR is not overwritten" "$out"
fi
# 8. Missing sccache is a fallback, not a failure, even when requested.
out=$(run_apply \
CODEWHALE_SCCACHE=1 \
CODEWHALE_DEV_CACHE_REPO_ROOT="$NEW_WT" \
CODEWHALE_CACHE_ROOT="$work/cache")
if contains "$out" "sccache=not-found" \
&& contains "$out" "RUSTC_WRAPPER=<unset>" \
&& contains "$out" "CARGO_INCREMENTAL=0"; then
ok "missing sccache falls back without setting RUSTC_WRAPPER"
else
bad "missing sccache falls back without setting RUSTC_WRAPPER" "$out"
fi
# 9. sccache wraps only when incremental is off and the binary exists.
printf '%s\n' '#!/bin/sh' 'exit 0' >"$FAKEBIN/sccache"
chmod +x "$FAKEBIN/sccache"
out=$(run_apply \
CARGO_INCREMENTAL=0 \
CODEWHALE_DEV_CACHE_REPO_ROOT="$NEW_WT" \
CODEWHALE_CACHE_ROOT="$work/cache" \
CODEWHALE_RUSTC_COMMIT=abc123deadbeef)
if contains "$out" "sccache=enabled" \
&& contains "$out" "RUSTC_WRAPPER=$FAKEBIN/sccache" \
&& contains "$out" "SCCACHE_DIR=$work/cache/sccache/abc123deadbeef"; then
ok "sccache wraps rustc when incremental is off"
else
bad "sccache wraps rustc when incremental is off" "$out"
fi
out=$(run_apply \
CARGO_INCREMENTAL=1 \
CODEWHALE_SCCACHE=1 \
CODEWHALE_DEV_CACHE_REPO_ROOT="$NEW_WT" \
CODEWHALE_CACHE_ROOT="$work/cache")
if contains "$out" "sccache=skipped-incremental" \
&& contains "$out" "RUSTC_WRAPPER=<unset>" \
&& contains "$out" "CARGO_INCREMENTAL=1"; then
ok "explicit incremental=1 wins over CODEWHALE_SCCACHE=1"
else
bad "explicit incremental=1 wins over CODEWHALE_SCCACHE=1" "$out"
fi
out=$(run_apply \
CODEWHALE_SCCACHE=1 \
CODEWHALE_DEV_CACHE_REPO_ROOT="$NEW_WT" \
CODEWHALE_CACHE_ROOT="$work/cache" \
CODEWHALE_RUSTC_COMMIT=abc123deadbeef)
if contains "$out" "sccache=enabled" \
&& contains "$out" "CARGO_INCREMENTAL=0"; then
ok "CODEWHALE_SCCACHE=1 requests incremental=0 and wraps"
else
bad "CODEWHALE_SCCACHE=1 requests incremental=0 and wraps" "$out"
fi
out=$(run_apply \
RUSTC_WRAPPER=/usr/bin/true \
CARGO_INCREMENTAL=0 \
CODEWHALE_DEV_CACHE_REPO_ROOT="$NEW_WT")
if contains "$out" "sccache=external-wrapper" \
&& contains "$out" "RUSTC_WRAPPER=/usr/bin/true"; then
ok "existing RUSTC_WRAPPER is left alone"
else
bad "existing RUSTC_WRAPPER is left alone" "$out"
fi
# 10. Cargo older than 1.91 falls back to a per-workspace CARGO_TARGET_DIR.
printf '%s\n' '#!/bin/sh' 'echo "cargo 1.88.0 (test)"' >"$FAKEBIN/cargo"
chmod +x "$FAKEBIN/cargo"
out=$(run_apply \
CODEWHALE_DEV_CACHE=1 \
CODEWHALE_DEV_CACHE_REPO_ROOT="$NEW_WT" \
CODEWHALE_CACHE_ROOT="$work/cache")
if contains "$out" "legacy-target-dir" \
&& contains "$out" "CARGO_BUILD_BUILD_DIR=<unset>" \
&& contains "$out" "CARGO_TARGET_DIR=$work/cache/target/"; then
ok "cargo 1.88 falls back to an isolated CARGO_TARGET_DIR"
else
bad "cargo 1.88 falls back to an isolated CARGO_TARGET_DIR" "$out"
fi
rm -f "$FAKEBIN/cargo"
# 11. CLI self-check passes for a new worktree with portable HOME.
cli_out=$(
env -i \
PATH="$BASE_PATH" \
HOME="$HOME_DIR" \
PWD="$NEW_WT" \
CODEWHALE_DEV_CACHE_QUIET=1 \
CODEWHALE_DEV_CACHE_REPO_ROOT="$NEW_WT" \
CODEWHALE_CACHE_ROOT="$work/cache" \
/bin/sh "$DEV_CACHE" --self-check
) || cli_rc=$?
cli_rc=${cli_rc:-0}
if [ "$cli_rc" -eq 0 ] && contains "$cli_out" "dev-cache: self-check ok"; then
ok "CLI --self-check passes on a new worktree"
else
bad "CLI --self-check passes on a new worktree" "$cli_out"
fi
# 12. Two worktree paths produce different legacy fingerprints.
# shellcheck source=scripts/dev-cache.sh
. "$DEV_CACHE"
fp_a=$(codewhale_dev_cache_path_fingerprint "$NEW_WT")
fp_b=$(codewhale_dev_cache_path_fingerprint "$OLD_WT")
if [ -n "$fp_a" ] && [ -n "$fp_b" ] && [ "$fp_a" != "$fp_b" ]; then
ok "path fingerprints differ across worktrees"
else
bad "path fingerprints differ across worktrees" "a=$fp_a b=$fp_b"
fi
# 13. dev-cargo.sh --status is the same helper.
if /bin/sh "$DEV_CARGO" --help | grep -q 'dev-cache'; then
ok "dev-cargo.sh --help delegates to the cache helper"
else
bad "dev-cargo.sh --help delegates to the cache helper"
fi
if [ "$fail" -eq 0 ]; then
printf 'dev-cache.test.sh: all %s checks passed\n' "$pass"
exit 0
fi
printf 'dev-cache.test.sh: %s/%s checks failed\n' "$fail" "$((pass + fail))" >&2
exit 1
+31
View File
@@ -0,0 +1,31 @@
#!/bin/sh
# Run cargo with the portable Codewhale cache topology applied.
#
# scripts/dev-cargo.sh test -p codewhale-config --lib --locked
# scripts/dev-cargo.sh --status
# scripts/dev-cargo.sh --self-check
#
# This is the everyday compile entry point. It does not change product
# behavior. See scripts/dev-cache.sh and docs/BUILD_PERFORMANCE.md.
set -eu
repo_root=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd)
cd "$repo_root"
# shellcheck source=scripts/dev-cache.sh
. "$repo_root/scripts/dev-cache.sh"
case ${1:-} in
--status|--self-check|--print-exports|--help|-h)
exec "$repo_root/scripts/dev-cache.sh" "$1"
;;
esac
codewhale_dev_cache_apply
# Match CI / the product's 16 MiB owner-thread stack so local cargo test
# and nextest do not abort on the default ~2 MiB (Windows ~1 MiB) stack.
if [ -z "${RUST_MIN_STACK:-}" ]; then
RUST_MIN_STACK=16777216
export RUST_MIN_STACK
fi
codewhale_dev_cache_exec_cargo "$@"
+90 -33
View File
@@ -1,24 +1,36 @@
#!/bin/sh
# Map a workspace area or source path to the fastest cargo test for that
# area. Developer iteration aid only; no product behavior.
# Map a workspace area or source path to the fastest cargo/nextest
# invocation for that area, and apply the portable cache topology so a
# new worktree actually gets isolated build-dir (+ sccache only when
# incremental is already off). Developer iteration aid only; no product
# behavior.
#
# Usage:
# scripts/dev-test.sh <area|path> [filter...]
# scripts/dev-test.sh --list
# scripts/dev-test.sh --status
#
# Examples:
# scripts/dev-test.sh config
# scripts/dev-test.sh tui elapsed::
# scripts/dev-test.sh crates/tui/src/elapsed.rs
# scripts/dev-test.sh tui-pty qa_pty
#
# Environment:
# CODEWHALE_DEV_NEXTEST auto|1|0 (default auto: use cargo-nextest when
# it is on PATH; 0 forces cargo test)
# Cache knobs are documented in scripts/dev-cache.sh.
set -eu
repo_root=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
repo_root=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd)
cd "$repo_root"
# shellcheck source=scripts/dev-cache.sh
. "$repo_root/scripts/dev-cache.sh"
usage() {
printf '%s\n' "usage: scripts/dev-test.sh <area|path> [filter...]" >&2
printf '%s\n' " scripts/dev-test.sh --list" >&2
printf '%s\n' " scripts/dev-test.sh --list|--status|--self-check" >&2
exit 2
}
@@ -26,29 +38,34 @@ list_areas() {
cat <<'EOF'
area command
---- -------
config cargo test -p codewhale-config --lib --locked
protocol cargo test -p codewhale-protocol --lib --locked
execpolicy cargo test -p codewhale-execpolicy --lib --locked
paths cargo test -p codewhale-paths --lib --locked
secrets cargo test -p codewhale-secrets --lib --locked
agent cargo test -p codewhale-agent --lib --locked
app-server cargo test -p codewhale-app-server --lib --locked
build-support cargo test -p codewhale-build-support --lib --locked
cli cargo test -p codewhale-cli --lib --locked
command-contract cargo test -p codewhale-command-contract --lib --locked
config cargo test -p codewhale-config --lib --locked
core cargo test -p codewhale-core --lib --locked
execpolicy cargo test -p codewhale-execpolicy --lib --locked
hooks cargo test -p codewhale-hooks --lib --locked
lane cargo test -p codewhale-lane --lib --locked
mcp cargo test -p codewhale-mcp --lib --locked
paths cargo test -p codewhale-paths --lib --locked
protocol cargo test -p codewhale-protocol --lib --locked
release cargo test -p codewhale-release --lib --locked
secrets cargo test -p codewhale-secrets --lib --locked
state cargo test -p codewhale-state --lib --locked
telemetry cargo test -p codewhale-telemetry --lib --locked
tools cargo test -p codewhale-tools --lib --locked
tui cargo test -p codewhale-tui --lib --locked
tui-integration cargo test -p codewhale-tui --test integration --locked
tui-pty cargo test -p codewhale-tui --test pty --locked
tui-cucumber cargo test -p codewhale-tui --test cucumber --locked
workflow cargo test -p codewhale-workflow --lib --locked
workflow-js cargo test -p codewhale-workflow-js --lib --locked
path prefix area / extra filter
----------- -------------------
crates/config/ config
crates/protocol/ protocol
crates/execpolicy/ execpolicy
crates/paths/ paths
crates/secrets/ secrets
crates/cli/ cli
crates/core/ core
crates/tools/ tools
crates/<crate>/ <crate>
crates/tui/src/tui/ tui tui::
crates/tui/src/tools/ tui tools::
crates/tui/src/core/ tui core::
@@ -59,8 +76,13 @@ crates/tui/tests/pty/ tui-pty <stem>
crates/tui/tests/cucumber/ tui-cucumber <stem>
crates/tui/tests/ tui-integration
Do not use cargo test --workspace for a single-area edit. --lib and
--tests are disjoint; a green --lib run does not cover crates/tui/tests/.
When cargo-nextest is on PATH, the run stage is `cargo nextest run`
instead of `cargo test` (same binaries; process per test). Set
CODEWHALE_DEV_NEXTEST=0 to force libtest. New worktrees get an isolated
Cargo build-dir via scripts/dev-cache.sh; sccache wraps rustc only when
incremental is already off. Do not use cargo test --workspace for a
single-area edit. --lib and --tests are disjoint; a green --lib run does
not cover crates/tui/tests/.
EOF
}
@@ -71,6 +93,10 @@ if [ "$1" = "--list" ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
exit 0
fi
if [ "$1" = "--status" ] || [ "$1" = "--self-check" ]; then
exec "$repo_root/scripts/dev-cache.sh" "$1"
fi
area=$1
shift
@@ -80,14 +106,6 @@ if [ -e "$area" ] || printf '%s' "$area" | grep -q /; then
rel=${area#./}
extra=
case $rel in
crates/config/*|crates/config) area=config ;;
crates/protocol/*|crates/protocol) area=protocol ;;
crates/execpolicy/*|crates/execpolicy) area=execpolicy ;;
crates/paths/*|crates/paths) area=paths ;;
crates/secrets/*|crates/secrets) area=secrets ;;
crates/cli/*|crates/cli) area=cli ;;
crates/core/*|crates/core) area=core ;;
crates/tools/*|crates/tools) area=tools ;;
crates/tui/tests/integration/*)
area=tui-integration
extra=$(basename "$rel" .rs)
@@ -147,15 +165,27 @@ fi
pkg=
target=--lib
case $area in
config) pkg=codewhale-config ;;
protocol) pkg=codewhale-protocol ;;
execpolicy) pkg=codewhale-execpolicy ;;
paths) pkg=codewhale-paths ;;
secrets) pkg=codewhale-secrets ;;
agent) pkg=codewhale-agent ;;
app-server) pkg=codewhale-app-server ;;
build-support) pkg=codewhale-build-support ;;
cli) pkg=codewhale-cli ;;
command-contract) pkg=codewhale-command-contract ;;
config) pkg=codewhale-config ;;
core) pkg=codewhale-core ;;
execpolicy) pkg=codewhale-execpolicy ;;
hooks) pkg=codewhale-hooks ;;
lane) pkg=codewhale-lane ;;
mcp) pkg=codewhale-mcp ;;
paths) pkg=codewhale-paths ;;
protocol) pkg=codewhale-protocol ;;
release) pkg=codewhale-release ;;
secrets) pkg=codewhale-secrets ;;
state) pkg=codewhale-state ;;
telemetry) pkg=codewhale-telemetry ;;
tools) pkg=codewhale-tools ;;
tui) pkg=codewhale-tui ;;
workflow) pkg=codewhale-workflow ;;
workflow-js) pkg=codewhale-workflow-js ;;
tui-integration)
pkg=codewhale-tui
target=--test
@@ -177,11 +207,38 @@ case $area in
;;
esac
codewhale_dev_cache_apply
if [ -z "${RUST_MIN_STACK:-}" ]; then
RUST_MIN_STACK=16777216
export RUST_MIN_STACK
fi
use_nextest=0
_cw_nextest=${CODEWHALE_DEV_NEXTEST:-auto}
if codewhale_dev_cache_falsey "$_cw_nextest"; then
use_nextest=0
elif command -v cargo-nextest >/dev/null 2>&1; then
use_nextest=1
elif codewhale_dev_cache_truthy "$_cw_nextest"; then
printf '%s\n' "dev-test: CODEWHALE_DEV_NEXTEST=${_cw_nextest} but cargo-nextest is not on PATH" >&2
exit 2
fi
if [ "$target" = "--test" ]; then
if [ "$use_nextest" -eq 1 ]; then
set -- nextest run -p "$pkg" --test "$harness" --locked "$@"
printf '+ cargo %s\n' "$*"
codewhale_dev_cache_exec_cargo "$@"
fi
set -- test -p "$pkg" --test "$harness" --locked "$@"
else
if [ "$use_nextest" -eq 1 ]; then
set -- nextest run -p "$pkg" --lib --locked "$@"
printf '+ cargo %s\n' "$*"
codewhale_dev_cache_exec_cargo "$@"
fi
set -- test -p "$pkg" --lib --locked "$@"
fi
printf '+ cargo %s\n' "$*"
exec cargo "$@"
codewhale_dev_cache_exec_cargo "$@"
+216
View File
@@ -0,0 +1,216 @@
#!/bin/sh
# Hermetic tests for scripts/dev-test.sh: area routing, nextest vs
# libtest selection, and that the cache helper is actually applied.
# Uses a fake cargo; does not compile anything.
set -eu
repo_root=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd)
DEV_TEST=$repo_root/scripts/dev-test.sh
fail=0
pass=0
ok() {
pass=$((pass + 1))
printf 'ok - %s\n' "$1"
}
bad() {
fail=$((fail + 1))
printf 'FAIL - %s\n' "$1"
if [ -n "${2:-}" ]; then
printf '%s\n' "$2" | sed 's/^/ /'
fi
}
work=$(mktemp -d "${TMPDIR:-/tmp}/codewhale-dev-test.XXXXXX")
cleanup() { rm -rf "$work"; }
trap cleanup EXIT INT HUP TERM
FAKEBIN=$work/bin
mkdir -p "$FAKEBIN"
NEW_WT=$work/new-wt
mkdir -p "$NEW_WT"
cat >"$FAKEBIN/cargo" <<'EOF'
#!/bin/sh
printf 'CARGO:%s\n' "$*"
printf 'CARGO_BUILD_BUILD_DIR=%s\n' "${CARGO_BUILD_BUILD_DIR-<unset>}"
printf 'RUSTC_WRAPPER=%s\n' "${RUSTC_WRAPPER-<unset>}"
printf 'CARGO_INCREMENTAL=%s\n' "${CARGO_INCREMENTAL-<unset>}"
printf 'RUST_MIN_STACK=%s\n' "${RUST_MIN_STACK-<unset>}"
exit 0
EOF
chmod +x "$FAKEBIN/cargo"
BASE_PATH=$FAKEBIN:/usr/bin:/bin
run_dev_test() {
# Leading KEY=VAL pairs are extra env; the rest are script arguments.
_extra=$work/extra-env
: >"$_extra"
while [ $# -gt 0 ]; do
case $1 in
*=*)
printf '%s\n' "$1" >>"$_extra"
shift
;;
*)
break
;;
esac
done
# env -i + env-file keeps values with spaces intact and never treats
# --list as an env(1) option.
set -- /bin/sh "$DEV_TEST" "$@"
while IFS= read -r _line; do
set -- "$_line" "$@"
done <"$_extra"
env -i \
PATH="$BASE_PATH" \
HOME="$work/home" \
CODEWHALE_DEV_CACHE_QUIET=1 \
CODEWHALE_DEV_CACHE_REPO_ROOT="$NEW_WT" \
CODEWHALE_CACHE_ROOT="$work/cache" \
"$@"
}
contains() {
printf '%s' "$1" | grep -qF -- "$2"
}
# --list names every workspace crate family, including the ones the old
# mapper dropped on the floor.
list_out=$(run_dev_test --list)
for needle in \
"codewhale-agent" \
"codewhale-app-server" \
"codewhale-build-support" \
"codewhale-command-contract" \
"codewhale-hooks" \
"codewhale-lane" \
"codewhale-mcp" \
"codewhale-release" \
"codewhale-state" \
"codewhale-telemetry" \
"codewhale-workflow" \
"codewhale-workflow-js" \
"codewhale-tui --lib" \
"codewhale-tui --test pty"
do
if contains "$list_out" "$needle"; then
ok "--list mentions $needle"
else
bad "--list mentions $needle" "$list_out"
fi
done
# Narrow routing: libtest forced so we assert cargo test argv.
out=$(run_dev_test CODEWHALE_DEV_NEXTEST=0 config)
if contains "$out" "+ cargo test -p codewhale-config --lib --locked" \
&& contains "$out" "test -p codewhale-config --lib --locked"; then
ok "area config maps to codewhale-config --lib"
else
bad "area config maps to codewhale-config --lib" "$out"
fi
out=$(run_dev_test CODEWHALE_DEV_NEXTEST=0 crates/tui/src/elapsed.rs)
if contains "$out" "test -p codewhale-tui --lib --locked elapsed::"; then
ok "path crates/tui/src/elapsed.rs invents elapsed::"
else
bad "path crates/tui/src/elapsed.rs invents elapsed::" "$out"
fi
out=$(run_dev_test CODEWHALE_DEV_NEXTEST=0 crates/workflow-js/src/eval.rs)
if contains "$out" "test -p codewhale-workflow-js --lib --locked"; then
ok "path crates/workflow-js maps to codewhale-workflow-js"
else
bad "path crates/workflow-js maps to codewhale-workflow-js" "$out"
fi
out=$(run_dev_test CODEWHALE_DEV_NEXTEST=0 crates/app-server/src/lib.rs)
if contains "$out" "test -p codewhale-app-server --lib --locked"; then
ok "path crates/app-server maps to codewhale-app-server"
else
bad "path crates/app-server maps to codewhale-app-server" "$out"
fi
out=$(run_dev_test CODEWHALE_DEV_NEXTEST=0 tui-pty qa_pty)
if contains "$out" "test -p codewhale-tui --test pty --locked qa_pty"; then
ok "tui-pty maps to the pty harness"
else
bad "tui-pty maps to the pty harness" "$out"
fi
# Unknown area fails closed.
rc=0
out=$(run_dev_test CODEWHALE_DEV_NEXTEST=0 not-a-crate 2>&1) || rc=$?
if [ "$rc" -ne 0 ] && contains "$out" "unknown area"; then
ok "unknown area fails closed"
else
bad "unknown area fails closed" "rc=$rc $out"
fi
# New worktree applies the isolated build-dir (compile-time topology).
out=$(run_dev_test CODEWHALE_DEV_NEXTEST=0 config)
if contains "$out" "CARGO_BUILD_BUILD_DIR=$work/cache/build/{workspace-path-hash}" \
&& contains "$out" '--config build.build-dir = "'; then
ok "dev-test applies isolated build-dir on a new worktree"
else
bad "dev-test applies isolated build-dir on a new worktree" "$out"
fi
if contains "$out" "RUST_MIN_STACK=16777216"; then
ok "dev-test sets RUST_MIN_STACK when unset"
else
bad "dev-test sets RUST_MIN_STACK when unset" "$out"
fi
if contains "$out" "RUSTC_WRAPPER=<unset>"; then
ok "dev-test does not wrap rustc on the incremental default"
else
bad "dev-test does not wrap rustc on the incremental default" "$out"
fi
# CODEWHALE_DEV_CACHE=0 really disables the topology.
out=$(run_dev_test CODEWHALE_DEV_NEXTEST=0 CODEWHALE_DEV_CACHE=0 config)
if contains "$out" "CARGO_BUILD_BUILD_DIR=<unset>" \
&& ! contains "$out" '--config build.build-dir'; then
ok "CODEWHALE_DEV_CACHE=0 skips the cache topology"
else
bad "CODEWHALE_DEV_CACHE=0 skips the cache topology" "$out"
fi
# nextest is used when cargo-nextest is on PATH (test-runtime).
printf '%s\n' '#!/bin/sh' 'exit 0' >"$FAKEBIN/cargo-nextest"
chmod +x "$FAKEBIN/cargo-nextest"
out=$(run_dev_test tui elapsed::)
if contains "$out" "+ cargo nextest run -p codewhale-tui --lib --locked elapsed::" \
&& contains "$out" "nextest run -p codewhale-tui --lib --locked elapsed::"; then
ok "nextest is used when cargo-nextest is installed"
else
bad "nextest is used when cargo-nextest is installed" "$out"
fi
out=$(run_dev_test CODEWHALE_DEV_NEXTEST=0 tui elapsed::)
if contains "$out" "+ cargo test -p codewhale-tui --lib --locked elapsed::" \
&& contains "$out" "test -p codewhale-tui --lib --locked elapsed::"; then
ok "CODEWHALE_DEV_NEXTEST=0 forces cargo test"
else
bad "CODEWHALE_DEV_NEXTEST=0 forces cargo test" "$out"
fi
# Forced nextest without the binary fails closed instead of silent cargo.
rm -f "$FAKEBIN/cargo-nextest"
rc=0
out=$(run_dev_test CODEWHALE_DEV_NEXTEST=1 config 2>&1) || rc=$?
if [ "$rc" -ne 0 ] && contains "$out" "cargo-nextest is not on PATH"; then
ok "CODEWHALE_DEV_NEXTEST=1 without nextest fails closed"
else
bad "CODEWHALE_DEV_NEXTEST=1 without nextest fails closed" "rc=$rc $out"
fi
if [ "$fail" -eq 0 ]; then
printf 'dev-test.test.sh: all %s checks passed\n' "$pass"
exit 0
fi
printf 'dev-test.test.sh: %s/%s checks failed\n' "$fail" "$((pass + fail))" >&2
exit 1