1313 - " apps/presentation/site/**"
1414 - " docs/**"
1515 - " mkdocs.yaml"
16+ - " mkdocs.book.zh.yaml"
17+ - " mkdocs.book.en.yaml"
1618 - " docs/showcases/**"
1719 - " docs/assets/long-running-loop-openviking-trajectory.png"
1820 - " docs/assets/long-running-loop-ml-experiment-trajectory.png"
1921 - " examples/export-frontstage-share-bundle.mjs"
2022 - " examples/frontstage-share-bundle-smoke.mjs"
2123 - " examples/readme-star-history-smoke.py"
24+ - " examples/dev-book-publication-smoke.py"
2225 - " examples/goal-channel-frontstage-fixture.py"
2326 - " examples/showcase-catalog-smoke.py"
2427 - " examples/status.example.json"
2528 - " scripts/render-star-history.py"
29+ - " scripts/install-from-github.sh"
2630 push :
2731 branches :
2832 - main
3438 - " apps/presentation/site/**"
3539 - " docs/**"
3640 - " mkdocs.yaml"
41+ - " mkdocs.book.zh.yaml"
42+ - " mkdocs.book.en.yaml"
3743 - " docs/showcases/**"
3844 - " docs/assets/long-running-loop-openviking-trajectory.png"
3945 - " docs/assets/long-running-loop-ml-experiment-trajectory.png"
4046 - " examples/export-frontstage-share-bundle.mjs"
4147 - " examples/frontstage-share-bundle-smoke.mjs"
4248 - " examples/readme-star-history-smoke.py"
49+ - " examples/dev-book-publication-smoke.py"
4350 - " examples/goal-channel-frontstage-fixture.py"
4451 - " examples/showcase-catalog-smoke.py"
4552 - " examples/status.example.json"
4653 - " scripts/render-star-history.py"
54+ - " scripts/install-from-github.sh"
4755
4856permissions :
4957 actions : read
8896 - name : Validate public showcase catalog
8997 run : python3 examples/showcase-catalog-smoke.py
9098
91- - name : Validate README star history
99+ - name : Validate README star history
92100 run : python3 examples/readme-star-history-smoke.py
93101
102+ - name : Validate Developer Book publication
103+ run : python3 examples/dev-book-publication-smoke.py
104+
94105 - name : Validate public-safe frontstage bundle
95106 working-directory : apps/presentation/dashboard
96107 run : npm run smoke:frontstage-share-bundle
@@ -102,18 +113,40 @@ jobs:
102113 - name : Fetch complete GitHub stargazer history
103114 if : github.event_name != 'pull_request'
104115 env :
105- GH_TOKEN : ${{ github.token }}
116+ # Since July 2026, GitHub restricts this endpoint to repository
117+ # collaborators. Keep this credential read-only and repo-scoped.
118+ GH_TOKEN : ${{ secrets.STAR_HISTORY_READ_TOKEN }}
106119 run : |
107120 set -euo pipefail
121+ if [[ -z "${GH_TOKEN:-}" ]]; then
122+ echo "::error title=Missing star-history credential::Set STAR_HISTORY_READ_TOKEN to a fine-grained PAT limited to this repository with Metadata: read." >&2
123+ exit 1
124+ fi
125+ owner="${GITHUB_REPOSITORY%%/*}"
126+ repo="${GITHUB_REPOSITORY#*/}"
127+ count_query='query($owner: String!, $repo: String!) {
128+ repository(owner: $owner, name: $repo) { stargazerCount }
129+ }'
130+ history_query='query($owner: String!, $repo: String!, $endCursor: String) {
131+ repository(owner: $owner, name: $repo) {
132+ stargazers(first: 100, after: $endCursor, orderBy: {field: STARRED_AT, direction: ASC}) {
133+ edges { starredAt }
134+ pageInfo { hasNextPage endCursor }
135+ }
136+ }
137+ }'
108138 for attempt in 1 2 3; do
109- count_before="$(gh api "/repos/$GITHUB_REPOSITORY" --jq .stargazers_count)"
110- gh api --paginate --slurp \
111- --header "Accept: application/vnd.github.star+json" \
112- --header "X-GitHub-Api-Version: 2026-03-10" \
113- "/repos/$GITHUB_REPOSITORY/stargazers?per_page=100" \
139+ count_before="$(gh api graphql -f query="$count_query" -F owner="$owner" -F repo="$repo" --jq .data.repository.stargazerCount)"
140+ gh api graphql --paginate --slurp \
141+ -f query="$history_query" \
142+ -F owner="$owner" \
143+ -F repo="$repo" \
144+ > "$RUNNER_TEMP/loopx-stargazer-pages.json"
145+ jq '[.[].data.repository.stargazers.edges[] | {starred_at: .starredAt}]' \
146+ "$RUNNER_TEMP/loopx-stargazer-pages.json" \
114147 > "$RUNNER_TEMP/loopx-stargazers.json"
115- count_after="$(gh api "/repos/$GITHUB_REPOSITORY " -- jq .stargazers_count )"
116- fetched_count="$(jq '[.[][]] | length' "$RUNNER_TEMP/loopx-stargazers.json")"
148+ count_after="$(gh api graphql -f query="$count_query " -F owner="$owner" -F repo="$repo" -- jq .data.repository.stargazerCount )"
149+ fetched_count="$(jq 'length' "$RUNNER_TEMP/loopx-stargazers.json")"
117150 if [[ "$count_before" == "$count_after" && "$fetched_count" == "$count_after" ]]; then
118151 printf '%s\n' "$count_after" > "$RUNNER_TEMP/loopx-stargazers-count"
119152 break
@@ -137,6 +170,15 @@ jobs:
137170 - name : Build documentation site
138171 run : mkdocs build --strict --site-dir output/frontstage-pages/site/docs
139172
173+ - name : Build Chinese Developer Book
174+ run : mkdocs build --strict --config-file mkdocs.book.zh.yaml --site-dir output/frontstage-pages/site/docs/book
175+
176+ - name : Build English Developer Book
177+ run : mkdocs build --strict --config-file mkdocs.book.en.yaml --site-dir output/frontstage-pages/site/docs/book/en
178+
179+ - name : Validate rendered Developer Book
180+ run : python3 examples/dev-book-publication-smoke.py --site-dir output/frontstage-pages/site/docs/book
181+
140182 - name : Configure Pages
141183 if : github.event_name != 'pull_request'
142184 uses : actions/configure-pages@v6
0 commit comments