Files
werkrevisor/tools/dry-run
claude-code 0349323c85
werkator build succeeded after 00:10
werkator/werkrevisor-statistics build succeeded after 00:30
werkator/release build succeeded after 00:35
werkrevisor 0.57.0: hs-review puts the diagrams of PR Lens next to its draft (#129)
Co-authored-by: claude-code <claude-code@javagil.de>
2026-10-21 07:32:04 +02:00

73 lines
4.1 KiB
Bash
Executable File

#!/usr/bin/env bash
# Usage: tools/dry-run [-h] <pr-url> [config] [--llm | --prompt-out build/<file>]
#
# Reviews a real Gitea PR without writing to Gitea (--no-publish), also a merged or closed one.
# Without --llm it applies the deterministic rules only (--no-llm) and needs no OpenRouter key.
# With --llm it calls the model and costs money.
# With --prompt-out it writes the prompt the model would get to that file under build/, as JSON, and calls no model;
# Jev and the excerpt selection still run, so it needs the same keys as --llm.
# Needs GITEA_BOT_TOKEN (read access is enough) and, with --llm, OPENROUTER_API_KEY in the environment;
# with --llm and an [engine] mode other than "llm" also TYPESAFE_API_KEY.
# The default config is config/hsadmin-ng.toml; a set WERKREVISOR_CONFIG_TOML wins over it.
# It runs with docker, else podman; CONTAINER_ENGINE overrides the choice.
# Usage lines are appended to build/werkrevisor/usage.jsonl for later measurement.
# With WERKREVISOR_STATS_URL and WERKREVISOR_STATS_TOKEN set, the run reports its usage record as a local review.
# With --llm and WERKREVISOR_DIAGRAMS_OUT set to a directory under build/, it writes the diagrams of [diagrams] there;
# it then runs in the stage base of the Dockerfile, with Node.js and PR Lens, and builds it once if it is missing.
#
# Example:
# tools/dry-run https://git.example.org/owner/repo/pulls/302
set -euo pipefail
if [[ $# -lt 1 || "$1" =~ ^(-h|-\?|--help)$ ]]; then
awk 'NR > 1 && /^#/ { sub(/^# ?/, ""); print; next } NR > 1 { exit }' "$0"
exit 0
fi
image="docker.io/pragent/pr-agent@sha256:7d98954c29289846a08faf00aaea0f1f1375b1676cd8a2ed303e0af07010af7a"
container_engine="${CONTAINER_ENGINE:-$(command -v docker || command -v podman || true)}"
[[ -n "$container_engine" ]] || { echo "tools/dry-run: neither docker nor podman found; set CONTAINER_ENGINE" >&2; exit 2; }
pr_url="$1"
config="${2:-config/hsadmin-ng.toml}"
: "${GITEA_BOT_TOKEN:?GITEA_BOT_TOKEN must be set}"
# Secrets are passed by name, so their values never appear in the process list.
docker_env=(-e GITEA_BOT_TOKEN)
# An inline operator config wins over the config file argument, as in production.
[[ -n "${WERKREVISOR_CONFIG_TOML:-}" ]] && docker_env+=(-e WERKREVISOR_CONFIG_TOML)
[[ -n "${WERKREVISOR_STATS_URL:-}" && -n "${WERKREVISOR_STATS_TOKEN:-}" ]] && docker_env+=(-e WERKREVISOR_STATS_URL -e WERKREVISOR_STATS_TOKEN)
werkrevisor_args=(--no-llm)
if [[ "${3:-}" == "--prompt-out" ]]; then
[[ "${4:-}" == build/?* && "/$4/" != */../* ]] \
|| { echo "tools/dry-run: --prompt-out needs a file under build/, without .." >&2; exit 2; }
mkdir -p "$(dirname "$4")"
fi
if [[ "${3:-}" == "--llm" || "${3:-}" == "--prompt-out" ]]; then
: "${OPENROUTER_API_KEY:?OPENROUTER_API_KEY must be set for --llm and --prompt-out}"
docker_env+=(-e OPENROUTER_API_KEY)
[[ -n "${TYPESAFE_API_KEY:-}" ]] && docker_env+=(-e TYPESAFE_API_KEY)
werkrevisor_args=()
[[ "${3:-}" == "--prompt-out" ]] && werkrevisor_args=(--prompt-out "/work/$4")
fi
if [[ -n "${WERKREVISOR_DIAGRAMS_OUT:-}" && "${3:-}" == "--llm" ]]; then
[[ "$WERKREVISOR_DIAGRAMS_OUT" == build/?* && "/$WERKREVISOR_DIAGRAMS_OUT/" != */../* ]] \
|| { echo "tools/dry-run: WERKREVISOR_DIAGRAMS_OUT needs a directory under build/, without .." >&2; exit 2; }
mkdir -p "$WERKREVISOR_DIAGRAMS_OUT"
werkrevisor_args+=(--diagrams-out "/work/$WERKREVISOR_DIAGRAMS_OUT")
base=$(python3 tools/release_rootfs.py base-name)
image="localhost/werkrevisor-base:${base#werkrevisor-base-}"
image="${image%.tar.zst}"
if ! "$container_engine" image inspect "$image" >/dev/null 2>&1; then
echo "tools/dry-run: building $image once, for the diagrams" >&2
"$container_engine" build -q --target base -t "$image" . >&2
fi
fi
mkdir -p build/werkrevisor
"$container_engine" run --rm \
-v "$PWD":/werkrevisor:ro -v "$PWD/build":/work/build -w /work \
-e PYTHONPATH=/werkrevisor:/app -e PYTHONDONTWRITEBYTECODE=1 -e PYTHONNOUSERSITE=1 \
"${docker_env[@]}" \
--entrypoint python "$image" \
-s -m werkrevisor --config "/werkrevisor/$config" --pr-url "$pr_url" --no-publish --allow-closed "${werkrevisor_args[@]}"