Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .cursor/rules/diataxis-docs.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
description: Diátaxis documentation standards for the Tap Python SDK
globs: docs/**/*.md,Readme.md,mkdocs.yml
alwaysApply: false
---

# Diátaxis docs guidelines

This repository's docs follow [Diátaxis](https://diataxis.fr/). Keep them consistent with that model.

## Quadrants

| Quadrant | Path | Purpose |
|----------|------|---------|
| Tutorial | `docs/tutorial/` | Learning-oriented; one successful first path |
| How-to | `docs/how-to/` | Problem-oriented recipes for a specific goal |
| Reference | `docs/reference/` | Information-oriented API / type / event facts |
| Explanation | `docs/explanation/` | Understanding-oriented background |

`Readme.md` stays a short overview that links into `docs/` and the published MkDocs site. Do not re-inflate it into a full API manual.

## When a code change requires doc updates

- Public API, callbacks, command semantics, or example behavior → **Reference** (and How-to / Tutorial if the happy path changed)
- New supported task or platform install step → **How-to**
- Conceptual behavior (modes, connection, sensors) → **Explanation**
- First-run experience changes → **Tutorial**
- Docs-only PRs that already match the change → no further edits

## Style

- Prefer clear, unambiguous language; one job per page
- Do not invent features or UUIDs not present in the code
- Keep MkDocs links valid (`mkdocs build --strict` must pass)
- Example file links should point at GitHub `blob` URLs, not `../../examples/...`
- Axis diagrams live under `docs/assets/`

## Published site

Configured by `mkdocs.yml` (Material). GitHub Pages workflow: `.github/workflows/docs.yml`.
26 changes: 26 additions & 0 deletions .github/docs-verify-cli.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"permissions": {
"allow": [
"Read(**/*)",
"Shell(grep)",
"Shell(find)",
"Shell(ls)",
"Shell(git diff)",
"Shell(git log)",
"Shell(git ls-files)",
"Shell(git show)",
"Shell(git status)",
"Shell(test)"
],
"deny": [
"Write(**/*)",
"Shell(git commit)",
"Shell(git push)",
"Shell(git checkout)",
"Shell(gh)",
"Shell(rm)",
"Shell(curl)",
"Shell(wget)"
]
}
}
183 changes: 183 additions & 0 deletions .github/workflows/docs-verify.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
name: Verify docs

on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
paths:
- "tapsdk/**"
- "examples/**"
- "docs/**"
- "Readme.md"
- "mkdocs.yml"
- "requirements-docs.txt"
- ".github/docs-verify-cli.json"
- ".github/workflows/docs-verify.yml"
workflow_dispatch:
inputs:
pr_number:
description: "PR number to verify (required for manual runs)"
required: true
type: string

permissions:
contents: read
pull-requests: write

concurrency:
group: docs-verify-${{ github.event.pull_request.number || inputs.pr_number || github.run_id }}
cancel-in-progress: true

jobs:
verify-docs:
runs-on: ubuntu-latest
steps:
- name: Resolve PR number
id: pr
run: |
if [ "${{ github.event_name }}" = "pull_request" ]; then
echo "number=${{ github.event.pull_request.number }}" >> "$GITHUB_OUTPUT"
echo "base_ref=${{ github.base_ref }}" >> "$GITHUB_OUTPUT"
echo "head_ref=${{ github.head_ref }}" >> "$GITHUB_OUTPUT"
echo "sha=${{ github.event.pull_request.head.sha }}" >> "$GITHUB_OUTPUT"
else
echo "number=${{ inputs.pr_number }}" >> "$GITHUB_OUTPUT"
data=$(gh api "repos/${{ github.repository }}/pulls/${{ inputs.pr_number }}")
echo "base_ref=$(echo "$data" | jq -r .base.ref)" >> "$GITHUB_OUTPUT"
echo "head_ref=$(echo "$data" | jq -r .head.ref)" >> "$GITHUB_OUTPUT"
echo "sha=$(echo "$data" | jq -r .head.sha)" >> "$GITHUB_OUTPUT"
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ steps.pr.outputs.sha }}

- name: Check CURSOR_API_KEY
id: cursor_key
env:
CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }}
run: |
if [ -z "$CURSOR_API_KEY" ]; then
echo "present=false" >> "$GITHUB_OUTPUT"
echo "::warning::CURSOR_API_KEY is not set. Skipping agent verification. Add it under Settings → Secrets → Actions to enable this check."
else
echo "present=true" >> "$GITHUB_OUTPUT"
fi

- name: Notice when verification is skipped
if: steps.cursor_key.outputs.present != 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
MARKER="<!-- cursor-docs-verify -->"
BODY="${MARKER}"$'\n'"## Docs check"$'\n'$'\n'"Verification skipped: repository secret \`CURSOR_API_KEY\` is not configured."$'\n'$'\n'"Add it from [Cursor API Keys](https://cursor.com/dashboard/api), then re-run **Verify docs**."
PR="${{ steps.pr.outputs.number }}"
existing=$(gh api "repos/${{ github.repository }}/issues/${PR}/comments" \
--jq ".[] | select(.body | contains(\"${MARKER}\")) | .id" | head -n1)
if [ -n "${existing}" ]; then
gh api -X PATCH "repos/${{ github.repository }}/issues/comments/${existing}" -f body="$BODY"
else
gh pr comment "$PR" --body "$BODY"
fi

