chore: remove uptime monitoring from main repo (#82)

Monitoring moved to a dedicated Upptime repo at StarTrail-org/status.
The old setup with a `status` branch in this repo didn't work because
Upptime's summary generator queries the default branch for commit
history, not the data branch.

Removes: uptime workflows, .upptimerc.yml, status-site/.
Keeps: web/lib/uptime.ts (may be repointed to the new repo later).
This commit is contained in:
Zhifei Li
2026-06-23 18:19:16 +08:00
committed by GitHub
parent 8d5c607f9e
commit 13d53c1250
8 changed files with 0 additions and 375 deletions
-24
View File
@@ -1,24 +0,0 @@
name: Status Site CI
on:
push:
branches: [main]
paths:
- "status-site/**"
- ".github/workflows/status-site.yml"
workflow_dispatch:
permissions:
contents: write
pages: write
jobs:
deploy:
name: Deploy static status page
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Deploy to gh-pages
uses: JamesIves/github-pages-deploy-action@v4
with:
branch: gh-pages
folder: ./status-site
clean: true
@@ -1,24 +0,0 @@
name: Response Time CI
on:
schedule:
- cron: "0 23 * * *"
workflow_dispatch:
permissions:
contents: write
jobs:
response-time:
name: Check response time
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
with:
ref: status
token: ${{ secrets.GH_PAT || github.token }}
- name: Update response time
uses: upptime/uptime-monitor@v1.41.8
with:
command: "response-time"
env:
GH_PAT: ${{ secrets.GH_PAT || github.token }}
SECRETS_CONTEXT: ${{ toJson(secrets) }}
-25
View File
@@ -1,25 +0,0 @@
name: Summary CI
on:
schedule:
# Every 10 min so history/summary.json (the data source for the static
# status page) stays near-real-time, not just daily.
- cron: "*/10 * * * *"
workflow_dispatch:
permissions:
contents: write
jobs:
summary:
name: Generate summary
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
with:
ref: status
token: ${{ secrets.GH_PAT || github.token }}
- name: Update summary
uses: upptime/uptime-monitor@v1.41.8
with:
command: "readme"
env:
GH_PAT: ${{ secrets.GH_PAT || github.token }}
-24
View File
@@ -1,24 +0,0 @@
name: Uptime CI
on:
schedule:
- cron: "*/5 * * * *"
workflow_dispatch:
permissions:
contents: write
jobs:
uptime:
name: Check status
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
with:
ref: status
token: ${{ secrets.GH_PAT || github.token }}
- name: Check endpoint status
uses: upptime/uptime-monitor@v1.41.8
with:
command: "update"
env:
GH_PAT: ${{ secrets.GH_PAT || github.token }}
SECRETS_CONTEXT: ${{ toJson(secrets) }}
-20
View File
@@ -1,20 +0,0 @@
owner: StarTrail-org
repo: PixelRAG
# Checks run by GitHub Actions every 5 min; results committed to history/.
# The status page (status-site/, deployed to status.pixelrag.ai) reads the
# generated history/summary.json — we don't use Upptime's own site builder.
sites:
- name: API Health
url: http://api.pixelrag.ai:30001/health
- name: Search API
url: http://api.pixelrag.ai:30001/status
- name: Tile Serving
url: http://api.pixelrag.ai:30001/tile/0/0/0
expectedStatusCodes:
- 200
- 404
- name: Agent
url: http://api.pixelrag.ai:30010/health
- name: Website
url: https://pixelrag.ai
-1
View File
@@ -1 +0,0 @@
status.pixelrag.ai
-227
View File
@@ -1,227 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>PixelRAG Status</title>
<meta name="description" content="Live availability of the PixelRAG search API, tile serving, agent backend, and website.">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Crimson+Pro:ital,wght@0,300;0,400;0,500;1,400&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<style>
:root {
--bg: #faf9f7; --fg: #1a1816; --muted: #8a8078; --secondary: #3a3530;
--card: #ffffff; --border: #e8e2da; --accent: #8b6943;
--up: #5a8a5a; --down: #c44040; --degraded: #c08a3a;
--serif: "Crimson Pro", Georgia, serif;
--sans: "Inter", system-ui, sans-serif;
--mono: "JetBrains Mono", ui-monospace, monospace;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: var(--bg); color: var(--fg); font-family: var(--sans);
font-size: 14px; line-height: 1.6; min-height: 100vh;
position: relative; -webkit-font-smoothing: antialiased;
}
body::before {
content: ''; position: fixed; inset: 0; z-index: -2; pointer-events: none;
background:
radial-gradient(ellipse 80% 60% at 15% 0%, rgba(139,105,67,0.06), transparent 55%),
radial-gradient(ellipse 70% 50% at 85% 5%, rgba(150,170,140,0.05), transparent 50%);
}
body::after {
content: ''; position: fixed; inset: 0; z-index: -1; pointer-events: none; opacity: 0.4;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='256' height='256' filter='url(%23n)' opacity='0.04'/%3E%3C/svg%3E");
background-size: 200px 200px;
}
nav {
position: sticky; top: 0; z-index: 50; backdrop-filter: blur(12px);
background: rgba(250,249,247,0.7); border-bottom: 1px solid var(--border);
}
nav .inner {
max-width: 880px; margin: 0 auto; height: 64px; padding: 0 24px;
display: flex; align-items: center; justify-content: space-between;
}
.logo { display: flex; align-items: center; gap: 10px; text-decoration: none; color: var(--fg); }
.logo-mark {
position: relative; width: 28px; height: 28px;
display: flex; align-items: center; justify-content: center;
}
.logo-mark span:nth-child(1) { position: absolute; inset: 0; border-radius: 7px; background: rgba(139,105,67,0.15); }
.logo-mark span:nth-child(2) { position: absolute; inset: 3px; border-radius: 5px; border: 1px solid rgba(139,105,67,0.4); }
.logo-mark span:nth-child(3) { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
.logo-name { font-family: var(--serif); font-size: 20px; font-weight: 600; letter-spacing: -0.01em; }
.logo-name b { color: var(--accent); font-weight: 600; }
.nav-links { display: flex; gap: 24px; }
.nav-links a { color: var(--muted); text-decoration: none; font-size: 14px; transition: color .2s; }
.nav-links a:hover { color: var(--fg); }
main { max-width: 880px; margin: 0 auto; padding: 56px 24px 80px; }
.head { text-align: center; margin-bottom: 40px; }
.pill {
display: inline-flex; align-items: center; gap: 8px; font-family: var(--mono);
font-size: 10px; text-transform: uppercase; letter-spacing: 0.18em;
border: 1px solid var(--border); border-radius: 999px; padding: 6px 16px;
color: var(--muted); margin-bottom: 20px; background: rgba(255,255,255,0.5);
}
.dot { width: 8px; height: 8px; border-radius: 50%; position: relative; }
.dot.up { background: var(--up); }
.dot.down { background: var(--down); }
.dot.degraded { background: var(--degraded); }
.dot.up::after {
content: ''; position: absolute; inset: 0; border-radius: 50%;
background: var(--up); animation: ping 2s cubic-bezier(0,0,.2,1) infinite;
}
@keyframes ping { 75%,100% { transform: scale(2.4); opacity: 0; } }
h1 { font-family: var(--serif); font-weight: 300; font-size: 44px; line-height: 1.1; letter-spacing: -0.02em; }
.sub { color: var(--muted); margin-top: 12px; font-size: 15px; }
.banner {
display: flex; align-items: center; gap: 12px; justify-content: center;
border: 1px solid var(--border); border-radius: 16px; padding: 18px 24px;
background: var(--card); margin-bottom: 36px; font-size: 16px; font-weight: 500;
}
.banner .dot { width: 10px; height: 10px; }
.banner.up { border-color: rgba(90,138,90,0.3); }
.banner.down { border-color: rgba(196,64,64,0.3); }
.banner.degraded { border-color: rgba(192,138,58,0.3); }
.services { display: flex; flex-direction: column; gap: 14px; }
.service {
border: 1px solid var(--border); border-radius: 16px; padding: 20px 22px; background: var(--card);
}
.service-top { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; }
.service-name { font-family: var(--serif); font-size: 19px; font-weight: 500; }
.service-status { margin-left: auto; display: flex; align-items: center; gap: 7px; font-size: 13px; font-weight: 500; }
.service-status.up { color: var(--up); }
.service-status.down { color: var(--down); }
.service-meta { display: flex; gap: 20px; color: var(--muted); font-size: 12.5px; margin-bottom: 14px; }
.service-meta b { color: var(--secondary); font-weight: 600; font-variant-numeric: tabular-nums; }
.bars { display: flex; gap: 2px; height: 32px; }
.bar { flex: 1; border-radius: 2px; min-width: 0; }
.bar.up { background: #cfe0cf; } .bar.up:hover { background: var(--up); }
.bar.warn { background: #ecd9b0; } .bar.warn:hover { background: var(--degraded); }
.bar.down { background: #e8b8b8; } .bar.down:hover { background: var(--down); }
.bar.none { background: var(--border); }
.bar { transition: background .15s; }
.bars-legend { display: flex; justify-content: space-between; color: var(--muted); font-family: var(--mono); font-size: 9px; margin-top: 6px; text-transform: uppercase; letter-spacing: .08em; }
.updated { text-align: center; color: var(--muted); font-size: 12px; margin-top: 32px; font-family: var(--mono); }
footer { text-align: center; color: var(--muted); font-size: 13px; margin-top: 16px; }
footer a { color: var(--accent); text-decoration: none; }
footer a:hover { text-decoration: underline; }
.loading, .error { text-align: center; color: var(--muted); padding: 60px 0; }
.error { color: var(--down); }
.skeleton { animation: pulse 1.4s ease-in-out infinite; }
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: .5; } }
</style>
</head>
<body>
<nav>
<div class="inner">
<a class="logo" href="https://pixelrag.ai">
<span class="logo-mark"><span></span><span></span><span></span></span>
<span class="logo-name">Pixel<b>RAG</b></span>
</a>
<div class="nav-links">
<a href="https://pixelrag.ai">Home</a>
<a href="https://github.com/StarTrail-org/PixelRAG" target="_blank" rel="noopener">GitHub</a>
</div>
</div>
</nav>
<main>
<div class="head">
<div class="pill"><span class="dot up"></span> System Status</div>
<h1>PixelRAG Status</h1>
<p class="sub">Live availability of the search API, tile serving, agent backend, and website.</p>
</div>
<div id="content">
<div class="loading skeleton">Loading status…</div>
</div>
<div class="updated" id="updated"></div>
<footer>
Hosted independently on GitHub Pages ·
<a href="https://github.com/StarTrail-org/PixelRAG" target="_blank" rel="noopener">open source</a>
</footer>
</main>
<script>
const SUMMARY_URL = "https://raw.githubusercontent.com/StarTrail-org/PixelRAG/status/history/summary.json";
const DAYS = 90;
function fmtTime(ms) {
if (ms == null) return "—";
return ms < 1000 ? ms + " ms" : (ms / 1000).toFixed(2) + " s";
}
function dayBars(dailyMinutesDown) {
const bars = [];
const today = new Date();
for (let i = DAYS - 1; i >= 0; i--) {
const d = new Date(today);
d.setDate(d.getDate() - i);
const key = d.toISOString().slice(0, 10);
const down = (dailyMinutesDown && dailyMinutesDown[key]) || 0;
let cls = "up", label = "No downtime";
if (down > 0 && down < 30) { cls = "warn"; label = down + " min down"; }
else if (down >= 30) { cls = "down"; label = down + " min down"; }
bars.push(`<div class="bar ${cls}" title="${key}: ${label}"></div>`);
}
return bars.join("");
}
function render(services) {
const allUp = services.every(s => s.status === "up");
const anyDown = services.some(s => s.status === "down");
const overall = allUp ? "up" : anyDown ? "down" : "degraded";
const overallText = allUp ? "All systems operational"
: anyDown ? "Partial system outage" : "Degraded performance";
let html = `<div class="banner ${overall}"><span class="dot ${overall}"></span>${overallText}</div>`;
html += `<div class="services">`;
for (const s of services) {
const up = s.status === "up";
html += `
<div class="service">
<div class="service-top">
<span class="service-name">${s.name}</span>
<span class="service-status ${up ? "up" : "down"}">
<span class="dot ${up ? "up" : "down"}"></span>${up ? "Operational" : "Down"}
</span>
</div>
<div class="service-meta">
<span>Uptime <b>${s.uptime || "—"}</b></span>
<span>Avg response <b>${fmtTime(s.time)}</b></span>
</div>
<div class="bars">${dayBars(s.dailyMinutesDown)}</div>
<div class="bars-legend"><span>${DAYS} days ago</span><span>today</span></div>
</div>`;
}
html += `</div>`;
document.getElementById("content").innerHTML = html;
const now = new Date();
document.getElementById("updated").textContent =
"Last checked " + now.toLocaleString();
}
async function load() {
try {
const res = await fetch(SUMMARY_URL + "?t=" + Date.now(), { cache: "no-store" });
if (!res.ok) throw new Error("HTTP " + res.status);
const data = await res.json();
if (!Array.isArray(data) || data.length === 0) throw new Error("no data");
render(data);
} catch (e) {
document.getElementById("content").innerHTML =
`<div class="error">Couldn't load status data (${e.message}).<br>The monitoring data may still be initializing.</div>`;
}
}
load();
setInterval(load, 60000); // refresh every minute from committed data (no GitHub API)
</script>
</body>
</html>
-30
View File
@@ -1,30 +0,0 @@
const REPO_OWNER = "StarTrail-org"
const REPO_NAME = "PixelRAG"
const BRANCH = "main"
interface UptimeSite {
name: string
url: string
slug: string
status: "up" | "down" | "degraded"
uptime: string
uptimeDay: string
uptimeWeek: string
uptimeMonth: string
uptimeYear: string
time: number
timeDay: number
timeWeek: number
timeMonth: number
timeYear: number
dailyMinutesDown: Record<string, number>
}
export type { UptimeSite }
export async function fetchUptimeSummary(): Promise<UptimeSite[]> {
const url = `https://raw.githubusercontent.com/${REPO_OWNER}/${REPO_NAME}/${BRANCH}/history/summary.json`
const res = await fetch(url, { cache: "no-store" })
if (!res.ok) throw new Error(`Failed to fetch uptime data: ${res.status}`)
return res.json()
}