From 50652361364e7f66ca252a1f3c5ed7a2b59141ec Mon Sep 17 00:00:00 2001 From: Divya Date: Fri, 8 May 2026 11:48:28 +0530 Subject: [PATCH 1/5] docs: add automated upstream sync workflow Adds a Claude-powered workflow that syncs docs pages with upstream README changes from five source repos (tracebloc-py-package, client, start-training, data-ingestors, model-zoo). Source repos fire repository_dispatch on push; this repo's workflow fetches the upstream file, has Claude rewrite the target .mdx in docs voice, and opens a PR. - .github/sync-sources.yml: mapping of upstream files to docs pages - .github/workflows/sync-docs.yml: dispatch + manual + cron-driven sync job - .github/notify-docs.workflow-template.yml: template for source repos Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/notify-docs.workflow-template.yml | 31 ++++++ .github/sync-sources.yml | 69 ++++++++++++ .github/workflows/sync-docs.yml | 121 ++++++++++++++++++++++ 3 files changed, 221 insertions(+) create mode 100644 .github/notify-docs.workflow-template.yml create mode 100644 .github/sync-sources.yml create mode 100644 .github/workflows/sync-docs.yml diff --git a/.github/notify-docs.workflow-template.yml b/.github/notify-docs.workflow-template.yml new file mode 100644 index 0000000..4cf473d --- /dev/null +++ b/.github/notify-docs.workflow-template.yml @@ -0,0 +1,31 @@ +# Template — copy into each upstream source repo as +# .github/workflows/notify-docs.yml +# +# Replace below with the matching `id` from +# tracebloc/docs:.github/sync-sources.yml +# +# Adjust the `paths:` filter if the watched file is not README.md. +# +# Required: an org-level (or repo-level) secret named DOCS_DISPATCH_TOKEN. +# - Fine-grained PAT scoped to repo `tracebloc/docs` +# - Permission: Contents: Read and write (needed to fire repository_dispatch) + +name: Notify docs of upstream change + +on: + push: + branches: [main] + paths: + - "README.md" + +jobs: + notify: + runs-on: ubuntu-latest + steps: + - name: Trigger docs sync + env: + GH_TOKEN: ${{ secrets.DOCS_DISPATCH_TOKEN }} + run: | + gh api repos/tracebloc/docs/dispatches \ + -f event_type=upstream-changed \ + -f 'client_payload[source_id]=' diff --git a/.github/sync-sources.yml b/.github/sync-sources.yml new file mode 100644 index 0000000..ea966b0 --- /dev/null +++ b/.github/sync-sources.yml @@ -0,0 +1,69 @@ +# Mapping: upstream source files → docs pages +# +# Add a new source by appending an entry. The `id` is also used in the +# source repo's notify workflow (see .github/notify-docs.workflow-template.yml) +# to tell this repo which mapping changed. +# +# Fields: +# id unique slug for this mapping +# repo owner/name of the upstream repo +# ref branch or tag to read from +# src file path inside the upstream repo +# dest path in this repo (must exist) +# private true if the repo is private (requires SOURCE_REPOS_TOKEN) +# instruction natural-language brief Claude follows when updating dest + +sources: + - id: tracebloc-package + repo: tracebloc/tracebloc-py-package + ref: main + src: README.md + dest: tools-help/tracebloc-package.mdx + private: true + instruction: | + Sync the Installation, Key Features, and Quick Start sections to reflect + the upstream README. Preserve the page frontmatter and any prose that is + unique to the docs page (e.g. links to other Mintlify pages). + + - id: client-setup + repo: tracebloc/client + ref: main + src: README.md + dest: environment-setup/setup-guide.mdx + private: false + instruction: | + Sync installer steps, requirements, supported platforms, and verification + commands. Preserve the page's narrative framing (numbered top-level steps, + requirements table) and any prose unique to the docs page. + + - id: start-training + repo: tracebloc/start-training + ref: main + src: README.md + dest: join-use-case/start-training.mdx + private: false + instruction: | + Sync notebook setup and the steps for launching experiments to match the + upstream README. Preserve cross-links to other Join-a-Use-Case pages. + + - id: data-ingestors + repo: tracebloc/data-ingestors + ref: main + src: Readme.md + dest: create-use-case/prepare-dataset.mdx + private: false + instruction: | + Sync dataset preparation pipeline steps, supported formats, and ingestor + configuration from the upstream README. Preserve the page frontmatter and + any examples specific to the docs page. + + - id: model-zoo + repo: tracebloc/model-zoo + ref: main + src: README.md + dest: create-use-case/templates.mdx + private: false + instruction: | + Sync the list of available model templates and their descriptions from the + upstream README. Preserve the page frontmatter and any prose specific to + the docs page. diff --git a/.github/workflows/sync-docs.yml b/.github/workflows/sync-docs.yml new file mode 100644 index 0000000..0b27779 --- /dev/null +++ b/.github/workflows/sync-docs.yml @@ -0,0 +1,121 @@ +name: Sync docs from upstream + +# Triggers: +# - repository_dispatch: fired by source repos when a watched file changes (push-driven) +# - workflow_dispatch: manual run from the Actions tab (optional source_id input) +# - schedule: daily safety-net in case a dispatch is missed +on: + repository_dispatch: + types: [upstream-changed] + workflow_dispatch: + inputs: + source_id: + description: "Specific source id from sync-sources.yml (leave empty for all)" + required: false + type: string + schedule: + - cron: "0 6 * * *" + +permissions: + contents: write + pull-requests: write + +jobs: + sync: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install yq + run: | + sudo wget -qO /usr/local/bin/yq \ + https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 + sudo chmod +x /usr/local/bin/yq + + - name: Resolve target sources + id: filter + env: + DISPATCH_ID: ${{ github.event.client_payload.source_id }} + INPUT_ID: ${{ inputs.source_id }} + run: | + target="${DISPATCH_ID:-${INPUT_ID:-}}" + if [ -n "$target" ]; then + echo "Filtering for source: $target" + yq -o=json ".sources[] | select(.id == \"$target\")" \ + .github/sync-sources.yml | jq -s . > /tmp/sources.json + else + echo "Processing all sources" + yq -o=json '.sources' .github/sync-sources.yml > /tmp/sources.json + fi + count=$(jq length /tmp/sources.json) + echo "count=$count" >> "$GITHUB_OUTPUT" + echo "Found $count source(s) to process" + if [ "$count" = "0" ]; then + echo "Nothing to do." + fi + + - name: Fetch upstream files + if: steps.filter.outputs.count != '0' + env: + GH_TOKEN: ${{ secrets.SOURCE_REPOS_TOKEN || secrets.GITHUB_TOKEN }} + run: | + mkdir -p .sync-cache + jq -c '.[]' /tmp/sources.json | while read -r s; do + id=$(jq -r .id <<<"$s") + repo=$(jq -r .repo <<<"$s") + ref=$(jq -r .ref <<<"$s") + src=$(jq -r .src <<<"$s") + echo "Fetching $repo@$ref:$src -> .sync-cache/$id" + gh api "repos/$repo/contents/$src?ref=$ref" \ + -H "Accept: application/vnd.github.raw" \ + > ".sync-cache/$id" + done + ls -la .sync-cache + + - name: Run Claude to update docs + if: steps.filter.outputs.count != '0' + uses: anthropics/claude-code-action@v1 + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + with: + prompt: | + You are syncing this Mintlify docs site with upstream README changes. + + The mapping is at `.github/sync-sources.yml`. + The list of sources to process this run is at `/tmp/sources.json`. + For each source, the latest upstream file content is at + `.sync-cache/`. + + For every entry in `/tmp/sources.json`: + 1. Read `.sync-cache/` (upstream) and the docs page at `dest`. + 2. Apply the entry's `instruction` to update the docs page in place. + 3. Preserve YAML frontmatter, page-specific framing, links to other + Mintlify pages, and any callouts/components already on the page. + 4. Follow `AGENTS.md` style: active voice, second person, sentence + case headings, **bold** for UI elements, `code` for paths and + commands. + 5. If the upstream content does not meaningfully change anything in + the docs page, skip that source — do not edit the file. + + Do not edit any files outside the `dest` paths listed in the + sources. Do not touch `.sync-cache/` or `/tmp/`. + + - name: Open or update PR + if: steps.filter.outputs.count != '0' + uses: peter-evans/create-pull-request@v6 + with: + branch: docs/sync-upstream + delete-branch: true + commit-message: "docs: sync upstream sources" + title: "docs: sync upstream sources" + body: | + Automated sync from upstream repos via Claude. + + **Triggered by:** `${{ github.event_name }}` + **Source filter:** `${{ github.event.client_payload.source_id || inputs.source_id || 'all' }}` + + Review carefully — Claude rewrites prose to fit docs style, but + verify accuracy against the upstream README before merging. + labels: | + docs-sync + automated From d750493808685f5b2b2715f648135f42d55b377a Mon Sep 17 00:00:00 2001 From: Asad Iqbal Date: Tue, 12 May 2026 18:40:08 +0500 Subject: [PATCH 2/5] fix: address bugbot issues in sync workflow - Pass ANTHROPIC_API_KEY as anthropic_api_key input to claude-code-action instead of env var (action reads via core.getInput, not env). - Move sync cache from .sync-cache/ to /tmp/sync-cache/ so untracked cache files are not picked up by create-pull-request. Co-Authored-By: Claude Opus 4.7 --- .github/workflows/sync-docs.yml | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/.github/workflows/sync-docs.yml b/.github/workflows/sync-docs.yml index 0b27779..f9db20b 100644 --- a/.github/workflows/sync-docs.yml +++ b/.github/workflows/sync-docs.yml @@ -59,35 +59,34 @@ jobs: env: GH_TOKEN: ${{ secrets.SOURCE_REPOS_TOKEN || secrets.GITHUB_TOKEN }} run: | - mkdir -p .sync-cache + mkdir -p /tmp/sync-cache jq -c '.[]' /tmp/sources.json | while read -r s; do id=$(jq -r .id <<<"$s") repo=$(jq -r .repo <<<"$s") ref=$(jq -r .ref <<<"$s") src=$(jq -r .src <<<"$s") - echo "Fetching $repo@$ref:$src -> .sync-cache/$id" + echo "Fetching $repo@$ref:$src -> /tmp/sync-cache/$id" gh api "repos/$repo/contents/$src?ref=$ref" \ -H "Accept: application/vnd.github.raw" \ - > ".sync-cache/$id" + > "/tmp/sync-cache/$id" done - ls -la .sync-cache + ls -la /tmp/sync-cache - name: Run Claude to update docs if: steps.filter.outputs.count != '0' uses: anthropics/claude-code-action@v1 - env: - ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} with: + anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} prompt: | You are syncing this Mintlify docs site with upstream README changes. The mapping is at `.github/sync-sources.yml`. The list of sources to process this run is at `/tmp/sources.json`. For each source, the latest upstream file content is at - `.sync-cache/`. + `/tmp/sync-cache/`. For every entry in `/tmp/sources.json`: - 1. Read `.sync-cache/` (upstream) and the docs page at `dest`. + 1. Read `/tmp/sync-cache/` (upstream) and the docs page at `dest`. 2. Apply the entry's `instruction` to update the docs page in place. 3. Preserve YAML frontmatter, page-specific framing, links to other Mintlify pages, and any callouts/components already on the page. @@ -98,7 +97,7 @@ jobs: the docs page, skip that source — do not edit the file. Do not edit any files outside the `dest` paths listed in the - sources. Do not touch `.sync-cache/` or `/tmp/`. + sources. Do not touch `/tmp/sync-cache/` or `/tmp/sources.json`. - name: Open or update PR if: steps.filter.outputs.count != '0' From a4e1525df0076ab862d73b3d7cc60aa6850ab5be Mon Sep 17 00:00:00 2001 From: Asad Iqbal Date: Tue, 12 May 2026 19:36:52 +0500 Subject: [PATCH 3/5] fix: address remaining bugbot issues in sync workflow - Add concurrency group so overlapping cron/dispatch/manual runs serialize instead of racing on the docs/sync-upstream branch (would otherwise fail with "failed to push some refs" and drop changes from the losing run). - Pin yq to v4.44.3 instead of latest for deterministic builds. - Restrict create-pull-request add-paths to **/*.mdx so stray edits outside docs pages cannot be staged into the sync PR. - Note in the notify template that branches may need adjusting for repos using master (e.g. data-ingestors). Co-Authored-By: Claude Opus 4.7 --- .github/notify-docs.workflow-template.yml | 2 ++ .github/workflows/sync-docs.yml | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/notify-docs.workflow-template.yml b/.github/notify-docs.workflow-template.yml index 4cf473d..2c608ec 100644 --- a/.github/notify-docs.workflow-template.yml +++ b/.github/notify-docs.workflow-template.yml @@ -5,6 +5,8 @@ # tracebloc/docs:.github/sync-sources.yml # # Adjust the `paths:` filter if the watched file is not README.md. +# Adjust `branches:` if the source repo's default branch is not `main` +# (e.g. some tracebloc repos use `master`). # # Required: an org-level (or repo-level) secret named DOCS_DISPATCH_TOKEN. # - Fine-grained PAT scoped to repo `tracebloc/docs` diff --git a/.github/workflows/sync-docs.yml b/.github/workflows/sync-docs.yml index f9db20b..089cc8e 100644 --- a/.github/workflows/sync-docs.yml +++ b/.github/workflows/sync-docs.yml @@ -20,6 +20,10 @@ permissions: contents: write pull-requests: write +concurrency: + group: sync-docs + cancel-in-progress: false + jobs: sync: runs-on: ubuntu-latest @@ -29,7 +33,7 @@ jobs: - name: Install yq run: | sudo wget -qO /usr/local/bin/yq \ - https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 + https://github.com/mikefarah/yq/releases/download/v4.44.3/yq_linux_amd64 sudo chmod +x /usr/local/bin/yq - name: Resolve target sources @@ -105,6 +109,7 @@ jobs: with: branch: docs/sync-upstream delete-branch: true + add-paths: "**/*.mdx" commit-message: "docs: sync upstream sources" title: "docs: sync upstream sources" body: | From 8194a2eec35d382a16d6575ac5efccc8118b3638 Mon Sep 17 00:00:00 2001 From: Asad Iqbal Date: Tue, 12 May 2026 21:16:55 +0500 Subject: [PATCH 4/5] fix: accumulate sync runs onto existing PR branch Previously each run checked out the default branch fresh and force-pushed only the dispatched source's diff to docs/sync-upstream, silently overwriting any earlier dispatched sources' pending changes. Now the workflow: - Checks if docs/sync-upstream exists on the remote; if so, checks it out so prior accumulated changes are part of the working tree. - Resolves the default branch dynamically and passes it to peter-evans as the explicit base so the PR continues targeting the right branch even after we switched off it. Result: sequential dispatches for different sources combine into one PR instead of clobbering each other. Co-Authored-By: Claude Opus 4.7 --- .github/workflows/sync-docs.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.github/workflows/sync-docs.yml b/.github/workflows/sync-docs.yml index 089cc8e..d40d328 100644 --- a/.github/workflows/sync-docs.yml +++ b/.github/workflows/sync-docs.yml @@ -29,6 +29,23 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Resolve PR base and accumulate onto existing sync branch + id: setup + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + base=$(gh repo view --json defaultBranchRef -q .defaultBranchRef.name) + echo "base=$base" >> "$GITHUB_OUTPUT" + if git ls-remote --exit-code --heads origin docs/sync-upstream >/dev/null 2>&1; then + echo "Existing docs/sync-upstream branch found — checking it out so this run accumulates onto pending changes." + git fetch origin docs/sync-upstream:docs/sync-upstream + git checkout docs/sync-upstream + else + echo "No existing sync branch — starting from $base." + fi - name: Install yq run: | @@ -107,6 +124,7 @@ jobs: if: steps.filter.outputs.count != '0' uses: peter-evans/create-pull-request@v6 with: + base: ${{ steps.setup.outputs.base }} branch: docs/sync-upstream delete-branch: true add-paths: "**/*.mdx" From 85d9045f5138d6bb583260eef04f8be9679c6f5b Mon Sep 17 00:00:00 2001 From: Asad Iqbal Date: Wed, 13 May 2026 14:25:22 +0500 Subject: [PATCH 5/5] fix: read sync-sources.yml from base branch, not stale sync branch After the previous fix switched the working tree to docs/sync-upstream to accumulate changes, all subsequent reads of .github/sync-sources.yml were coming from the (potentially stale) sync branch instead of the base branch. If a new source were added or an instruction edited on main while a sync PR was pending, the workflow would silently use the outdated config. Snapshot the mapping to /tmp/sync-sources.yml before any branch switch, and point both the yq filter step and the Claude prompt at the snapshot. Co-Authored-By: Claude Opus 4.7 --- .github/workflows/sync-docs.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/sync-docs.yml b/.github/workflows/sync-docs.yml index d40d328..037180e 100644 --- a/.github/workflows/sync-docs.yml +++ b/.github/workflows/sync-docs.yml @@ -39,6 +39,10 @@ jobs: run: | base=$(gh repo view --json defaultBranchRef -q .defaultBranchRef.name) echo "base=$base" >> "$GITHUB_OUTPUT" + # Snapshot the mapping from the base branch BEFORE possibly switching + # to the sync branch, so we never use a stale config from a pending + # PR (e.g. if a new source was added on main after the PR opened). + cp .github/sync-sources.yml /tmp/sync-sources.yml if git ls-remote --exit-code --heads origin docs/sync-upstream >/dev/null 2>&1; then echo "Existing docs/sync-upstream branch found — checking it out so this run accumulates onto pending changes." git fetch origin docs/sync-upstream:docs/sync-upstream @@ -63,10 +67,10 @@ jobs: if [ -n "$target" ]; then echo "Filtering for source: $target" yq -o=json ".sources[] | select(.id == \"$target\")" \ - .github/sync-sources.yml | jq -s . > /tmp/sources.json + /tmp/sync-sources.yml | jq -s . > /tmp/sources.json else echo "Processing all sources" - yq -o=json '.sources' .github/sync-sources.yml > /tmp/sources.json + yq -o=json '.sources' /tmp/sync-sources.yml > /tmp/sources.json fi count=$(jq length /tmp/sources.json) echo "count=$count" >> "$GITHUB_OUTPUT" @@ -101,7 +105,8 @@ jobs: prompt: | You are syncing this Mintlify docs site with upstream README changes. - The mapping is at `.github/sync-sources.yml`. + The mapping is at `/tmp/sync-sources.yml` (snapshotted from the + base branch at the start of this run, so it is always current). The list of sources to process this run is at `/tmp/sources.json`. For each source, the latest upstream file content is at `/tmp/sync-cache/`. @@ -118,7 +123,8 @@ jobs: the docs page, skip that source — do not edit the file. Do not edit any files outside the `dest` paths listed in the - sources. Do not touch `/tmp/sync-cache/` or `/tmp/sources.json`. + sources. Do not touch `/tmp/sync-cache/`, `/tmp/sources.json`, + or `/tmp/sync-sources.yml`. - name: Open or update PR if: steps.filter.outputs.count != '0'