#!/usr/bin/env bash # Weekly paper-library harvest. # # Deliberately thin: it calls the API and reports what came back. All the # logic lives in the server, so this file never needs to change when the # harvest does. # # The token lives in /etc/clawmates/library.token (root-only). It is a # long-lived operator session; rotate by replacing the file. set -uo pipefail TOKEN_FILE=/etc/clawmates/library.token [ -r "$TOKEN_FILE" ] || { echo "library: no token at $TOKEN_FILE"; exit 1; } TOKEN=$(cat "$TOKEN_FILE") RESP=$(docker run --rm --network clawmates_core curlimages/curl:latest \ -s -m 1800 -X POST \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"per_topic":5}' \ http://clawmates_server_1:8080/api/library/runs) echo "library: $RESP" | head -c 2000 # Report health explicitly. A run that shelved nothing is normal for a # mature library; a run that ERRORED is not, and the two look identical # if you only count papers. echo "$RESP" | python3 -c ' import json, sys try: d = json.load(sys.stdin) except Exception as e: print("library: unreadable response (%s)" % e) sys.exit(1) shelved = len(d.get("shelved", [])) healthy = d.get("healthy", False) # Backslashes are avoided inside this program on purpose: it is embedded in a # single-quoted shell string, and an escaped quote here does not survive the # shell. The first version used one inside an f-string, crashed on every run, # and systemd reported a FAILED unit for a harvest that had actually shelved # 15 papers and pushed them. A false failure destroys trust in the signal as # surely as a false success. print("library: %d candidates, %d already held, %d shelved, healthy=%s, pushed=%s, branch=%s" % ( d.get("candidates", 0), d.get("already_had", 0), shelved, healthy, d.get("pushed"), d.get("branch"))) for f in d.get("failed", []): print("library: FAILED %s" % f) sys.exit(0 if healthy else 1) '