fix(ci): fail loudly when WEBSITE_SYNC_TOKEN missing + trigger on doc… #3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Sync toolkit docs to website | |
| # Issue #38: toolkit-owned docs are authoritative for CLI / MCP / SDK / | |
| # coding-agent setup. When they change on main, open a PR back to | |
| # WonderfulValley/qveris-website:release/test so the website mirror stays | |
| # in sync. Website-owned docs (rest-api, cookbook, openapi) are excluded | |
| # from the trigger so this workflow cannot create a sync loop. | |
| on: | |
| push: | |
| branches: | |
| - main | |
| paths: | |
| # Toolkit-owned docs. The website's docs/.source-manifest.json | |
| # (sources.toolkit_owned.paths) is the authority for what sync-docs.mjs | |
| # actually mirrors; this trigger must be a SUPERSET of it so a toolkit | |
| # edit reliably starts the sync. Paths the manifest does not list yet | |
| # (python-sdk, the docs/cn/zh-CN CN-region variants) are included here so | |
| # they trigger as soon as the website manifest is updated to mirror them. | |
| - "docs/en-US/cli.md" | |
| - "docs/zh-CN/cli.md" | |
| - "docs/cn/zh-CN/cli.md" | |
| - "docs/en-US/mcp-server.md" | |
| - "docs/zh-CN/mcp-server.md" | |
| - "docs/cn/zh-CN/mcp-server.md" | |
| - "docs/en-US/ide-cli-setup.md" | |
| - "docs/zh-CN/ide-cli-setup.md" | |
| - "docs/cn/zh-CN/ide-cli-setup.md" | |
| - "docs/en-US/claude-code-setup.md" | |
| - "docs/zh-CN/claude-code-setup.md" | |
| - "docs/en-US/opencode-setup.md" | |
| - "docs/zh-CN/opencode-setup.md" | |
| - "docs/cn/zh-CN/opencode-setup.md" | |
| # SDK docs (added after the manifest's last policy update; the website | |
| # manifest must list these before sync-docs.mjs will mirror them). | |
| - "docs/en-US/python-sdk.md" | |
| - "docs/zh-CN/python-sdk.md" | |
| - "docs/cn/zh-CN/python-sdk.md" | |
| - ".github/workflows/sync-docs-to-website.yml" | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: sync-docs-to-website | |
| cancel-in-progress: false | |
| jobs: | |
| sync: | |
| runs-on: ubuntu-latest | |
| env: | |
| WEBSITE_SYNC_TOKEN: ${{ secrets.WEBSITE_SYNC_TOKEN }} | |
| WEBSITE_REPO: WonderfulValley/qveris-website | |
| WEBSITE_BASE: release/test | |
| steps: | |
| - name: Check sync token | |
| id: guard | |
| run: | | |
| if [ -n "${WEBSITE_SYNC_TOKEN}" ]; then | |
| echo "skip=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| # Missing secret. Do NOT report a silent green "success" that did | |
| # nothing — that hid this breakage until a manual run was inspected. | |
| echo "::error title=WEBSITE_SYNC_TOKEN missing::Repo secret WEBSITE_SYNC_TOKEN is not configured, so the toolkit -> website docs sync cannot run. Add it under Settings -> Secrets and variables -> Actions. The token needs Contents:write + Pull requests:write on ${WEBSITE_REPO}." | |
| if [ "${GITHUB_REPOSITORY}" = "QVerisAI/qveris-agent-toolkit" ]; then | |
| # First-party repo: a missing required secret is a misconfiguration | |
| # that must be visible (red), not a silent no-op. | |
| exit 1 | |
| fi | |
| # Forks / mirrors legitimately cannot hold this secret — skip there | |
| # so they are not permanently red for a sync they can't perform. | |
| echo "Not the first-party repo (${GITHUB_REPOSITORY}); skipping fork-safe." | |
| echo "skip=true" >> "$GITHUB_OUTPUT" | |
| - name: Checkout toolkit | |
| if: steps.guard.outputs.skip != 'true' | |
| uses: actions/checkout@v4 | |
| with: | |
| path: qveris-agent-toolkit | |
| - name: Checkout website (release/test) | |
| if: steps.guard.outputs.skip != 'true' | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: ${{ env.WEBSITE_REPO }} | |
| ref: ${{ env.WEBSITE_BASE }} | |
| token: ${{ secrets.WEBSITE_SYNC_TOKEN }} | |
| path: qveris-website | |
| - name: Setup Node.js | |
| if: steps.guard.outputs.skip != 'true' | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| - name: Mirror toolkit-owned docs into website checkout | |
| if: steps.guard.outputs.skip != 'true' | |
| working-directory: qveris-website | |
| run: node scripts/sync-docs.mjs --from-toolkit --toolkit-dir ../qveris-agent-toolkit | |
| - name: Open website PR if docs changed | |
| if: steps.guard.outputs.skip != 'true' | |
| working-directory: qveris-website | |
| env: | |
| GH_TOKEN: ${{ secrets.WEBSITE_SYNC_TOKEN }} | |
| TOOLKIT_SHA: ${{ github.sha }} | |
| run: | | |
| set -euo pipefail | |
| if [ -z "$(git status --porcelain)" ]; then | |
| echo "No website doc changes after sync; nothing to open." | |
| exit 0 | |
| fi | |
| SHORT_SHA="$(echo "${TOOLKIT_SHA}" | cut -c1-12)" | |
| BRANCH="sync/toolkit-docs-${SHORT_SHA}" | |
| git config user.name "qveris-docs-sync[bot]" | |
| git config user.email "qveris-docs-sync@users.noreply.github.com" | |
| git checkout -b "${BRANCH}" | |
| git add -A | |
| git commit -m "docs: sync toolkit-owned docs from qveris-agent-toolkit@${SHORT_SHA}" | |
| git push --force origin "${BRANCH}" | |
| BODY="$(cat <<EOF | |
| Automated mirror of **toolkit-owned** docs from \`QVerisAI/qveris-agent-toolkit\` @ \`${SHORT_SHA}\`. | |
| Source of truth is the toolkit repo (CLI / MCP / SDK / coding-agent setup docs). Generated by \`.github/workflows/sync-docs-to-website.yml\` via \`scripts/sync-docs.mjs --from-toolkit\`. Website-owned docs (rest-api, cookbook, openapi) are not touched by this workflow. | |
| EOF | |
| )" | |
| OPEN_COUNT="$(gh pr list --repo "${WEBSITE_REPO}" --head "${BRANCH}" --base "${WEBSITE_BASE}" --state open --json number --jq 'length')" | |
| if [ "${OPEN_COUNT}" != "0" ]; then | |
| echo "PR for ${BRANCH} already open; branch updated, no new PR created." | |
| else | |
| gh pr create \ | |
| --repo "${WEBSITE_REPO}" \ | |
| --base "${WEBSITE_BASE}" \ | |
| --head "${BRANCH}" \ | |
| --title "docs: sync toolkit-owned docs (qveris-agent-toolkit@${SHORT_SHA})" \ | |
| --body "${BODY}" | |
| fi |