- name: Install Cursor CLI
if: steps.cursor_key.outputs.present == 'true'
run: |
curl https://cursor.com/install -fsS | bash
echo "$HOME/.cursor/bin" >> "$GITHUB_PATH"

- name: Apply verify-only CLI permissions
if: steps.cursor_key.outputs.present == 'true'
run: |
mkdir -p .cursor
cp .github/docs-verify-cli.json .cursor/cli.json

- name: Verify docs
if: steps.cursor_key.outputs.present == 'true'
id: verify
env:
CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }}
run: |
set -euo pipefail
agent -p --mode ask --trust --output-format text \
"You are verifying documentation for TapWithUs/tap-python-sdk PR #${{ steps.pr.outputs.number }}.

Context:
- Base branch: ${{ steps.pr.outputs.base_ref }}
- Head branch: ${{ steps.pr.outputs.head_ref }}
- Guidelines: read .cursor/rules/diataxis-docs.mdc and docs/index.md
- Site config: mkdocs.yml

Steps:
1. Inspect the PR diff (git diff origin/${{ steps.pr.outputs.base_ref }}...HEAD).
2. Decide which Diátaxis quadrants (if any) are affected.
3. Check that docs/, Readme.md, and mkdocs.yml still match the guidelines and the code change.
4. Before claiming any file or asset is missing, verify in the checked-out tree:
- git ls-files -- <path> (required for tracked files, including binaries under docs/assets/)
- test -f <path>
Report a path as missing only when both checks show it is absent.
5. Do not infer absence from the diff alone; binary assets may be added without appearing in text diffs.
6. Do not invent features. If the PR is docs-only and consistent, status is OK.

Output markdown ONLY (no preamble), using exactly this template:

## Docs check
- Status: OK
- Affected quadrants: none | tutorial | how-to | reference | explanation (comma-separated)
- Gaps: none
- Suggested edits: none

If updates are required, use Status: NEEDS UPDATES and replace Gaps / Suggested edits
with concrete file paths and what to change.

Do NOT modify files, commit, push, or call gh." \
| tee /tmp/docs-check.md

- name: Comment on PR
if: steps.cursor_key.outputs.present == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
MARKER="<!-- cursor-docs-verify -->"
RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
PR="${{ steps.pr.outputs.number }}"

if grep -qiE 'Status:[[:space:]]*NEEDS UPDATES' /tmp/docs-check.md || \
! grep -qiE 'Status:[[:space:]]*OK' /tmp/docs-check.md; then
{
printf '%s\n' "$MARKER"
printf 'Workflow run: %s\n\n' "$RUN_URL"
cat /tmp/docs-check.md
} > /tmp/docs-comment.md
gh pr comment "$PR" --body-file /tmp/docs-comment.md
else
{
printf '%s\n' "$MARKER"
cat /tmp/docs-check.md
} > /tmp/docs-comment.md
existing=$(gh api "repos/${{ github.repository }}/issues/${PR}/comments" \
--jq ".[] | select(.body | contains(\"${MARKER}\")) | .id" | head -n1)
if [ -n "${existing}" ]; then
gh api -X PATCH "repos/${{ github.repository }}/issues/comments/${existing}" \
-F "body=@/tmp/docs-comment.md"
else
gh pr comment "$PR" --body-file /tmp/docs-comment.md
fi
fi

- name: Fail when docs need updates
if: steps.cursor_key.outputs.present == 'true'
run: |
if grep -qiE 'Status:[[:space:]]*NEEDS UPDATES' /tmp/docs-check.md; then
gaps=$(sed -n 's/^- Gaps:[[:space:]]*//p' /tmp/docs-check.md | head -n1)
echo "::error::Documentation updates required (see latest PR comment). ${gaps}"
exit 1
fi
if ! grep -qiE 'Status:[[:space:]]*OK' /tmp/docs-check.md; then
echo "::error::Docs check output missing Status: OK or NEEDS UPDATES (see latest PR comment)."
exit 1
fi
83 changes: 83 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
name: Deploy docs

# Test on this PR: the build job runs automatically on pull_request.
# Test full Pages deploy before merge: Actions → Deploy docs → Run workflow
# (select this branch). Requires Pages source = GitHub Actions in repo settings.
on:
push:
branches: [master]
paths:
- "docs/**"
- "docs/assets/**"
- "mkdocs.yml"
- "requirements-docs.txt"
- ".github/workflows/docs.yml"
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
paths:
- "docs/**"
- "docs/assets/**"
- "mkdocs.yml"
- "requirements-docs.txt"
- ".github/workflows/docs.yml"
workflow_dispatch:
inputs:
deploy:
description: "Upload artifact and deploy to GitHub Pages"
type: boolean
default: true

permissions:
contents: read
pages: write
id-token: write

concurrency:
group: pages
cancel-in-progress: false

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Cache MkDocs
uses: actions/cache@v4
with:
path: ~/.cache
key: mkdocs-material-${{ hashFiles('requirements-docs.txt') }}
restore-keys: |
mkdocs-material-

- name: Install docs dependencies
run: pip install -r requirements-docs.txt

- name: Build site
run: mkdocs build --strict --clean

- name: Upload Pages artifact
if: >
github.event_name == 'push' ||
(github.event_name == 'workflow_dispatch' && inputs.deploy)
uses: actions/upload-pages-artifact@v3
with:
path: site

deploy:
if: >
github.event_name == 'push' ||
(github.event_name == 'workflow_dispatch' && inputs.deploy)
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
Loading
Loading