Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@ jobs:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

- name: Live probe published site
run: scripts/probe_site.sh
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ This repo is **English-primary, zh-en bilingual**: source files are English; ext

## 包

- `packages/site-board/`(flat):站点数据源 v0。cron 轮询 `FKST_GITHUB_REPO` 的 open issue/PR 板面,构建 `fkst-website.board.v1` 快照 JSON;`FKST_SITE_WRITE=1` 且设置 `FKST_SITE_PUBLISH_ROOT` 时原子发布 `board.json`(写 tmp + mv),否则 dry-run 只记日志。
- `packages/site-board/`(flat):站点数据源 v0。cron 轮询 `FKST_GITHUB_REPO` 的 open issue/PR 板面,构建 `fkst-website.board.v1` 快照 JSON;`FKST_SITE_WRITE=1` 且设置 `FKST_SITE_PUBLISH_ROOT` 时原子发布 `board.json`(写 tmp + mv),否则 dry-run 只记日志。GitHub Pages deploy 后读取 `site/probe-manifest` 对发布站点做只读 live probe,只输出可 grep 的 `PROBE` ok/fail/skip 日志。

## 构建 / 测试

Expand Down
47 changes: 47 additions & 0 deletions scripts/probe_site.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/usr/bin/env bash
# Probe the deployed GitHub Pages site from the tracked manifest.
set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
MANIFEST="${FKST_SITE_PROBE_MANIFEST:-$ROOT/site/probe-manifest}"
BASE_URL="${FKST_SITE_PROBE_BASE_URL:-https://chronoaiproject.github.io/fkst-website}"
TIMEOUT_SECONDS="${FKST_SITE_PROBE_TIMEOUT_SECONDS:-15}"
CONNECT_TIMEOUT_SECONDS="${FKST_SITE_PROBE_CONNECT_TIMEOUT_SECONDS:-5}"

checked=0
failures=0
network_errors=0
results=()

while IFS= read -r path || [ -n "$path" ]; do
path="${path%%#*}"
path="${path#"${path%%[![:space:]]*}"}"
path="${path%"${path##*[![:space:]]}"}"
[ -n "$path" ] || continue

checked=$((checked + 1))
url="${BASE_URL}${path}"
code="$(curl -sL -o /dev/null -w '%{http_code}' --connect-timeout "$CONNECT_TIMEOUT_SECONDS" --max-time "$TIMEOUT_SECONDS" -- "$url")" || code="error"
[ -n "$code" ] || code="error"
results+=("${path}:${code}")

if [ "$code" = "200" ]; then
continue
elif [ "$code" = "error" ]; then
network_errors=$((network_errors + 1))
else
failures=$((failures + 1))
fi
done < "$MANIFEST"

joined="$(IFS=,; echo "${results[*]}")"
if [ "$checked" -eq 0 ]; then
echo "fkst-website dept=pages tag=skip PROBE paths=0 reason=empty-manifest results="
elif [ "$network_errors" -eq "$checked" ]; then
echo "fkst-website dept=pages tag=skip PROBE paths=$checked reason=all-paths-network-error results=$joined"
elif [ "$failures" -gt 0 ] || [ "$network_errors" -gt 0 ]; then
echo "fkst-website dept=pages tag=fail PROBE paths=$checked failures=$failures network_errors=$network_errors results=$joined"
exit 1
else
echo "fkst-website dept=pages tag=ok PROBE paths=$checked results=$joined"
fi
101 changes: 101 additions & 0 deletions scripts/probe_site_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#!/usr/bin/env python3
"""Unit tests for the deployed-site probe script."""

from __future__ import annotations

import os
import stat
import subprocess
import tempfile
import textwrap
import unittest
from pathlib import Path


ROOT = Path(__file__).resolve().parents[1]
PROBE = ROOT / "scripts" / "probe_site.sh"


class ProbeSiteTest(unittest.TestCase):
def run_probe(self, manifest: str, fake_curl: str) -> subprocess.CompletedProcess[str]:
with tempfile.TemporaryDirectory() as tmp:
tmp_path = Path(tmp)
manifest_path = tmp_path / "probe-manifest"
manifest_path.write_text(manifest, encoding="utf-8")

bin_dir = tmp_path / "bin"
bin_dir.mkdir()
curl_path = bin_dir / "curl"
curl_path.write_text(fake_curl, encoding="utf-8")
curl_path.chmod(curl_path.stat().st_mode | stat.S_IXUSR)

env = os.environ.copy()
env.update(
{
"PATH": f"{bin_dir}{os.pathsep}{env['PATH']}",
"FKST_SITE_PROBE_MANIFEST": str(manifest_path),
"FKST_SITE_PROBE_BASE_URL": "https://example.test",
}
)
return subprocess.run(
[str(PROBE)],
cwd=ROOT,
env=env,
text=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
check=False,
)

def test_all_200_logs_ok(self) -> None:
curl = textwrap.dedent(
"""\
#!/usr/bin/env bash
printf '200'
"""
)
result = self.run_probe("/\n/zh/\n", curl)

self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(
result.stdout.strip(),
"fkst-website dept=pages tag=ok PROBE paths=2 results=/:200,/zh/:200",
)

def test_partial_failure_logs_fail_and_exits_1(self) -> None:
curl = textwrap.dedent(
"""\
#!/usr/bin/env bash
url="${@: -1}"
case "$url" in
*/missing.html) printf '404' ;;
*) printf '200' ;;
esac
"""
)
result = self.run_probe("/\n/missing.html\n", curl)

self.assertEqual(result.returncode, 1)
self.assertEqual(
result.stdout.strip(),
"fkst-website dept=pages tag=fail PROBE paths=2 failures=1 network_errors=0 results=/:200,/missing.html:404",
)

def test_all_network_error_logs_skip(self) -> None:
curl = textwrap.dedent(
"""\
#!/usr/bin/env bash
exit 7
"""
)
result = self.run_probe("/\n/zh/\n", curl)

self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(
result.stdout.strip(),
"fkst-website dept=pages tag=skip PROBE paths=2 reason=all-paths-network-error results=/:error,/zh/:error",
)


if __name__ == "__main__":
unittest.main()
1 change: 1 addition & 0 deletions scripts/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ usage() {
cmd_check() {
python3 "$ROOT/scripts/check_repo.py"
python3 "$ROOT/scripts/check_repo_test.py"
python3 "$ROOT/scripts/probe_site_test.py"
}

check_test_file_coverage() {
Expand Down
6 changes: 6 additions & 0 deletions site/probe-manifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/
/zh/
/architecture.html
/doctrine.html
/zh/architecture.html
/zh/doctrine.html
Loading