diff --git a/.github/notify-docs.workflow-template.yml b/.github/notify-docs.workflow-template.yml new file mode 100644 index 0000000..2c608ec --- /dev/null +++ b/.github/notify-docs.workflow-template.yml @@ -0,0 +1,33 @@ +# 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. +# 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` +# - 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..037180e --- /dev/null +++ b/.github/workflows/sync-docs.yml @@ -0,0 +1,149 @@ +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 + +concurrency: + group: sync-docs + cancel-in-progress: false + +jobs: + sync: + 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" + # 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 + git checkout docs/sync-upstream + else + echo "No existing sync branch — starting from $base." + fi + + - name: Install yq + run: | + sudo wget -qO /usr/local/bin/yq \ + https://github.com/mikefarah/yq/releases/download/v4.44.3/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\")" \ + /tmp/sync-sources.yml | jq -s . > /tmp/sources.json + else + echo "Processing all sources" + yq -o=json '.sources' /tmp/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 /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 -> /tmp/sync-cache/$id" + gh api "repos/$repo/contents/$src?ref=$ref" \ + -H "Accept: application/vnd.github.raw" \ + > "/tmp/sync-cache/$id" + done + ls -la /tmp/sync-cache + + - name: Run Claude to update docs + if: steps.filter.outputs.count != '0' + uses: anthropics/claude-code-action@v1 + with: + anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + prompt: | + You are syncing this Mintlify docs site with upstream README changes. + + 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/`. + + For every entry in `/tmp/sources.json`: + 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. + 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 `/tmp/sync-cache/`, `/tmp/sources.json`, + or `/tmp/sync-sources.yml`. + + - name: Open or update PR + 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" + 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