#!/usr/bin/env bash set -euo pipefail root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" work="$(mktemp -d)" trap 'rm -rf "$work"' EXIT trap 'echo "mutate: interrupted" >&2; exit 130' INT TERM native() { if command -v cygpath >/dev/null 2>&1; then cygpath -m "$1" else printf '%s' "$1" fi } exclude_pattern() { local sep='[/\\]' local name="${1//./[.]}" printf '%s' "(^|${sep})${name}\$" } repo="$work/repo" mkdir -p "$repo" "$repo/tmp" "$repo/.git" "$work/tmp" "$root/tmp" tar -C "$root" -c \ --exclude=./bin --exclude=./web --exclude=./node_modules --exclude=./.git \ --exclude=./.task --exclude=./tmp --exclude=./data --exclude=./.claude \ --exclude=./internal/infrastructure/assets/dist --exclude='*.exe' --exclude='*.db' . | tar -C "$repo" -x export GOCACHE="$(native "$work/gocache")" export TEMP="$(native "$work/tmp")" export TMP="$TEMP" export TMPDIR="$TEMP" export GOFLAGS="-buildvcs=false${MUTATE_RUN:+ -run=$MUTATE_RUN}" cd "$repo" code=0 scopes=( ./internal/infrastructure/useCases ./api/middleware ./api/pkg/claims ./internal/domain/audit ./internal/infrastructure/persistence/repositories ./api/handlers/settings ) if [ "$#" -gt 0 ]; then scopes=("$@") fi coverpkg="" for scope in "${scopes[@]}"; do coverpkg="${coverpkg:+$coverpkg,}$scope/..." done parts=() i=0 for scope in "${scopes[@]}"; do i=$((i + 1)) part="$work/part$i.json" rc=0 excludes=() if [ -n "${MUTATE_FILES:-}" ]; then keep=0 for f in "$scope"/*.go; do base="$(basename "$f")" case "$base" in *_test.go) continue ;; esac case ",${MUTATE_FILES}," in *",$base,"*) keep=$((keep + 1)) ;; *) excludes+=(-E "$(exclude_pattern "$base")") ;; esac done if [ "$keep" -eq 0 ]; then continue; fi fi gremlins unleash --integration --tags nofrontend --workers "${MUTATE_WORKERS:-4}" --coverpkg="$coverpkg" --timeout-coefficient 10 ${excludes[@]+"${excludes[@]}"} --output "$(native "$part")" "$scope" || rc=$? if [ "$rc" -ge 128 ]; then exit "$rc"; fi if [ "$rc" -ne 0 ]; then code=$rc; fi if [ -f "$part" ]; then parts+=("$(native "$part")"); fi done python - "$(native "$root/tmp/gremlins.json")" "${parts[@]}" <<'PY' import json, sys out, parts = sys.argv[1], sys.argv[2:] merged = None for p in parts: d = json.load(open(p)) if merged is None: merged = d else: merged["files"] = merged.get("files", []) + d.get("files", []) if merged is None: merged = {"files": []} json.dump(merged, open(out, "w"), indent=2) PY go clean -cache >/dev/null 2>&1 || true exit "$code"