Compare commits

...

10 Commits

3 changed files with 171 additions and 45 deletions
+31 -37
View File
@@ -1,64 +1,58 @@
# Task 06G4FT0MB733H2ZCZ237WFHFD8
# Task 06G4VF5HZW7Q4JBM3TTY7W1Y64
Give the healthcheck a self-test and a machine-readable mode
Add ten named checks to the healthcheck, in five phases
- Project: test-e2e
- Source: gitea:test-e2e/10
- Source: burnin/run18-implement-successor
- Priority: 0
## Instructions
Three pieces of work, in order. Plan them as exactly three phases in that order.
scripts/orchestra_e2e_healthcheck.sh currently runs a single check. Grow it to ten named checks, each implemented as its own shell function, each reported by name.
## Phase 1 — a self-test for the healthcheck
The ten checks, all read-only and all satisfiable inside this repository:
New file `scripts/orchestra_e2e_selftest.sh`, executable, `#!/usr/bin/env bash`.
1. repo_root_readable, 2. scripts_dir_present, 3. healthcheck_executable_bit, 4. selftest_present, 5. test_healthcheck_present, 6. readme_present, 7. no_crlf_line_endings, 8. no_tabs_in_scripts, 9. shebang_is_bash, 10. usage_text_mentions_every_flag.
It runs `scripts/orchestra_e2e_healthcheck.sh`, then asserts:
Each check is a function named check_<name> that returns 0 for pass and 1 for fail, prints nothing on its own, and records its name and outcome in the existing results state.
- exit status is 0
- stdout contains `OK`
Plan this as FIVE phases:
On failure it prints which assertion failed and exits 1. On success it prints `selftest: ok` and exits 0.
1. Checks 1 to 3, with the dispatch loop that runs a list of check functions and records each outcome.
2. Checks 4 to 6.
3. Checks 7 to 8.
4. Checks 9 to 10.
5. Update the usage text in --help to list every check name, and extend scripts/test_healthcheck.sh with one assertion per check plus an assertion that all ten names appear in the output.
Verification for this phase is automated only. The one check is:
## Work one phase at a time
- run: ["bash", "-n", "scripts/orchestra_e2e_selftest.sh"]
This is a hard requirement. Implement phase N, request its verification, and only then begin phase N+1. Do not write the whole change first and verify the phases afterwards.
Do not add a manual step to this phase.
## Behaviour that must not change
## Phase 2 — `--json` on the healthcheck
The existing success line, the --quiet, --json and --help flags, and the exit status all keep their current behaviour when every check passes.
`scripts/orchestra_e2e_healthcheck.sh --json` prints exactly one line:
## Verification policy for this project
{"status":"ok","checks":1}
Only two commands may appear on a run: line, exactly:
and exits 0. Without `--json` the existing human output is unchanged, and `--help` keeps working. `--json` and `--help` together behave as `--help`.
- ["bash", "-n", "<path>"]
- ["bash", "scripts/orchestra_e2e_healthcheck.sh"]
Verification for this phase must include both an automated check and a manual step. The JSON shape is a judgement a human confirms by reading it, so state the manual step as the exact command a human runs and the exact line they should see.
## Phase 3 — teach the self-test about `--json`
Extend `scripts/orchestra_e2e_selftest.sh` to run the healthcheck twice: once plain and once with `--json`. Assert the plain run still contains `OK`, and assert the `--json` run prints one line beginning with `{"status":`.
Verification for this phase is automated only:
- run: ["bash", "-n", "scripts/orchestra_e2e_selftest.sh"]
- run: ["bash", "scripts/orchestra_e2e_healthcheck.sh"]
## Constraints
The project's verification policy allows exactly two command shapes:
["bash", "-n", "<one file>"]
["bash", "scripts/orchestra_e2e_healthcheck.sh"]
A `run:` line outside those is refused when the plan seals, not later.
Anything else is refused when you seal the plan. Give every phase at least one automated check from that list, and add a manual check where a human should confirm the printed text.
## Research first
Before planning, establish at least three findings and label their confidence honestly: at least one `fact`, one `inference`, and one `assumption`. The plan must cite at least two of them in References.
Establish at least three findings with distinct confidence: at least one fact, one inference, one assumption.
## Handoff behaviour
Behave normally throughout this task. If Orchestra asks you to write a handoff report, write it and stop.
## Quality gate
bash -n scripts/*.sh && bash scripts/orchestra_e2e_healthcheck.sh
## Completion
+108 -7
View File
@@ -1,14 +1,94 @@
#!/usr/bin/env bash
readonly VERSION=1.0.0
readonly ROOT=$(cd "$(dirname "$0")/.." && pwd)
# Space-separated check names; each has a check_<name> function.
CHECKS="repo_root_readable scripts_dir_present healthcheck_executable_bit
selftest_present test_healthcheck_present readme_present
no_crlf_line_endings no_tabs_in_scripts
shebang_is_bash usage_text_mentions_every_flag"
# name=ok / name=fail pairs, in run order.
RESULTS=
FAILED=0
TOTAL=0
# record <name> <status>: append one outcome to the results state.
record() {
RESULTS="$RESULTS $1=$2"
TOTAL=$((TOTAL + 1))
[ "$2" = ok ] || FAILED=$((FAILED + 1))
}
check_repo_root_readable() { [ -d "$ROOT" ] && [ -r "$ROOT" ]; }
check_scripts_dir_present() { [ -d "$ROOT/scripts" ]; }
check_healthcheck_executable_bit() { [ -x "$ROOT/scripts/orchestra_e2e_healthcheck.sh" ]; }
check_selftest_present() { [ -f "$ROOT/scripts/orchestra_e2e_selftest.sh" ]; }
check_test_healthcheck_present() { [ -f "$ROOT/scripts/test_healthcheck.sh" ]; }
check_readme_present() { [ -f "$ROOT/README.md" ]; }
check_no_crlf_line_endings() {
[ -d "$ROOT/scripts" ] || return 1
! grep -qU $'\r' "$ROOT"/scripts/*.sh "$ROOT/README.md" 2>/dev/null
}
check_no_tabs_in_scripts() {
[ -d "$ROOT/scripts" ] || return 1
! grep -q "$(printf '\t')" "$ROOT"/scripts/*.sh 2>/dev/null
}
check_shebang_is_bash() {
[ -d "$ROOT/scripts" ] || return 1
local f
for f in "$ROOT"/scripts/*.sh; do
[ "$(head -n 1 "$f")" = '#!/usr/bin/env bash' ] || return 1
done
}
check_usage_text_mentions_every_flag() {
local text flag
text=$(usage text)
for flag in --quiet --json --help; do
case "$text" in
*"$flag"*) ;;
*) return 1 ;;
esac
done
}
# emit <format> <template> [args...]: the single output path.
# format: text or json print; none suppresses (--quiet). Explicit argument,
# never read from an enclosing variable.
emit() {
local format=$1
shift
[ "$format" = none ] || printf "$@"
}
# usage <format>: the --help body. Also the source check_usage_text_mentions_every_flag
# reads, so the flag list has exactly one home.
usage() {
emit "$1" 'Usage: %s [--quiet]\n\n' "${0##*/}"
emit "$1" 'Healthcheck script for Orchestra E2E tests.\n'
emit "$1" 'Exits 0 with a success message if all checks pass.\n'
emit "$1" ' --quiet Suppress the success message; still exits 0.\n'
emit "$1" ' --json Print a single-line JSON result; still exits 0.\n'
emit "$1" ' --help Print this usage text and exit 0.\n'
emit "$1" '\nChecks:\n'
local name
for name in $CHECKS; do
emit "$1" ' %s\n' "$name"
done
emit "$1" '\nVersion: %s\n' "$VERSION"
}
main() {
local quiet=
local json=
for arg in "$@"; do
if [ "$arg" = --help ]; then
printf 'Usage: %s [--quiet]\n\n' "${0##*/}"
printf 'Healthcheck script for Orchestra E2E tests.\n'
printf 'Exits 0 with a success message if all checks pass.\n'
printf ' --quiet Suppress the success message; still exits 0.\n'
usage text
exit 0
elif [ "$arg" = --quiet ]; then
quiet=1
@@ -17,12 +97,33 @@ main() {
fi
done
if [ -n "$json" ]; then
printf '{"status":"ok","checks":1}\n'
local name
for name in $CHECKS; do
if "check_$name"; then
record "$name" ok
else
record "$name" fail
fi
done
local format=text
[ -n "$quiet" ] && format=none
[ -n "$json" ] && format=json
if [ "$FAILED" -gt 0 ]; then
local entry
for entry in $RESULTS; do
[ "${entry#*=}" = fail ] && emit "$format" 'FAIL - %s\n' "${entry%=*}"
done
exit 1
fi
if [ "$format" = json ]; then
emit "$format" '{"status":"ok","checks":%d}\n' "$TOTAL"
exit 0
fi
[ -n "$quiet" ] || printf 'OK - all healthchecks passed\n'
emit "$format" 'OK - all healthchecks passed\n'
exit 0
}
+32 -1
View File
@@ -3,7 +3,11 @@
HC="$(dirname "$0")/orchestra_e2e_healthcheck.sh"
OK='OK - all healthchecks passed'
USAGE="$(printf 'Usage: orchestra_e2e_healthcheck.sh [--quiet]\n\nHealthcheck script for Orchestra E2E tests.\nExits 0 with a success message if all checks pass.\n --quiet Suppress the success message; still exits 0.')"
NAMES='repo_root_readable scripts_dir_present healthcheck_executable_bit
selftest_present test_healthcheck_present readme_present
no_crlf_line_endings no_tabs_in_scripts
shebang_is_bash usage_text_mentions_every_flag'
USAGE="$(printf 'Usage: orchestra_e2e_healthcheck.sh [--quiet]\n\nHealthcheck script for Orchestra E2E tests.\nExits 0 with a success message if all checks pass.\n --quiet Suppress the success message; still exits 0.\n --json Print a single-line JSON result; still exits 0.\n --help Print this usage text and exit 0.\n\nChecks:\n repo_root_readable\n scripts_dir_present\n healthcheck_executable_bit\n selftest_present\n test_healthcheck_present\n readme_present\n no_crlf_line_endings\n no_tabs_in_scripts\n shebang_is_bash\n usage_text_mentions_every_flag\n\nVersion: 1.0.0')"
fails=0
check() { # check <expected-stdout> <label> [args...]
@@ -17,6 +21,18 @@ check() { # check <expected-stdout> <label> [args...]
fi
}
contains() { # contains <needle> <label> [args...]
local want=$1 label=$2 got status
shift 2
got=$(bash "$HC" "$@" 2>/dev/null)
status=$?
if [ "$status" -ne 0 ] || [ "${got#*"$want"}" = "$got" ]; then
printf 'FAIL: %s (exit=%s)\n---missing---\n%s\n---in---\n%s\n' \
"$label" "$status" "$want" "$got"
fails=$((fails + 1))
fi
}
check "$OK" 'no args'
check '' '--quiet' --quiet
check "$USAGE" '--help' --help
@@ -24,5 +40,20 @@ check "$USAGE" '--help --quiet' --help --quiet
check "$USAGE" '--quiet --help' --quiet --help
check "$OK" 'unknown flag ignored' --bogus
for name in $NAMES; do
contains "$name" "--help names $name" --help
done
# All ten names in one run's output.
help_out=$(bash "$HC" --help 2>/dev/null)
missing=
for name in $NAMES; do
[ "${help_out#*"$name"}" = "$help_out" ] && missing="$missing $name"
done
if [ -n "$missing" ]; then
printf 'FAIL: --help lists all ten check names\n---missing---\n%s\n' "$missing"
fails=$((fails + 1))
fi
[ "$fails" -eq 0 ] || exit 1
printf 'all checks passed\n'