# Build and deploy MkDocs documentation to GitHub Pages (https://rfdetr.roboflow.com/) # using mike for versioned docs. # # Deploy matrix: # push develop → mike deploy develop (rfdetr.roboflow.com/develop/) # push release/latest → mike deploy latest (rfdetr.roboflow.com/latest/) # release published (stable/post) → mike deploy (rfdetr.roboflow.com//; .postN stripped; RC/pre-release skipped) # workflow_dispatch target=develop → same as push develop # workflow_dispatch target=release/latest → same as push release/latest (→ latest alias) # workflow_dispatch target= → mike deploy # # Every deploy also: # - Copies robots.txt, llms.txt, llms-full.txt to gh-pages root # - Regenerates sitemap.xml normalising versioned paths to /latest/ # - Pings IndexNow (Bing) with canonical /latest/ URLs name: Build and Publish Docs on: push: branches: ["release/latest", "develop"] release: types: [published] workflow_dispatch: inputs: target: description: "Deploy target: 'develop', 'release/latest', or a version tag (e.g. '1.2.3'). Determines both the checkout ref and the mike version label." required: true default: "release/latest" # Ensure only one concurrent deployment concurrency: group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.ref_name || github.event_name == 'workflow_dispatch' && inputs.target || github.event_name == 'release' && github.event.release.tag_name || github.ref_name }} cancel-in-progress: true # Restrict permissions by default permissions: contents: write # Required for committing to gh-pages pages: write # Required for deploying to Pages pull-requests: write # Required for PR comments jobs: doc-deploy: name: Publish Docs runs-on: ubuntu-latest environment: name: documentation-deployment url: https://rfdetr.roboflow.com/ timeout-minutes: 10 steps: - name: 🔍 Validate dispatch target if: github.event_name == 'workflow_dispatch' run: | TARGET="${{ inputs.target }}" if [ "$TARGET" = "develop" ] || [ "$TARGET" = "release/latest" ]; then echo "✓ Target '$TARGET' is valid" elif echo "$TARGET" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(\.post[0-9]+)?$'; then echo "✓ Target '$TARGET' is valid (version tag)" else echo "::error::Invalid target '$TARGET'. Must be 'develop', 'release/latest', or a version tag (e.g. '1.2.3' or '1.2.3.post1')" exit 1 fi - name: 📥 Checkout the repository uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: fetch-depth: 0 ref: ${{ inputs.target || github.ref }} - name: 🐍 Install uv and set Python uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 with: python-version: "3.10" activate-environment: true - name: 🏗️ Install dependencies # Install PyTorch CPU-only first (UV_TORCH_BACKEND=cpu works with 'uv pip') run: uv pip install -e ".[plus]" --group docs - name: ⚙️ Configure git for github-actions run: | git config --global user.name "${{ github.actor }}" git config --global user.email "${{ github.actor }}@users.noreply.github.com" - name: 🚀 Deploy Development Docs if: github.event_name == 'push' && github.ref == 'refs/heads/develop' env: MKDOCS_GIT_COMMITTERS_APIKEY: ${{ secrets.GITHUB_TOKEN }} run: uv run --no-sync mike deploy --push develop - name: 🚀 Deploy Latest Branch Docs if: github.event_name == 'push' && github.ref == 'refs/heads/release/latest' env: MKDOCS_GIT_COMMITTERS_APIKEY: ${{ secrets.GITHUB_TOKEN }} run: uv run --no-sync mike deploy --push --update-aliases latest - name: 🚀 Deploy Release Docs if: github.event_name == 'release' && github.event.action == 'published' && !github.event.release.prerelease env: MKDOCS_GIT_COMMITTERS_APIKEY: ${{ secrets.GITHUB_TOKEN }} run: | TAG="${{ github.event.release.tag_name }}" DOC_VERSION="${TAG%.post*}" uv run --no-sync mike deploy --push "$DOC_VERSION" - name: 🚀 Deploy Docs (workflow_dispatch) if: github.event_name == 'workflow_dispatch' env: MKDOCS_GIT_COMMITTERS_APIKEY: ${{ secrets.GITHUB_TOKEN }} run: | TARGET="${{ inputs.target }}" if [ "$TARGET" = "develop" ]; then uv run --no-sync mike deploy --push develop elif [ "$TARGET" = "release/latest" ]; then uv run --no-sync mike deploy --push --update-aliases latest else DOC_VERSION="${TARGET%.post*}" uv run --no-sync mike deploy --push "$DOC_VERSION" fi - name: 🏗️ Build docs for artifact run: uv run --no-sync mkdocs build - name: 📤 Upload docs artifact uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: docs-site path: site/ retention-days: 7 - name: Deploy root static files to gh-pages if: >- (github.event_name == 'push' && (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/release/latest')) || (github.event_name == 'release' && github.event.action == 'published' && !github.event.release.prerelease) || github.event_name == 'workflow_dispatch' run: | cp docs/root-static/robots.txt /tmp/robots.txt cp docs/root-static/llms.txt /tmp/llms.txt cp docs/root-static/llms-full.txt /tmp/llms-full.txt cp docs/root-static/cace9ef287cb8d641db90d4295fcb1e1.txt /tmp/indexnow.txt git fetch origin gh-pages:refs/remotes/origin/gh-pages git checkout -B gh-pages origin/gh-pages cp /tmp/robots.txt robots.txt cp /tmp/llms.txt llms.txt cp /tmp/llms-full.txt llms-full.txt cp /tmp/indexnow.txt cace9ef287cb8d641db90d4295fcb1e1.txt git add robots.txt llms.txt llms-full.txt cace9ef287cb8d641db90d4295fcb1e1.txt # Normalize versioned paths (/X.Y.Z/) to /latest/ so sitemap URLs are # not blocked by the User-agent: * Disallow rules in robots.txt. # latest/ may be a mike alias redirect (no sitemap.xml) — fall back to highest versioned dir. SITEMAP_SRC="" if [ -f latest/sitemap.xml ]; then SITEMAP_SRC="latest/sitemap.xml" else LATEST_VER=$(ls -d [0-9]* 2>/dev/null | grep -E '^[0-9]+\.[0-9]+' | sort -V | tail -1) if [ -n "$LATEST_VER" ] && [ -f "$LATEST_VER/sitemap.xml" ]; then SITEMAP_SRC="$LATEST_VER/sitemap.xml" elif [ -f develop/sitemap.xml ]; then SITEMAP_SRC="develop/sitemap.xml" fi fi if [ -n "$SITEMAP_SRC" ]; then sed 's|rfdetr\.roboflow\.com/[^/]*/|rfdetr.roboflow.com/latest/|g' "$SITEMAP_SRC" > sitemap.xml git add sitemap.xml fi git diff --staged --quiet || git commit -m "chore: update root static files and sitemap" git push origin gh-pages || (git pull --rebase origin gh-pages && git push origin gh-pages) # IndexNow key: cace9ef287cb8d641db90d4295fcb1e1 # Key file served at https://rfdetr.roboflow.com/cace9ef287cb8d641db90d4295fcb1e1.txt # (deployed via "Deploy root static files" step above). # To rotate: generate new key, update docs/root-static/.txt, replace key string here. - name: 📡 Notify IndexNow (Bing) if: >- (github.event_name == 'push' && (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/release/latest')) || (github.event_name == 'release' && github.event.action == 'published' && !github.event.release.prerelease) || github.event_name == 'workflow_dispatch' run: | curl -s -o /dev/null -w "%{http_code}" -X POST "https://api.indexnow.org/IndexNow" \ -H "Content-Type: application/json; charset=utf-8" \ -d '{ "host": "rfdetr.roboflow.com", "key": "cace9ef287cb8d641db90d4295fcb1e1", "keyLocation": "https://rfdetr.roboflow.com/cace9ef287cb8d641db90d4295fcb1e1.txt", "urlList": [ "https://rfdetr.roboflow.com/", "https://rfdetr.roboflow.com/latest/", "https://rfdetr.roboflow.com/latest/learn/install/", "https://rfdetr.roboflow.com/latest/learn/pretrained/", "https://rfdetr.roboflow.com/latest/learn/run/detection/", "https://rfdetr.roboflow.com/latest/learn/run/segmentation/", "https://rfdetr.roboflow.com/latest/learn/train/", "https://rfdetr.roboflow.com/latest/learn/export/", "https://rfdetr.roboflow.com/latest/learn/deploy/", "https://rfdetr.roboflow.com/latest/learn/benchmarks/" ] }' || true - name: Minimize uv cache run: uv cache prune --ci