Skip to content

Relevance — daily 3-day check-in #80

Relevance — daily 3-day check-in

Relevance — daily 3-day check-in #80

name: Relevance — daily 3-day check-in
# Asks each event's owner once a day whether their 3-day-old report is still
# relevant (push + queues the in-app modal). Same App Service constraint as
# cluster-daily.yml: the student tier has no Always On, so we can't rely on
# the in-process PeriodicTimer. This workflow guarantees one trigger per day.
#
# Re-uses the existing CLUSTERING_ADMIN_TOKEN secret. Both admin endpoints
# (clustering + relevance) validate against the same server-side Admin:Token
# config key, so a single token covers both.
on:
schedule:
# 07:00 UTC = 10:00 Israel summer / 09:00 winter. Picked so the push
# lands at a reasonable local time, not in the middle of the night.
- cron: "0 7 * * *"
workflow_dispatch:
permissions:
contents: read
jobs:
notify:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Wake & run relevance check
env:
API_BASE: https://app-groundshare-api.azurewebsites.net
ADMIN_TOKEN: ${{ secrets.CLUSTERING_ADMIN_TOKEN }}
POLL_TIMEOUT: "180"
POLL_INTERVAL: "10"
run: |
set -euo pipefail
if [ -z "${ADMIN_TOKEN}" ]; then
echo "::error::CLUSTERING_ADMIN_TOKEN secret is not set."
exit 1
fi
json_field() { python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('$1') or '')"; }
# 1. Wake the App Service (student tier sleeps on idle).
echo "Pinging relevance diagnostics to warm the App Service..."
for attempt in 1 2 3; do
if curl -fsS --max-time 60 "${API_BASE}/api/relevance/diagnostics" >/tmp/diag.json; then
cat /tmp/diag.json; echo
break
fi
echo "Attempt ${attempt} failed, retrying..."
sleep 15
done
before=$(json_field lastRunUtc </tmp/diag.json)
echo "lastRunUtc before run: '${before}'"
# 2. Kick off the relevance run. Fire-and-forget: returns 202 immediately.
echo "Triggering /run-now..."
http_code=$(curl -sS -o /tmp/run.json -w "%{http_code}" \
--max-time 60 \
-X POST \
-H "X-Admin-Token: ${ADMIN_TOKEN}" \
"${API_BASE}/api/relevance/run-now")
echo "HTTP ${http_code}"
cat /tmp/run.json; echo
# 202 Accepted is the success path; tolerate 200 during the deploy window.
if [ "${http_code}" != "202" ] && [ "${http_code}" != "200" ]; then
echo "::error::Relevance run-now trigger failed with HTTP ${http_code}"
exit 1
fi
# 3. Poll diagnostics until lastRunUtc advances past 'before'.
echo "Polling for completion (timeout ${POLL_TIMEOUT}s)..."
deadline=$(( $(date +%s) + POLL_TIMEOUT ))
while :; do
if curl -fsS --max-time 30 "${API_BASE}/api/relevance/diagnostics" >/tmp/diag.json; then
after=$(json_field lastRunUtc </tmp/diag.json)
if [ -n "${after}" ] && [ "${after}" != "${before}" ]; then
echo "Relevance run complete. lastRunUtc now: '${after}'"
cat /tmp/diag.json; echo
exit 0
fi
echo " still running (lastRunUtc='${after}')..."
else
echo " diagnostics ping failed, will retry..."
fi
if [ "$(date +%s)" -ge "${deadline}" ]; then
echo "::error::Relevance run did not complete within ${POLL_TIMEOUT}s"
cat /tmp/diag.json 2>/dev/null || true
exit 1
fi
sleep "${POLL_INTERVAL}"
done