WUT_Computer_Science/install.sh
Krzysztof kuhy Rudnicki 7515bd0dc2 Add CI, install.sh and the run.sh harness
Two workflows, one per gate, each checking out kuhyx/utils into .utils and
calling the shared script -- the pattern every other repo here uses.
pre-commit.yml sets UTILS_ROOT to that checkout, without which the shims fail
with "shared gate not found", and both use fetch-depth 1 because the history
is ~494 MB and no gate reads it.

install.sh ends by verifying and exits non-zero if the gate cannot run; a
warning there would just recreate the bug it exists to prevent, since this
repo had no hooks at all until now. Confirmed both ways: --check exited 1
while the hooks were missing, then 0 once installed.

run.sh separates `status` (probe, seconds, safe in CI) from `run <dir>`
(actually executes one project). Conflating them is not hypothetical -- the
first version of the probe did exactly that and it cost 120 seconds and a
scare. Some course dirs already ship a run.sh from years ago, and
Programming/PSD/run.sh installs packages with sudo and starts Kafka; calling
it with an unknown --probe flag does not probe anything, it runs the project.
It blocked on a sudo prompt rather than installing (verified against
/var/log/pacman.log and the absence of a yay clone), but only by luck.

So probe_one now invokes a runner ONLY if it declares --probe, wraps it in
`timeout 20s` as defence in depth, and reports anything else as unprobed
without touching it. All 44 directories now probe instantly.

DOCS-runnability.md is generated with a per-environment column. Recording one
global status would make the CI check red by construction, since `runnable`
locally and `blocked` on ubuntu-latest is the normal case for the MATLAB,
Unity and .NET directories rather than a drift signal.

Per-directory run.sh files are the next step; all 44 currently read unprobed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0172dj34FDpao6wsix8ZuCzE
2026-08-28 18:26:10 +02:00

115 lines
3.3 KiB
Bash
Executable File

#!/bin/bash
# ============================================================================
# Set this repository up for development.
#
# Usage:
# ./install.sh install tools and wire the git hooks
# ./install.sh --check verify only; exit 1 if anything is missing
#
# Idempotent: a second run reports what is already present and changes nothing.
#
# It ENDS by verifying, and fails loudly if the gate is not actually runnable.
# A warning here would just recreate the bug it exists to prevent: the hooks
# were absent from this repo entirely, so every "pre-commit passed" claim
# before now was vacuous.
# ============================================================================
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly SCRIPT_DIR
readonly UTILS_ROOT="${UTILS_ROOT:-$HOME/utils}"
CHECK_ONLY=0
log() { printf '==> %s\n' "$*"; }
err() { printf 'error: %s\n' "$*" >&2; }
usage() {
grep -E '^# \./install\.sh' "${BASH_SOURCE[0]}" | sed 's/^# //'
exit 0
}
# The shared gates are not vendored here on purpose -- they live in one repo so
# that every repo enforces the same rule. Without them the hooks cannot run.
check_shared_gates() {
if [[ ! -d "$UTILS_ROOT" ]]; then
err "shared gates not found at $UTILS_ROOT"
err " git clone https://github.com/kuhyx/utils \"$UTILS_ROOT\""
err " (or set UTILS_ROOT to where it lives)"
return 1
fi
log "shared gates: $UTILS_ROOT"
}
install_tools() {
local missing=()
command -v shellcheck > /dev/null 2>&1 || missing+=(shellcheck)
command -v pre-commit > /dev/null 2>&1 || missing+=(pre-commit)
if [[ ${#missing[@]} -eq 0 ]]; then
log "tools already present: shellcheck, pre-commit"
return 0
fi
if [[ $CHECK_ONLY -eq 1 ]]; then
err "missing tools: ${missing[*]}"
return 1
fi
log "installing: ${missing[*]}"
if command -v pacman > /dev/null 2>&1; then
sudo pacman -S --needed --noconfirm "${missing[@]}"
elif command -v apt-get > /dev/null 2>&1; then
sudo apt-get update -qq && sudo apt-get install -y -qq "${missing[@]}"
else
err "no supported package manager; install manually: ${missing[*]}"
return 1
fi
}
install_hooks() {
if [[ $CHECK_ONLY -eq 1 ]]; then
[[ -f "${SCRIPT_DIR}/.git/hooks/pre-commit" ]] || {
err "git hooks are not installed"
return 1
}
log "git hooks installed"
return 0
fi
log "wiring git hooks (pre-commit and pre-push)"
( cd "$SCRIPT_DIR" \
&& pre-commit install > /dev/null \
&& pre-commit install --hook-type pre-push > /dev/null )
}
# The last word. If the gate cannot actually run, say so and exit non-zero.
verify() {
log "verifying the gate runs"
if ! ( cd "$SCRIPT_DIR" && pre-commit run --all-files > /dev/null 2>&1 ); then
err "pre-commit run --all-files failed -- the repo is not clean"
err "run it directly to see why: pre-commit run --all-files"
return 1
fi
log "OK: all hooks pass"
}
main() {
check_shared_gates
install_tools
install_hooks
verify
}
while [[ $# -gt 0 ]]; do
case $1 in
--check) CHECK_ONLY=1; shift ;;
-h | --help) usage ;;
*) err "unknown option: $1"; exit 1 ;;
esac
done
main "$@"