Skip to content
Open
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
10 changes: 9 additions & 1 deletion .github/workflows/frontstage-pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ on:
- "docs/assets/long-running-loop-ml-experiment-trajectory.png"
- "examples/export-frontstage-share-bundle.mjs"
- "examples/frontstage-share-bundle-smoke.mjs"
- "examples/frontstage-pages-workflow-smoke.py"
- "examples/readme-star-history-smoke.py"
- "examples/frontstage-stargazer-fetch-smoke.py"
- "examples/dev-book-publication-smoke.py"
Expand Down Expand Up @@ -58,6 +59,7 @@ on:
- "docs/assets/long-running-loop-ml-experiment-trajectory.png"
- "examples/export-frontstage-share-bundle.mjs"
- "examples/frontstage-share-bundle-smoke.mjs"
- "examples/frontstage-pages-workflow-smoke.py"
- "examples/readme-star-history-smoke.py"
- "examples/frontstage-stargazer-fetch-smoke.py"
- "examples/dev-book-publication-smoke.py"
Expand All @@ -83,6 +85,9 @@ concurrency:

jobs:
build:
# Forks retain PR validation without requiring publication credentials.
# Scheduled, push, and manual publication belongs to the upstream site.
if: github.event_name == 'pull_request' || github.repository == 'huangruiteng/loopx'
runs-on: ubuntu-latest
timeout-minutes: 40
steps:
Expand Down Expand Up @@ -132,6 +137,9 @@ jobs:
python -m pip install --disable-pip-version-check -r docs/requirements-docs.txt
python -m pip install --disable-pip-version-check -e .

- name: Validate Pages workflow isolation
run: python3 examples/frontstage-pages-workflow-smoke.py

- name: Validate public showcase catalog
run: python3 examples/showcase-catalog-smoke.py

Expand Down Expand Up @@ -222,7 +230,7 @@ jobs:
path: output/frontstage-pages/site

deploy:
if: github.event_name != 'pull_request'
if: github.event_name != 'pull_request' && github.repository == 'huangruiteng/loopx'
needs: build
runs-on: ubuntu-latest
timeout-minutes: 15
Expand Down
37 changes: 36 additions & 1 deletion examples/frontstage-pages-workflow-smoke.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#!/usr/bin/env python3
"""Smoke-test the public-safe GitHub Pages frontstage workflow source."""
"""Smoke-test fork-safe validation and upstream-only Frontstage publication."""

from __future__ import annotations

import re
from pathlib import Path


Expand Down Expand Up @@ -58,9 +59,42 @@ def assert_pr_and_push_trigger(trigger_text: str, path: str) -> None:
)


def assert_publication_isolation(text: str) -> None:
build, deploy = text.split("\n build:\n", 1)[1].split("\n deploy:\n", 1)
# PR validation must run on any repository. Every non-PR event on a fork
# must skip before credential access; deployment independently stays gated.
assert re.findall(r"^ if: (.+)$", build, re.MULTILINE) == [
"github.event_name == 'pull_request' || github.repository == 'huangruiteng/loopx'"
]
assert re.findall(r"^ if: (.+)$", deploy, re.MULTILINE) == [
"github.event_name != 'pull_request' && github.repository == 'huangruiteng/loopx'"
]
assert_contains(deploy, "\n needs: build\n")

steps = dict(re.findall(
r"^ - name: ([^\n]+)\n(.*?)(?=^ - name:|\Z)",
build,
re.MULTILINE | re.DOTALL,
))
for name in [
"Fetch complete GitHub stargazer history",
"Generate verified public star history",
"Verify star history freshness",
"Configure Pages",
"Upload Pages artifact",
]:
assert re.findall(r"^ if: (.+)$", steps[name], re.MULTILINE) == [
"github.event_name != 'pull_request'"
], name
validation = steps["Validate Pages workflow isolation"]
assert not re.search(r"^ if:", validation, re.MULTILINE)
assert_contains(validation, "run: python3 examples/frontstage-pages-workflow-smoke.py")


def main() -> int:
text = WORKFLOW.read_text(encoding="utf-8")
trigger_text = text.split("\npermissions:", 1)[0]
assert_publication_isolation(text)

for needle in [
"workflow_dispatch:",
Expand Down Expand Up @@ -133,6 +167,7 @@ def main() -> int:
assert_absent(text, forbidden)

for path in [
"examples/frontstage-pages-workflow-smoke.py",
"docs/book/mkdocs.zh.yaml",
"docs/book/mkdocs.en.yaml",
"examples/dev-book-publication-smoke.py",
Expand Down
Loading