Skip to content

signed-in-health

signed-in-health #1688

# Hand-maintained (NOT generated by Upptime; update-template leaves it alone).
#
# Signed-in dashboard health. The checker's rows prove the sign-in page, the
# docs, and the API answer; none of them holds a session. On 2026-09-22
# 22:55-23:20Z every SIGNED-IN page of platform.experientiallabs.ai
# intermittently 502'd (an nginx TLS sidecar in the web pods rejected Next.js
# responses whose Set-Cookie carried the chunked Supabase session cookies)
# while this page stayed green. This workflow runs scripts/signed-in-probe.mjs
# every 5 minutes: a dedicated monitor account (status-dashboard-monitor@,
# its own personal org, no credits) signs in with the password grant, presents
# the session as the browser cookies do, loads /overview through the public
# hostname, then repeats with an expired token so the proxy refreshes the
# session and writes the chunked Set-Cookie response. See the script header
# for the verdict rules; the JSON lands in assets/status-ui/signed-in-health.json
# and the status-ui overlay renders it as the "Dashboard (signed in)" row.
#
# Incidents: a non-ok verdict opens ONE issue labelled `status` + `dashboard`
# with Upptime's title shape ("🟥 Dashboard (signed in) is down" /
# "⚠️ Dashboard (signed in) has degraded performance"), so the page's Past
# Incidents, the 90-day bars of the injected row, the Atom feed, and
# slack-mention.yml (owner @mention on down, recovery line on close) all pick
# it up through the paths they already have. Recovery closes it. The issue is
# opened with GH_PAT on purpose: issues created by github.token do not fire the
# `issues` event slack-mention.yml listens to. An `unknown` verdict (the monitor
# itself could not sign in for a client-side reason) never touches issues; the
# run fails red instead so the owner sees it.
name: Signed-in Health
on:
# Fallback only: GitHub runs this cron when it has capacity (about every two
# hours on this repo). The Vercel cron (vercel/api/cron/signed-in.js) fires
# the repository_dispatch every 5 minutes, three minutes after the checker.
schedule:
- cron: "*/5 * * * *"
repository_dispatch:
types: [signed-in-health]
workflow_dispatch:
# Upptime's group: this workflow pushes to main, so it must serialize with the
# checker (README "Anything that pushes to main must share Upptime's
# concurrency group"). Never cancel-in-progress here.
concurrency:
group: ${{ github.repository }}-${{ github.head_ref || github.ref_name }}-upptime
cancel-in-progress: false
permissions:
contents: write
issues: write
jobs:
probe:
name: Render the signed-in dashboard
runs-on: ubuntu-latest
timeout-minutes: 8
steps:
- name: Checkout
uses: actions/checkout@v6
with:
token: ${{ secrets.GH_PAT || github.token }}
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: "22"
- name: Sign in and render /overview
id: probe
env:
STATUS_SUPABASE_URL: ${{ secrets.STATUS_SUPABASE_URL }}
STATUS_SUPABASE_ANON_KEY: ${{ secrets.STATUS_SUPABASE_ANON_KEY }}
STATUS_MONITOR_EMAIL: ${{ secrets.STATUS_MONITOR_EMAIL }}
STATUS_MONITOR_PASSWORD: ${{ secrets.STATUS_MONITOR_PASSWORD }}
run: node scripts/signed-in-probe.mjs --out assets/status-ui/signed-in-health.json
- name: Commit if changed
run: |
git config user.name "Upptime Bot"
git config user.email "73812536+upptime-bot@users.noreply.github.com"
git add assets/status-ui/signed-in-health.json
git diff --cached --quiet && { echo "No change."; exit 0; }
git commit -m ":stethoscope: Refresh signed-in dashboard health [skip ci]"
# Upptime's own bots commit to main every few minutes; rebase over
# whatever landed while this job ran instead of failing the push.
for _ in 1 2 3; do
git push && exit 0
git pull --rebase --autostash && continue
done
exit 1
- name: Open, hold, or close the incident
env:
GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
VERDICT: ${{ steps.probe.outputs.verdict }}
REASON: ${{ steps.probe.outputs.reason }}
REPO: ${{ github.repository }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
set -euo pipefail
name="Dashboard (signed in)"
open_issue=$(gh issue list --repo "$REPO" --label status --label dashboard --state open --json number --jq '.[0].number // empty')
case "$VERDICT" in
down|degraded)
if [ "$VERDICT" = down ]; then
title="🟥 $name is down"
else
title="⚠️ $name has degraded performance"
fi
if [ -z "$open_issue" ]; then
gh label create dashboard --repo "$REPO" --color 0e8a16 \
--description "Signed-in dashboard check (signed-in-health workflow)" 2>/dev/null || true
gh issue create --repo "$REPO" --label status --label dashboard --assignee SilenNaihin \
--title "$title" \
--body "$(printf '%s\n\nSource: the signed-in dashboard check (a monitor account renders %s through the public hostname, including the session-refresh path that writes chunked Set-Cookie headers).\nVerdict: **%s**\n\nThis issue closes automatically when the next check renders the page cleanly. Run: %s' \
"$REASON" "https://platform.experientiallabs.ai/overview" "$VERDICT" "$RUN_URL")"
else
gh issue comment "$open_issue" --repo "$REPO" --body "Still **$VERDICT**: $REASON ($RUN_URL)"
fi
;;
ok)
if [ -n "$open_issue" ]; then
gh issue close "$open_issue" --repo "$REPO" \
--comment "Recovered: the signed-in dashboard renders again, including the session-refresh path ($RUN_URL)."
fi
;;
unknown)
echo "::error::The monitor could not sign in: $REASON. Check STATUS_MONITOR_EMAIL / STATUS_MONITOR_PASSWORD / STATUS_SUPABASE_*; no incident opened."
exit 1
;;
*)
echo "::error::Unexpected verdict '$VERDICT'"
exit 1
;;
esac