#!/usr/bin/env bash # Refuse tooling that contradicts what this project actually uses. # # TRACES: | DR-222 # # ./scripts/check-tooling.sh # # ## Why # # This is a bun project: `packageManager` in package.json says so, bun.lock is # the committed lockfile, and .gitignore hides the other package managers' # lockfiles precisely so they cannot be committed by accident. # # scripts/build-android.sh nonetheless ran `npm install` on its clean-build # path. npm ignores bun.lock, re-resolves the whole tree from package.json, and # writes a package-lock.json that .gitignore then hides from view. # # That is not a style preference. The Tauri CLI refuses to build when a plugin's # Rust crate and npm package differ by minor version, so the JS side is pinned # exactly against Cargo.lock -- and a silent re-resolve is exactly how those # halves drift apart again. The drift already cost one release build. # # It survived because the clean-build path runs rarely. That is the shape of # nearly every defect found while preparing v0.10.0: the code that runs on every # commit was fine, and the code that runs on a release, a clean build or a tag # had no guard at all. set -uo pipefail REPO_ROOT="$(git rev-parse --show-toplevel)" cd "$REPO_ROOT" || exit 1 FAILED=0 echo "🔎 Checking build tooling is consistent with packageManager…" # Only the *invocations* matter. A comment explaining why npm is wrong, or a # .gitignore entry naming package-lock.json, is not a violation -- so match a # command at the start of a line or after a shell separator. PATTERN='(^|[;&|(]|&&|\|\||\bthen |\bdo |[[:space:]]{4,})(npm|yarn|pnpm)[[:space:]]+(install|ci|add|run|exec)\b' MATCHES="$(grep -rInE "$PATTERN" \ --include='*.sh' --include='*.yml' --include='*.yaml' \ scripts/ .gitea/ 2>/dev/null | grep -v '^\s*#' || true)" if [ -n "$MATCHES" ]; then echo "❌ A non-bun package manager is invoked:" echo "$MATCHES" | sed 's/^/ /' echo "" echo " This project uses bun (packageManager in package.json, bun.lock" echo " committed). npm/yarn/pnpm ignore that lockfile and re-resolve the" echo " dependency tree, which is how the Tauri plugin crate/package" echo " versions drifted apart and broke a release build." echo "" echo " Use: bun install / bun run / bunx" FAILED=1 fi # A lockfile from another manager should never exist here; .gitignore hides # them, so one can sit in a working tree unnoticed and change what installs. for stray in package-lock.json yarn.lock pnpm-lock.yaml; do if [ -f "$stray" ]; then echo "❌ $stray exists. Another package manager has run here." echo " Delete it and run: bun install" FAILED=1 fi done if [ "$FAILED" -eq 0 ]; then echo "✅ Only bun is used, and no foreign lockfile is present." fi exit "$FAILED"