diff --git a/packages/mosaic/framework/tools/git/detect-platform.sh b/packages/mosaic/framework/tools/git/detect-platform.sh index 97c6e5b3..a06452d1 100755 --- a/packages/mosaic/framework/tools/git/detect-platform.sh +++ b/packages/mosaic/framework/tools/git/detect-platform.sh @@ -5,7 +5,10 @@ detect_platform() { local remote_url - remote_url=$(git remote get-url origin 2>/dev/null) + # `|| true` is load-bearing under `set -e`: outside a git repo this returns 128 and + # kills the CALLER before the -z check below can run, so the error message that is + # already written here was unreachable. Same idiom as get_gitea_repo_args() below. + remote_url=$(git remote get-url origin 2>/dev/null) || true if [[ -z "$remote_url" ]]; then echo "error: not a git repository or no origin remote" >&2 @@ -39,7 +42,10 @@ detect_platform() { get_repo_info() { local remote_url - remote_url=$(git remote get-url origin 2>/dev/null) + # `|| true` is load-bearing under `set -e`: outside a git repo this returns 128 and + # kills the CALLER before the -z check below can run, so the error message that is + # already written here was unreachable. Same idiom as get_gitea_repo_args() below. + remote_url=$(git remote get-url origin 2>/dev/null) || true if [[ -z "$remote_url" ]]; then echo "error: not a git repository or no origin remote" >&2 diff --git a/packages/mosaic/framework/tools/git/test-detect-platform-outside-repo.sh b/packages/mosaic/framework/tools/git/test-detect-platform-outside-repo.sh new file mode 100755 index 00000000..fa7978c3 --- /dev/null +++ b/packages/mosaic/framework/tools/git/test-detect-platform-outside-repo.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# Regression: detect_platform / get_repo_info must FAIL LOUDLY outside a git repo, +# not kill the caller silently. +# +# Both functions already contained the right error path: +# if [[ -z "$remote_url" ]]; then echo "error: not a git repository..." >&2; return 1; fi +# but under `set -e` -- which every wrapper in this directory uses -- the preceding +# assignment `remote_url=$(git remote get-url origin 2>/dev/null)` returns git's 128 +# outside a repo and terminates the CALLER first. The message was unreachable. +# +# Observed cost: pr-review.sh invoked from a non-repo cwd exits 128 with NO stdout and +# NO stderr, even when -r/--repo and -H/--host are supplied -- the flags documented as +# "skips git-remote inference". Two reviewer seats hit this and correctly reported +# `blocked` with no diagnostic to report. +# +# The control that matters is the LOUD one: asserting "rc != 0" passes on the broken +# build too, because 128 is also non-zero. The test must assert the MESSAGE. +set -uo pipefail +fail=0 +HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +TMP="$(mktemp -d)"; trap 'rm -rf "$TMP"' EXIT + +run_outside() { # $1=function name -> "rc:sawmessage" + local fn="$1" out rc + out=$( cd "$TMP" && bash -c "set -e; source '$HERE/detect-platform.sh'; $fn" 2>&1 ); rc=$? + printf '%s:%s' "$rc" "$(grep -qi 'not a git repository' <<<"$out" && echo yes || echo no)" +} +check() { if [ "$2" = "$3" ]; then echo " PASS $1 ($2)"; else echo " FAIL $1: got $2, want $3"; fail=1; fi; } + +# $TMP is deliberately not a git repo, and must not be inside one. +( cd "$TMP" && git rev-parse --git-dir >/dev/null 2>&1 ) && { echo " SKIP scratch dir is inside a repo"; exit 0; } + +echo "== outside a git repo: rc=1 AND the diagnostic is emitted ==" +check "detect_platform" "$(run_outside detect_platform)" "1:yes" +check "get_repo_info" "$(run_outside get_repo_info)" "1:yes" + +echo "== inside a git repo the functions still work ==" +git init -q "$TMP/repo" 2>/dev/null +git -C "$TMP/repo" remote add origin https://git.mosaicstack.dev/mosaicstack/stack.git 2>/dev/null +out=$( cd "$TMP/repo" && bash -c "set -e; source '$HERE/detect-platform.sh'; detect_platform" 2>&1 ); rc=$? +if [ "$rc" -eq 0 ] && grep -qi 'gitea' <<<"$out"; then echo " PASS detect_platform in-repo (rc=0, $out)" +else echo " FAIL detect_platform in-repo: rc=$rc out=$out"; fail=1; fi + +[ "$fail" -eq 0 ] && echo "OK detect-platform fails loudly outside a repo" || echo "FAILED" +exit "$fail" diff --git a/packages/mosaic/package.json b/packages/mosaic/package.json index 23234ef3..bc7f750e 100644 --- a/packages/mosaic/package.json +++ b/packages/mosaic/package.json @@ -6,7 +6,7 @@ "url": "https://git.mosaicstack.dev/mosaicstack/stack.git", "directory": "packages/mosaic" }, - "description": "Mosaic agent framework — installation wizard and meta package", + "description": "Mosaic agent framework \u2014 installation wizard and meta package", "type": "module", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -25,7 +25,7 @@ "lint": "eslint src", "typecheck": "tsc --noEmit", "test": "vitest run --passWithNoTests && pnpm run test:framework-shell", - "test:framework-shell": "bash framework/tools/quality/scripts/check-test-enumeration.sh && bash framework/tools/quality/scripts/test-check-test-enumeration.sh && python3 src/lease-broker/daemon_deadline_unittest.py && python3 src/lease-broker/normative_fragments_unittest.py && python3 src/lease-broker/receipt_challenge_unittest.py && python3 src/lease-broker/context_recovery_unittest.py && python3 src/lease-broker/recovery_runtime_unittest.py && python3 src/lease-broker/recovery_b1_adversarial_unittest.py && python3 src/lease-broker/framework_skill_portability_unittest.py && python3 src/mutator-gate/runtime_tools_unittest.py && python3 src/mutator-gate/runtime_launch_guard_unittest.py && python3 src/mutator-gate/version_coupling_unittest.py && python3 framework/tools/lease-broker/check-runtime-launches.py --root ../.. && bash framework/tools/codex/test-pr-diff-context.sh && bash framework/tools/qa/test-deps-preflight.sh && bash framework/tools/git/test-pr-review-gitea-comment.sh && bash framework/tools/git/test-pr-review-repo-host-override.sh && bash framework/tools/git/test-ci-queue-wait-branch-absent.sh && bash framework/tools/git/test-ci-queue-wait-tristate.sh && bash framework/tools/git/test-ci-queue-wait-github-checks.sh && bash framework/tools/git/test-pr-merge-queue-branch.sh && bash framework/tools/git/test-pr-merge-head-pin.sh && bash framework/tools/git/test-pr-merge-message-field.sh && bash framework/tools/git/test-git-credential-mosaic.sh && bash framework/tools/git/test-gitea-token-identity.sh && bash framework/tools/woodpecker/test-terminal-green-contract.sh && bash framework/tools/_scripts/test-install-ordering-guard.sh && bash framework/tools/tmux/agent-send.test.sh && bash framework/tools/wake/test-wake-store-ack.sh && bash framework/tools/wake/test-wake-store-enqueue-race.sh && bash framework/tools/wake/test-wake-digest-hmac.sh && bash framework/tools/wake/test-wake-digest-quarantine.sh && bash framework/tools/wake/test-wake-detector.sh && bash framework/tools/wake/test-wake-fn-oracle.sh && bash framework/tools/wake/test-wake-reconcile.sh && bash framework/tools/wake/test-wake-beacon.sh && bash framework/tools/wake/test-wake-preimage.sh && bash framework/tools/wake/test-wake-install.sh" + "test:framework-shell": "bash framework/tools/quality/scripts/check-test-enumeration.sh && bash framework/tools/quality/scripts/test-check-test-enumeration.sh && python3 src/lease-broker/daemon_deadline_unittest.py && python3 src/lease-broker/normative_fragments_unittest.py && python3 src/lease-broker/receipt_challenge_unittest.py && python3 src/lease-broker/context_recovery_unittest.py && python3 src/lease-broker/recovery_runtime_unittest.py && python3 src/lease-broker/recovery_b1_adversarial_unittest.py && python3 src/lease-broker/framework_skill_portability_unittest.py && python3 src/mutator-gate/runtime_tools_unittest.py && python3 src/mutator-gate/runtime_launch_guard_unittest.py && python3 src/mutator-gate/version_coupling_unittest.py && python3 framework/tools/lease-broker/check-runtime-launches.py --root ../.. && bash framework/tools/codex/test-pr-diff-context.sh && bash framework/tools/qa/test-deps-preflight.sh && bash framework/tools/git/test-pr-review-gitea-comment.sh && bash framework/tools/git/test-pr-review-repo-host-override.sh && bash framework/tools/git/test-ci-queue-wait-branch-absent.sh && bash framework/tools/git/test-ci-queue-wait-tristate.sh && bash framework/tools/git/test-ci-queue-wait-github-checks.sh && bash framework/tools/git/test-pr-merge-queue-branch.sh && bash framework/tools/git/test-pr-merge-head-pin.sh && bash framework/tools/git/test-pr-merge-message-field.sh && bash framework/tools/git/test-git-credential-mosaic.sh && bash framework/tools/git/test-gitea-token-identity.sh && bash framework/tools/git/test-detect-platform-outside-repo.sh && bash framework/tools/woodpecker/test-terminal-green-contract.sh && bash framework/tools/_scripts/test-install-ordering-guard.sh && bash framework/tools/tmux/agent-send.test.sh && bash framework/tools/wake/test-wake-store-ack.sh && bash framework/tools/wake/test-wake-store-enqueue-race.sh && bash framework/tools/wake/test-wake-digest-hmac.sh && bash framework/tools/wake/test-wake-digest-quarantine.sh && bash framework/tools/wake/test-wake-detector.sh && bash framework/tools/wake/test-wake-fn-oracle.sh && bash framework/tools/wake/test-wake-reconcile.sh && bash framework/tools/wake/test-wake-beacon.sh && bash framework/tools/wake/test-wake-preimage.sh && bash framework/tools/wake/test-wake-install.sh" }, "dependencies": { "@mosaicstack/brain": "workspace:*",