Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 0
docs: add automated upstream sync workflow#27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
5065236d750493a4e15258194a2e85d9045File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| # Template — copy into each upstream source repo as | ||
| # .github/workflows/notify-docs.yml | ||
| # | ||
| # Replace <SOURCE_ID> 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]=<SOURCE_ID>' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
cursor[bot] marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| - 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: | ||
cursor[bot] marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| 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/<id>`. | ||
| For every entry in `/tmp/sources.json`: | ||
| 1. Read `/tmp/sync-cache/<id>` (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 | ||
cursor[bot] marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. cursor[bot] marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.