@@ -6,22 +6,37 @@ TEST_HOME="${DEV_KIT_TEST_HOME:-$(mktemp -d "${TMPDIR:-/tmp}/dev-kit-real-repos.
66DEV_KIT_BIN_DIR=" $TEST_HOME /.local/bin"
77KEEP_HOME=" ${DEV_KIT_TEST_KEEP_HOME:- 0} "
88REAL_REPOS_CSV=" ${DEV_KIT_TEST_REAL_REPOS:- } "
9+ MODE=" check"
10+ REPORT_DIR=" ${DEV_KIT_TEST_REPORT_DIR:- $TEST_HOME / reports} "
11+ COMMAND_SOFT_TIMEOUT=" ${DEV_KIT_TEST_SOFT_TIMEOUT:- 15} "
12+ COMMAND_HARD_TIMEOUT=" ${DEV_KIT_TEST_HARD_TIMEOUT:- 180} "
13+
14+ # shellcheck disable=SC1091
15+ . " $REPO_DIR /lib/modules/output.sh"
916
1017usage () {
1118 cat << 'EOF '
12- Usage: bash tests/real-repos.sh [/abs/path/to/repo ...]
19+ Usage: bash tests/real-repos.sh [--check|--write] [ /abs/path/to/repo ...]
1320
1421Runs the current dev.kit working tree against real local repos using a temporary
1522plain `dev.kit` shim, without changing the global install.
1623
24+ Default mode is --check, which is read-only for target repos.
25+
1726Options via environment:
1827 DEV_KIT_TEST_REAL_REPOS Colon-separated repo paths when no CLI args are given
1928 DEV_KIT_TEST_HOME Temp home for the test run
29+ DEV_KIT_TEST_REPORT_DIR Directory for per-repo JSON reports
30+ DEV_KIT_TEST_SOFT_TIMEOUT Seconds before a slow-command notice (default: 15)
31+ DEV_KIT_TEST_HARD_TIMEOUT Seconds before stopping a command (default: 180)
2032 DEV_KIT_TEST_KEEP_HOME Keep temp home after exit (default: 0)
2133
2234Examples:
23- bash tests/real-repos.sh ~/git/udx/reusable-workflows ~/git/udx/www.peakclt.com
24- DEV_KIT_TEST_REAL_REPOS="$HOME/git/udx/reusable-workflows:$HOME/git/udx/www.peakclt.com" bash tests/real-repos.sh
35+ bash tests/real-repos.sh --check ./reusable-workflows ./github-rabbit-action
36+ DEV_KIT_TEST_REAL_REPOS="./reusable-workflows:./github-rabbit-action" bash tests/real-repos.sh --check
37+ bash tests/real-repos.sh --write /tmp/dev-kit-probe-clone
38+
39+ Probe examples and release matrix candidates live in src/configs/repo-validation.yaml.
2540EOF
2641}
2742
@@ -33,59 +48,131 @@ cleanup() {
3348
3449trap cleanup EXIT
3550
36- if [ " ${1:- } " = " -h" ] || [ " ${1:- } " = " --help" ]; then
37- usage
38- exit 0
39- fi
40-
4151repo_paths=()
42- if [ " $# " -gt 0 ]; then
43- while [ " $# " -gt 0 ]; do
44- repo_paths+=(" $1 " )
45- shift
46- done
47- elif [ -n " $REAL_REPOS_CSV " ]; then
52+ while [ " $# " -gt 0 ]; do
53+ case " $1 " in
54+ --check) MODE=" check" ;;
55+ --write) MODE=" write" ;;
56+ -h|--help) usage; exit 0 ;;
57+ --* ) printf ' Unknown option: %s\n' " $1 " >&2 ; usage >&2 ; exit 1 ;;
58+ * ) repo_paths+=(" $1 " ) ;;
59+ esac
60+ shift
61+ done
62+
63+ if [ " ${# repo_paths[@]} " -eq 0 ] && [ -n " $REAL_REPOS_CSV " ]; then
4864 while IFS= read -r repo_path; do
4965 [ -n " $repo_path " ] || continue
5066 repo_paths+=(" $repo_path " )
5167 done << EOF
5268$( printf ' %s' " $REAL_REPOS_CSV " | tr ' :' ' \n' )
5369EOF
54- else
70+ fi
71+
72+ if [ " ${# repo_paths[@]} " -eq 0 ]; then
5573 usage >&2
5674 exit 1
5775fi
5876
5977mkdir -p " $DEV_KIT_BIN_DIR "
78+ mkdir -p " $REPORT_DIR "
6079ln -sfn " $REPO_DIR /bin/dev-kit" " $DEV_KIT_BIN_DIR /dev.kit"
6180
6281export HOME=" $TEST_HOME "
6382export PATH=" $DEV_KIT_BIN_DIR :/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
6483unset DEV_KIT_HOME
6584unset DEV_KIT_BIN_DIR
6685
86+ require_jq () {
87+ if ! command -v jq > /dev/null 2>&1 ; then
88+ printf ' jq is required for real repo report summaries\n' >&2
89+ exit 1
90+ fi
91+ }
92+
93+ report_name_for_repo () {
94+ basename " $1 " | tr -c ' A-Za-z0-9._-' ' -'
95+ }
96+
97+ print_check_summary () {
98+ local repo_path=" $1 "
99+ local home_json=" $2 "
100+ local repo_json=" $3 "
101+ local refs_count=" "
102+ local gap_count=" "
103+ local workflow_status=" "
104+ local context_status=" "
105+ local home_context_status=" "
106+
107+ home_context_status=" $( jq -r ' .synced.context_status // "none"' " $home_json " ) "
108+ workflow_status=" $( jq -r ' .workflow.jobs[] | select(.id == "repo") | .status' " $repo_json " ) "
109+ context_status=" $( jq -r ' .workflow.jobs[] | select(.id == "repo") | .context_status' " $repo_json " ) "
110+ gap_count=" $( jq -r ' .workflow.jobs[] | select(.id == "repo") | .gap_count' " $repo_json " ) "
111+ refs_count=" $( jq -r ' [.workflow.jobs[] | select(.id == "repo") | .steps[]? | select(.id == "read_repo") | .refs[]?] | length' " $repo_json " ) "
112+
113+ printf ' %s\tmode=%s\thome_context=%s\trepo_status=%s\trepo_context=%s\tgaps=%s\tread_refs=%s\n' \
114+ " $repo_path " " $MODE " " $home_context_status " " $workflow_status " " $context_status " " $gap_count " " $refs_count "
115+ }
116+
117+ print_write_summary () {
118+ local repo_path=" $1 "
119+ local repo_json=" $2 "
120+ local context_yaml=" $repo_path /.rabbit/context.yaml"
121+ local gap_count=" "
122+ local manifest_count=0
123+ local dep_count=0
124+
125+ gap_count=" $( jq -r ' .workflow.jobs[] | select(.id == "repo") | .gap_count' " $repo_json " ) "
126+ if [ -f " $context_yaml " ]; then
127+ manifest_count=" $( awk ' /^manifests:/{flag=1;next} flag && /^[^[:space:]#]/{exit} flag && /^ - path:/{count += 1} END{print count + 0}' " $context_yaml " ) "
128+ dep_count=" $( awk ' /^dependencies:/{flag=1;next} /^# Manifests/{if(flag) exit} flag && /^ - repo:/{count += 1} END{print count + 0}' " $context_yaml " ) "
129+ fi
130+
131+ printf ' %s\tmode=%s\tcontext=%s\tgaps=%s\tmanifests=%s\tdependencies=%s\n' \
132+ " $repo_path " " $MODE " " $context_yaml " " $gap_count " " $manifest_count " " $dep_count "
133+ }
134+
135+ run_report_command () {
136+ local label=" $1 "
137+ local output_file=" $2 "
138+ shift 2
139+
140+ local tmp_file=" ${output_file} .tmp"
141+ rm -f " $tmp_file "
142+ DEV_KIT_SPINNER_DISABLE=1 dev_kit_run_guarded \
143+ " $label " \
144+ " $COMMAND_SOFT_TIMEOUT " \
145+ " $COMMAND_HARD_TIMEOUT " \
146+ " $label is taking longer than usual; still resolving repo evidence" \
147+ " $@ " > " $tmp_file "
148+ mv " $tmp_file " " $output_file "
149+ }
150+
151+ require_jq
152+ printf ' report_dir: %s\n' " $REPORT_DIR "
153+ printf ' mode: %s\n' " $MODE "
154+
67155for repo_path in " ${repo_paths[@]} " ; do
68156 repo_path=" $( cd " $repo_path " 2> /dev/null && pwd || true) "
69157 [ -n " $repo_path " ] || { printf ' repo not found\n' >&2 ; exit 1; }
70158 [ -d " $repo_path /.git" ] || { printf ' not a git repo: %s\n' " $repo_path " >&2 ; exit 1; }
71- run_out=" $( mktemp " $TEST_HOME /dev-kit-real.XXXXXX.out" ) "
159+ repo_report_name=" $( report_name_for_repo " $repo_path " ) "
160+ home_json=" $REPORT_DIR /${repo_report_name} .home.json"
161+ repo_json=" $REPORT_DIR /${repo_report_name} .repo.json"
72162
73163 printf ' \n===== %s =====\n' " $repo_path "
74- (
75- cd " $repo_path "
76- if ! dev.kit > " $run_out " ; then
77- cat " $run_out " >&2
78- exit 1
79- fi
80- dev.kit repo > /dev/null
81- [ -f .rabbit/context.yaml ] || { printf ' missing .rabbit/context.yaml\n' >&2 ; exit 1; }
82-
83- printf ' context: %s\n' " $repo_path /.rabbit/context.yaml"
84- printf ' \nrepo:\n'
85- sed -n ' 1,20p' .rabbit/context.yaml
86- printf ' \ngaps:\n'
87- awk ' /^gaps:/{flag=1;next} /^# Dependencies/{if(flag) exit} flag{print}' .rabbit/context.yaml || true
88- printf ' \ndependencies:\n'
89- awk ' /^dependencies:/{flag=1;next} /^# Manifests/{if(flag) exit} flag{print}' .rabbit/context.yaml | sed -n ' 1,80p'
90- )
164+ if [ " $MODE " = " check" ]; then
165+ (
166+ cd " $repo_path "
167+ run_report_command " dev.kit home check: $repo_path " " $home_json " dev.kit --json
168+ run_report_command " dev.kit repo check: $repo_path " " $repo_json " dev.kit repo --json --check
169+ )
170+ print_check_summary " $repo_path " " $home_json " " $repo_json "
171+ else
172+ (
173+ cd " $repo_path "
174+ run_report_command " dev.kit repo write: $repo_path " " $repo_json " dev.kit repo --json
175+ )
176+ print_write_summary " $repo_path " " $repo_json "
177+ fi
91178done
0 commit comments