From f75e93cb912192e70d6d081f199fcf8ba7154757 Mon Sep 17 00:00:00 2001 From: Ace Data Cloud Dev Date: Mon, 5 Oct 2026 10:29:43 +0800 Subject: [PATCH 1/2] chore: consolidate capability sync into the daily Backend job --- .github/workflows/dispatch-on-push.yml | 86 ------------- .github/workflows/sync.yml | 167 ------------------------- README.md | 31 ++--- 3 files changed, 17 insertions(+), 267 deletions(-) delete mode 100644 .github/workflows/dispatch-on-push.yml delete mode 100644 .github/workflows/sync.yml diff --git a/.github/workflows/dispatch-on-push.yml b/.github/workflows/dispatch-on-push.yml deleted file mode 100644 index 910d97e22..000000000 --- a/.github/workflows/dispatch-on-push.yml +++ /dev/null @@ -1,86 +0,0 @@ -name: Dispatch on Push - -on: - push: - branches: [main] - paths: - - "openapi/**" - - "*/guides/**" - - "*/mcp/**" - -permissions: - contents: read - -jobs: - detect: - runs-on: ubuntu-latest - outputs: - changed_services: ${{ steps.detect.outputs.changed_services }} - commit_sha: ${{ steps.detect.outputs.commit_sha }} - skip: ${{ steps.detect.outputs.skip }} - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 2 - - - name: Detect changed services - id: detect - run: | - changed_files=$(git diff --name-only HEAD~1 HEAD 2>/dev/null || echo "") - echo "Changed files:" - echo "$changed_files" - - changed_services=$(echo "$changed_files" | grep -oP '^(?:openapi/|[^/]+/guides/|[^/]+/mcp/)\K[^/.]+' | sort -u | tr '\n' ',' | sed 's/,$//') - echo "changed_services=$changed_services" >> "$GITHUB_OUTPUT" - echo "commit_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" - - if [ -z "$changed_services" ]; then - echo "skip=true" >> "$GITHUB_OUTPUT" - else - echo "skip=false" >> "$GITHUB_OUTPUT" - fi - - dispatch: - needs: detect - if: needs.detect.outputs.skip != 'true' - runs-on: ubuntu-latest - timeout-minutes: 5 - strategy: - fail-fast: false - matrix: - # Code consumers receive canonical contracts directly from PlatformBackend. - # Docs only dispatches published-content updates to these consumers. - include: - - repo: AceDataCloud/APIs - services: all - - repo: AceDataCloud/Skills - services: all - steps: - - name: Check if service is relevant - id: check - run: | - changed="${{ needs.detect.outputs.changed_services }}" - target="${{ matrix.services }}" - if [ "$target" = "all" ]; then - echo "relevant=true" >> "$GITHUB_OUTPUT" - elif echo ",$changed," | grep -q ",$target,"; then - echo "relevant=true" >> "$GITHUB_OUTPUT" - else - echo "relevant=false" >> "$GITHUB_OUTPUT" - echo "Skipping ${{ matrix.repo }} — '$target' not in '$changed'" - fi - - - name: Dispatch to downstream repo - if: steps.check.outputs.relevant == 'true' - uses: peter-evans/repository-dispatch@v3 - with: - token: ${{ secrets.BOT_GITHUB_TOKEN }} - repository: ${{ matrix.repo }} - event-type: docs-updated - client-payload: | - { - "commit_sha": "${{ needs.detect.outputs.commit_sha }}", - "changed_services": "${{ needs.detect.outputs.changed_services }}", - "source": "Docs-push" - } diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml deleted file mode 100644 index 6cd67c9c6..000000000 --- a/.github/workflows/sync.yml +++ /dev/null @@ -1,167 +0,0 @@ -name: Sync Docs from PlatformBackend - -on: - push: - branches: [main] - paths: - - 'scripts/**' - - '.github/workflows/sync.yml' - repository_dispatch: - types: [platform-contracts-updated] - workflow_dispatch: - schedule: - - cron: "37 * * * *" - -concurrency: - group: docs-publication-main - cancel-in-progress: false - -permissions: - contents: write - -env: - PYTHONUNBUFFERED: "1" - -jobs: - sync: - runs-on: ubuntu-latest - timeout-minutes: 30 - outputs: - changed: ${{ steps.changes.outputs.changed }} - changed_services: ${{ steps.changes.outputs.changed_services }} - commit_sha: ${{ steps.commit.outputs.commit_sha }} - steps: - - name: Checkout Docs repo - uses: actions/checkout@v4 - with: - path: Docs - ref: main - token: ${{ secrets.BOT_GITHUB_TOKEN }} - - - name: Checkout current PlatformBackend source - uses: actions/checkout@v4 - with: - repository: AceDataCloud/PlatformBackend - ref: main - fetch-depth: 0 - path: PlatformBackend - token: ${{ secrets.BOT_GITHUB_TOKEN }} - - - name: Verify source event and current contract - id: backend - env: - EVENT_NAME: ${{ github.event_name }} - SOURCE_SHA: ${{ github.event.client_payload.source_sha }} - run: | - actual=$(git -C PlatformBackend rev-parse HEAD) - if [ "$EVENT_NAME" = "repository_dispatch" ]; then - if ! printf '%s' "$SOURCE_SHA" | grep -Eq '^[0-9a-f]{40}$'; then - echo "::error::Contract events require a full source_sha." - exit 1 - fi - # An old queued event is a reconciliation signal, never permission - # to replay an older snapshot over newer published content. - git -C PlatformBackend merge-base --is-ancestor "$SOURCE_SHA" "$actual" - fi - echo "sha=$actual" >> "$GITHUB_OUTPUT" - bundle=$(mktemp -d) - python PlatformBackend/scripts/ecosystem_contracts.py \ - --backend-dir PlatformBackend compile --output-dir "$bundle" --source-sha "$actual" - python PlatformBackend/scripts/ecosystem_contracts.py verify \ - --bundle-dir "$bundle" --source-sha "$actual" - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: "3.12" - - - name: Reconcile public documents - id: publication - working-directory: Docs - env: - PUBLIC_EXAMPLE_DENYLIST: ${{ secrets.PUBLIC_EXAMPLE_DENYLIST }} - run: | - set +e - python -u scripts/sync_from_platformbackend.py \ - --backend-dir ../PlatformBackend \ - --output-dir . \ - --report "$RUNNER_TEMP/docs-sync-report.json" - result=$? - set -e - if [ "$result" -ne 0 ] && [ "$result" -ne 2 ]; then - exit "$result" - fi - echo "incomplete=$([ "$result" -eq 2 ] && echo true || echo false)" >> "$GITHUB_OUTPUT" - python - "$RUNNER_TEMP/docs-sync-report.json" >> "$GITHUB_STEP_SUMMARY" <<'PY' - import json, sys - report = json.load(open(sys.argv[1])) - print(f"Current document versions: {report['ready']}/{report['total']}") - for item in report['pending'][:100]: - print(f"- {item['language']}/{item['source_key']}: {item['status']}") - PY - - - name: Preserve publication completeness report - if: always() - uses: actions/upload-artifact@v4 - with: - name: docs-sync-report - path: ${{ runner.temp }}/docs-sync-report.json - if-no-files-found: warn - retention-days: 14 - - - uses: actions/setup-node@v4 - with: - node-version: '24' - cache: npm - cache-dependency-path: Docs/package-lock.json - - - name: Validate MDX and local links before pushing - working-directory: Docs - run: | - npm ci --ignore-scripts - node scripts/validate_mdx.mjs . - - - name: Check for changes - id: changes - working-directory: Docs - run: | - git add -A - if git diff --cached --quiet; then - echo "changed=false" >> "$GITHUB_OUTPUT" - echo "changed_services=" >> "$GITHUB_OUTPUT" - exit 0 - fi - - echo "changed=true" >> "$GITHUB_OUTPUT" - changed_files=$(git diff --cached --name-only) - git diff --cached --stat - - changed_services=$(echo "$changed_files" \ - | grep -oP '^(?:openapi/|[^/]+/guides/|[^/]+/mcp/)\K[^/.]+' \ - | sort -u \ - | tr '\n' ',' \ - | sed 's/,$//' || true) - echo "changed_services=$changed_services" >> "$GITHUB_OUTPUT" - - - name: Commit and push - id: commit - if: steps.changes.outputs.changed == 'true' - working-directory: Docs - run: | - git config user.name "Ace Data Cloud Dev" - git config user.email "dev@acedata.cloud" - latest=$(git -C ../PlatformBackend ls-remote origin refs/heads/main | cut -f1) - test "$latest" = "${{ steps.backend.outputs.sha }}" || { - echo "::error::PlatformBackend advanced during publication; retry from current main." - exit 1 - } - git commit -m "docs: sync from PlatformBackend [automated]" \ - -m "Source: ${{ steps.backend.outputs.sha }}" - git push - echo "commit_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" - - - name: Require complete publication - if: steps.publication.outputs.incomplete == 'true' - run: | - echo "::error::Publication is incomplete. Current pages were refreshed; retained or missing translations are listed in docs-sync-report." - exit 1 diff --git a/README.md b/README.md index 52d99c10a..21af6a64f 100644 --- a/README.md +++ b/README.md @@ -31,17 +31,12 @@ links with `mint broken-links`. Navigation and site settings live in `docs.json` ## Synchronization contract -`Sync Ecosystem Contracts` is the only source-change trigger. The Docs workflow -serializes all writers, checks out current `main` after acquiring the queue, and -validates that an event SHA belongs to the current backend history. Old events -cannot republish old source snapshots. A final source check rejects a backend -revision that advanced during generation; normal Git push rejects concurrent -editorial changes without overwriting them. - -Hourly reconciliation picks up asynchronous source deployment and translation -completion even when no new Git event occurs. Before switching this consumer on, -deploy the additive metadata on the existing document list. Missing metadata or -malformed/incomplete pages fail instead of being treated as a successful sync. +PlatformBackend's daily ecosystem CronJob is the only publication coordinator. +It checks out a pinned current Backend source, runs this repository's existing +generator, validates MDX, and opens or updates a PR. Mintlify publishes after +normal review and merge. No cross-repository dispatch or hourly GitHub writer +remains. Every daily pass also checks translation completion without requiring +a new source commit. For every generated page, the database source hash must match the checked-out Markdown and the target translation must be current. Catalog identity must also @@ -50,11 +45,11 @@ and never counts that fallback as a current translation. When a translation is pending, an existing page is retained for availability but is explicitly reported as incomplete; a missing page is not fabricated. Ready pages and public withdrawals can still publish. Exit status **2** means partial -publication and fails the workflow's final completeness gate. Other nonzero +publication and prevents the daily controller from advancing its checkpoint. Other nonzero statuses abort publication; **0** means every expected page is current. -The workflow retains `docs-sync-report` for 14 days and puts pending page keys, -locales, and reasons in the job summary. Generated output is staged and validated +The generator writes a completeness report for the controller; incomplete +publication is retried on the next daily run. Generated output is staged and validated before an atomic publish; interruption recovery includes navigation and all MCP locales. A separate MDX and local-link gate checks every site page before Git push, including editorial entry points. Plain Markdown braces are escaped outside code rather than interpreted as @@ -88,3 +83,11 @@ containing complete responses from the same document list for reproducible, offline verification. Reports belong outside the generated output tree. No sync command writes the backend DB or generates translations. + +## Daily capability updates + +PlatformBackend `scripts/sync_ecosystem.py` is the only scheduled coordinator. +One daily Kubernetes Job reviews Backend docs and API changes with Claude Code, +updates existing files, and creates or updates one reviewable PR per repository. +It never merges PRs or duplicates the Backend guide tree. Normal CI and review +remain required; publication and sub-repository mirroring run after merge. From 8f0176fb914fbb06c2d2eee36e4a36e9c69b396d Mon Sep 17 00:00:00 2001 From: Ace Data Cloud Dev Date: Mon, 5 Oct 2026 11:29:59 +0800 Subject: [PATCH 2/2] docs: reference the root ecosystem entry point --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 21af6a64f..2524bdeda 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ or generates translations. ## Daily capability updates -PlatformBackend `scripts/sync_ecosystem.py` is the only scheduled coordinator. +PlatformBackend `ecosystem.py` is the only scheduled coordinator. One daily Kubernetes Job reviews Backend docs and API changes with Claude Code, updates existing files, and creates or updates one reviewable PR per repository. It never merges PRs or duplicates the Backend guide tree. Normal CI and review