From e62a5d848844eedd0e1b60cc4ac5fbea73527d05 Mon Sep 17 00:00:00 2001 From: Matt Linville Date: Tue, 13 Jan 2026 16:13:34 -0800 Subject: [PATCH 01/13] Turn on recursive link checking for the PR link checker --- .github/workflows/linkcheck-pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linkcheck-pr.yml b/.github/workflows/linkcheck-pr.yml index b498e5973b..7c76979e4d 100644 --- a/.github/workflows/linkcheck-pr.yml +++ b/.github/workflows/linkcheck-pr.yml @@ -25,7 +25,7 @@ jobs: id: lychee uses: lycheeverse/lychee-action@v2 with: - args: "--threads 5 --max-retries 5 --retry-wait-time 2 --include '^https?://' --include '^http?://' --base-url='${{ github.event.deployment_status.environment_url }}' '${{ github.event.deployment_status.environment_url }}'" + args: "--threads 5 --max-retries 5 --retry-wait-time 2 --include '^https?://' --include '^http?://' --base-url='${{ github.event.deployment_status.environment_url }}' '.'" format: markdown fail: false env: From e6f1d18c95bed5605008e81ef0e32ede965a1d29 Mon Sep 17 00:00:00 2001 From: Matt Linville Date: Tue, 13 Jan 2026 16:22:19 -0800 Subject: [PATCH 02/13] Update Lychee link check actions to be recursive - For the PR check, change the target to check to . to recursively check all supported files for http:// and https:// links to check - For the Prod check, Lychee doesn't support crawling. Instead, fetch and parse the live site map for live URLs to check individually for broken http:// and https:// links --- .github/workflows/linkcheck-prod.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linkcheck-prod.yml b/.github/workflows/linkcheck-prod.yml index a72662d688..382f31f957 100644 --- a/.github/workflows/linkcheck-prod.yml +++ b/.github/workflows/linkcheck-prod.yml @@ -11,14 +11,20 @@ jobs: permissions: issues: write # required for peter-evans/create-issue-from-file steps: - # check URLs with Lychee - uses: actions/checkout@v6 + - name: Download and parse sitemap + run: | + curl -s https://docs.wandb.ai/sitemap.xml | \ + grep -o '[^<]*' | \ + sed 's///g; s/<\/loc>//g' > urls.txt + echo "Found $(wc -l < urls.txt) URLs in sitemap" + - name: Link Checker id: lychee uses: lycheeverse/lychee-action@v2 with: - args: "--threads 5 --max-retries 5 --retry-wait-time 2 --include '^https?://' --include '^http?://' --base-url='http://docs.wandb.ai' 'http://docs.wandb.ai'" + args: "--threads 5 --max-retries 5 --retry-wait-time 2 --include '^https?://' --include '^http?://' urls.txt" output: ./lychee-report.md format: markdown fail: false From 4f0cefdd610fbaf4ba0531324ac2ce87b3278d08 Mon Sep 17 00:00:00 2001 From: Matt Linville Date: Tue, 13 Jan 2026 16:22:19 -0800 Subject: [PATCH 03/13] Update Lychee link check actions to be recursive - For the PR check, change the target to check to . to recursively check all supported files for http:// and https:// links to check - For the Prod check, Lychee doesn't support crawling. Instead, fetch and parse the live site map for live URLs to check individually for broken http:// and https:// links --- .github/workflows/linkcheck-pr.yml | 2 +- .github/workflows/linkcheck-prod.yml | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/linkcheck-pr.yml b/.github/workflows/linkcheck-pr.yml index b498e5973b..7c76979e4d 100644 --- a/.github/workflows/linkcheck-pr.yml +++ b/.github/workflows/linkcheck-pr.yml @@ -25,7 +25,7 @@ jobs: id: lychee uses: lycheeverse/lychee-action@v2 with: - args: "--threads 5 --max-retries 5 --retry-wait-time 2 --include '^https?://' --include '^http?://' --base-url='${{ github.event.deployment_status.environment_url }}' '${{ github.event.deployment_status.environment_url }}'" + args: "--threads 5 --max-retries 5 --retry-wait-time 2 --include '^https?://' --include '^http?://' --base-url='${{ github.event.deployment_status.environment_url }}' '.'" format: markdown fail: false env: diff --git a/.github/workflows/linkcheck-prod.yml b/.github/workflows/linkcheck-prod.yml index a72662d688..382f31f957 100644 --- a/.github/workflows/linkcheck-prod.yml +++ b/.github/workflows/linkcheck-prod.yml @@ -11,14 +11,20 @@ jobs: permissions: issues: write # required for peter-evans/create-issue-from-file steps: - # check URLs with Lychee - uses: actions/checkout@v6 + - name: Download and parse sitemap + run: | + curl -s https://docs.wandb.ai/sitemap.xml | \ + grep -o '[^<]*' | \ + sed 's///g; s/<\/loc>//g' > urls.txt + echo "Found $(wc -l < urls.txt) URLs in sitemap" + - name: Link Checker id: lychee uses: lycheeverse/lychee-action@v2 with: - args: "--threads 5 --max-retries 5 --retry-wait-time 2 --include '^https?://' --include '^http?://' --base-url='http://docs.wandb.ai' 'http://docs.wandb.ai'" + args: "--threads 5 --max-retries 5 --retry-wait-time 2 --include '^https?://' --include '^http?://' urls.txt" output: ./lychee-report.md format: markdown fail: false From b6b441b085d56b8e260e76f50db7fb075719eb6d Mon Sep 17 00:00:00 2001 From: Matt Linville Date: Tue, 13 Jan 2026 16:55:35 -0800 Subject: [PATCH 04/13] Fix broken links to /weave/guides/core-types/ pages by using absolute paths --- weave/cookbooks/source/dspy_prompt_optimization.ipynb | 4 ++-- weave/guides/integrations/notdiamond.mdx | 4 ++-- .../reference/generated_typescript_docs/intro-notebook.mdx | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/weave/cookbooks/source/dspy_prompt_optimization.ipynb b/weave/cookbooks/source/dspy_prompt_optimization.ipynb index 14afde3f63..8ce172ec72 100644 --- a/weave/cookbooks/source/dspy_prompt_optimization.ipynb +++ b/weave/cookbooks/source/dspy_prompt_optimization.ipynb @@ -127,7 +127,7 @@ "source": [ "## Load the BIG-Bench Hard Dataset\n", "\n", - "We will load this dataset from HuggingFace Hub, split into training and validation sets, and [publish](../../guides/core-types/datasets.md) them on Weave, this will let us version the datasets, and also use [`weave.Evaluation`](../../guides/core-types/evaluations.md) to evaluate our prompting strategy." + "We will load this dataset from HuggingFace Hub, split into training and validation sets, and [publish](/weave/guides/core-types/datasets) them on Weave, this will let us version the datasets, and also use [`weave.Evaluation`](/weave/guides/core-types/evaluations) to evaluate our prompting strategy." ] }, { @@ -287,7 +287,7 @@ "source": [ "## Evaluating our DSPy Program\n", "\n", - "Now that we have a baseline prompting strategy, let's evaluate it on our validation set using [`weave.Evaluation`](../../guides/core-types/evaluations.md) on a simple metric that matches the predicted answer with the ground truth. Weave will take each example, pass it through your application and score the output on multiple custom scoring functions. By doing this, you'll have a view of the performance of your application, and a rich UI to drill into individual outputs and scores.\n", + "Now that we have a baseline prompting strategy, let's evaluate it on our validation set using [`weave.Evaluation`](/weave/guides/core-types/evaluations) on a simple metric that matches the predicted answer with the ground truth. Weave will take each example, pass it through your application and score the output on multiple custom scoring functions. By doing this, you'll have a view of the performance of your application, and a rich UI to drill into individual outputs and scores.\n", "\n", "First, we need to create a simple weave evaluation scoring function that tells whether the answer from the baseline module's output is the same as the ground truth answer or not. Scoring functions need to have a `model_output` keyword argument, but the other arguments are user defined and are taken from the dataset examples. It will only take the necessary keys by using a dictionary key based on the argument name." ] diff --git a/weave/guides/integrations/notdiamond.mdx b/weave/guides/integrations/notdiamond.mdx index 638b5c0c60..0fba392dfd 100644 --- a/weave/guides/integrations/notdiamond.mdx +++ b/weave/guides/integrations/notdiamond.mdx @@ -107,10 +107,10 @@ Visit the [docs] or [send us a message][support] for further support. [chat]: https://chat.notdiamond.ai [custom router]: https://docs.notdiamond.ai/docs/router-training-quickstart [docs]: https://docs.notdiamond.ai -[evals]: ../../guides/core-types/evaluations.mdx +[evals]: /weave/guides/core-types/evaluations [keys]: https://app.notdiamond.ai/keys [nd]: https://www.notdiamond.ai/ -[ops]: ../../guides/tracking/ops.mdx +[ops]: /weave/guides/tracking/ops [python]: https://github.com/Not-Diamond/notdiamond-python [quickstart guide]: https://docs.notdiamond.ai/docs/quickstart [support]: mailto:support@notdiamond.ai diff --git a/weave/reference/generated_typescript_docs/intro-notebook.mdx b/weave/reference/generated_typescript_docs/intro-notebook.mdx index e2fc3d080d..8fb47c5974 100644 --- a/weave/reference/generated_typescript_docs/intro-notebook.mdx +++ b/weave/reference/generated_typescript_docs/intro-notebook.mdx @@ -106,7 +106,7 @@ async function demonstrateNestedTracking() { ## Dataset management -You can create and manage datasets with Weave using the [`weave.Dataset`](../../guides/core-types/datasets.mdx) class. Similar to [Weave `Models`](../../guides/core-types/models.mdx), `weave.Dataset` helps: +You can create and manage datasets with Weave using the [`weave.Dataset`](/weave/guides/core-types/datasets) class. Similar to [Weave `Models`](/weave/guides/core-types/models), `weave.Dataset` helps: - Track and version your data - Organize test cases @@ -144,7 +144,7 @@ function createGrammarDataset(): weave.Dataset { ## Evaluation framework -Weave supports evaluation-driven development with the [`Evaluation` class](../../guides/core-types/evaluations.mdx). Evaluations help you reliably iterate on your GenAI application. The `Evaluation` class does the following: +Weave supports evaluation-driven development with the [`Evaluation` class](/weave/guides/core-types/evaluations). Evaluations help you reliably iterate on your GenAI application. The `Evaluation` class does the following: - Assesses `Model` performance on a `Dataset` - Applies custom scoring functions @@ -224,4 +224,4 @@ async function main() { console.error('Error running demonstrations:', error); } } -``` \ No newline at end of file +``` From 6d1e16c8d6ec427a91433ec80fd9d4a1e1fc00b4 Mon Sep 17 00:00:00 2001 From: Matt Linville Date: Tue, 13 Jan 2026 17:22:09 -0800 Subject: [PATCH 05/13] Apply suggestion from @mdlinville --- .github/workflows/linkcheck-pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linkcheck-pr.yml b/.github/workflows/linkcheck-pr.yml index 7c76979e4d..924aee81ef 100644 --- a/.github/workflows/linkcheck-pr.yml +++ b/.github/workflows/linkcheck-pr.yml @@ -25,7 +25,7 @@ jobs: id: lychee uses: lycheeverse/lychee-action@v2 with: - args: "--threads 5 --max-retries 5 --retry-wait-time 2 --include '^https?://' --include '^http?://' --base-url='${{ github.event.deployment_status.environment_url }}' '.'" + args: "--threads 5 --max-retries 5 --retry-wait-time 2 --exclude '/ja' --exclude '/ko' --include '^https?://' --include '^http?://' --base-url='${{ github.event.deployment_status.environment_url }}' '.'" format: markdown fail: false env: From bc1542784add651830b324079f6c75a3a7f78aac Mon Sep 17 00:00:00 2001 From: Matt Linville Date: Wed, 14 Jan 2026 12:44:10 -0800 Subject: [PATCH 06/13] Update link checker actions with David F's optimizations --- .github/workflows/linkcheck-pr.yml | 150 ++++++++++++++++++++++++--- .github/workflows/linkcheck-prod.yml | 24 +++-- lychee.toml | 51 +++++++++ 3 files changed, 205 insertions(+), 20 deletions(-) create mode 100644 lychee.toml diff --git a/.github/workflows/linkcheck-pr.yml b/.github/workflows/linkcheck-pr.yml index 7c76979e4d..5d73c3d7f8 100644 --- a/.github/workflows/linkcheck-pr.yml +++ b/.github/workflows/linkcheck-pr.yml @@ -1,33 +1,159 @@ -name: Lychee PR link checker +name: Link checker - PR changed files + +# Avoid collisions by ensuring only one run per ref +concurrency: + group: linkcheck-pr-${{ github.ref_name }} + cancel-in-progress: false on: + workflow_dispatch: deployment_status: permissions: contents: read deployments: read + pull-requests: write jobs: linkChecker: runs-on: ubuntu-latest - + # Only run when Mintlify PR deployment succeeds if: | - github.event.deployment_status.state == 'success' && - github.event.deployment.environment == 'staging' && - contains(github.event.deployment_status.creator.login, 'mintlify') && - contains(github.event.deployment_status.environment_url, 'mintlify') + github.event_name == 'workflow_dispatch' || + (github.event_name == 'deployment_status' && + github.event.deployment_status.state == 'success' && + github.event.deployment.environment == 'staging' && + contains(github.event.deployment_status.creator.login, 'mintlify') && + contains(github.event.deployment_status.environment_url, 'mintlify')) + steps: - # check URLs with Lychee - uses: actions/checkout@v6 + with: + # Needed to diff base..head for the associated PR + fetch-depth: 0 + + - name: Resolve PR and deployment URL + id: pr-context + if: github.event_name == 'deployment_status' + uses: actions/github-script@v7 + with: + script: | + const { owner, repo } = context.repo; + const sha = context.payload.deployment?.sha; + const deployUrl = + context.payload.deployment_status?.environment_url || + context.payload.deployment_status?.target_url || + ''; + + core.info(`Deployment SHA: ${sha}`); + core.info(`Deployment URL: ${deployUrl}`); + + // Find PR(s) associated with this deployment commit SHA + const prsResp = await github.rest.repos.listPullRequestsAssociatedWithCommit({ + owner, + repo, + commit_sha: sha, + }); + + const pr = prsResp.data?.[0]; + if (!pr) { + core.warning(`No PR associated with commit ${sha}. Skipping linkcheck + PR comment.`); + core.setOutput('pr_number', ''); + core.setOutput('deploy_url', deployUrl); + return; + } + + core.info(`Associated PR: #${pr.number} (${pr.html_url})`); + core.setOutput('pr_number', String(pr.number)); + core.setOutput('base_sha', pr.base.sha); + core.setOutput('head_sha', pr.head.sha); + core.setOutput('deploy_url', deployUrl); + + - name: Get changed documentation files + id: changed-files + if: steps.pr-context.outputs.pr_number != '' || github.event_name == 'workflow_dispatch' + uses: tj-actions/changed-files@v47.0.1 + with: + base_sha: ${{ steps.pr-context.outputs.base_sha }} + sha: ${{ steps.pr-context.outputs.head_sha }} + files: | + **/*.md + **/*.mdx - name: Link Checker id: lychee + if: steps.changed-files.outputs.any_changed == 'true' || github.event_name == 'workflow_dispatch' uses: lycheeverse/lychee-action@v2 with: - args: "--threads 5 --max-retries 5 --retry-wait-time 2 --include '^https?://' --include '^http?://' --base-url='${{ github.event.deployment_status.environment_url }}' '.'" - format: markdown + # Configuration is in lychee.toml + # Don't fail the workflow on broken links (informational only) fail: false - env: - # to be used in case rate limits are surpassed - GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} + # Don't fail if no files to check + failIfEmpty: false + # Output format for reports + format: markdown + # GitHub token for API rate limiting + token: ${{ secrets.GITHUB_TOKEN }} + # Override base_url with the deployment URL and check only changed files + args: >- + --base-url ${{ steps.pr-context.outputs.deploy_url || 'https://docs.wandb.ai' }} + ${{ steps.changed-files.outputs.all_changed_files || '.' }} + + - name: Comment PR with link check results + if: steps.pr-context.outputs.pr_number != '' && (steps.changed-files.outputs.any_changed == 'true' || github.event_name == 'workflow_dispatch') + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + const identifier = ''; + + let commentBody = identifier + '\n'; + + if (${{ steps.lychee.outputs.exit_code }} === 0) { + // Success - no broken links + commentBody += '## 🔗 Link Checker Results\n\n'; + commentBody += '✅ **All links are valid!**\n\n'; + commentBody += 'No broken links were detected in the changed files.\n'; + } else { + // Issues found - include report + const report = fs.readFileSync('./lychee/out.md', 'utf8'); + + commentBody += '## 🔗 Link Checker Results\n\n'; + commentBody += '> [!NOTE]\n'; + commentBody += '> Links to **newly created files** in this PR may be reported as broken because this checks links against the **preview deployment**.\n'; + commentBody += '> \n'; + commentBody += '> Warnings about **new** files in this PR can be safely ignored.\n\n'; + commentBody += '---\n\n'; + commentBody += report; + } + + // Find existing comment + const prNumber = Number('${{ steps.pr-context.outputs.pr_number }}'); + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + }); + + const existingComment = comments.find(comment => + comment.body?.includes(identifier) && comment.user?.login === 'github-actions[bot]' + ); + + if (existingComment) { + // Update existing comment + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: existingComment.id, + body: commentBody + }); + } else { + // Create new comment + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: commentBody + }); + } diff --git a/.github/workflows/linkcheck-prod.yml b/.github/workflows/linkcheck-prod.yml index 382f31f957..62f0d2dfc1 100644 --- a/.github/workflows/linkcheck-prod.yml +++ b/.github/workflows/linkcheck-prod.yml @@ -1,36 +1,44 @@ -name: Lychee production link checker +name: Link checker - production site + on: repository_dispatch: workflow_dispatch: schedule: - - cron: "5 0 1 * *" # In UTC, currently 12:05 AM on the 1st of each month + - cron: "5 0 1 * *" # Monthly on the 1st at 12:05 AM UTC jobs: linkChecker: runs-on: ubuntu-latest permissions: - issues: write # required for peter-evans/create-issue-from-file + issues: write # Required for creating issues steps: - uses: actions/checkout@v6 - name: Download and parse sitemap run: | + echo "Fetching sitemap from https://docs.wandb.ai/sitemap.xml..." curl -s https://docs.wandb.ai/sitemap.xml | \ grep -o '[^<]*' | \ sed 's///g; s/<\/loc>//g' > urls.txt - echo "Found $(wc -l < urls.txt) URLs in sitemap" + + URL_COUNT=$(wc -l < urls.txt | tr -d ' ') + echo "Found ${URL_COUNT} URLs in sitemap" + + # Show first few URLs for verification + echo "Sample URLs:" + head -5 urls.txt - name: Link Checker id: lychee uses: lycheeverse/lychee-action@v2 with: - args: "--threads 5 --max-retries 5 --retry-wait-time 2 --include '^https?://' --include '^http?://' urls.txt" + # Configuration is in lychee.toml + # Check all URLs from sitemap + args: "urls.txt" output: ./lychee-report.md format: markdown fail: false - env: - # to be used in case rate limits are surpassed - GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} + token: ${{ secrets.GITHUB_TOKEN }} - name: Create Issue From File if: steps.lychee.outputs.exit_code != 0 diff --git a/lychee.toml b/lychee.toml new file mode 100644 index 0000000000..bcfa183b3b --- /dev/null +++ b/lychee.toml @@ -0,0 +1,51 @@ +# Lychee link checker configuration +# See https://lychee.cli.rs/guides/config/ for full documentation + +# Base URL for resolving relative links +# This will be overridden at runtime by the workflows +base_url = 'https://docs.wandb.ai' + +# Don't check heading anchors (fragments) - Mintlify generates these dynamically +include_fragments = false + +# Suppress progress bars in CI for cleaner logs +no_progress = true + +# Exclude private/internal network links +exclude_all_private = true + +# Retry configuration for handling transient failures +max_retries = 5 +retry_wait_time = 2 + +# Accept these HTTP status codes as valid +accept = [ + 200, # OK + 429, # Too Many Requests (rate limit - treat as success) +] + +# Only check HTTP/HTTPS URLs +scheme = [ + "https", + "http", +] + +# Logging verbosity +verbose = "info" + +# URL patterns to exclude from checking +exclude = [ + # Exclude images - Mintlify rewrites paths during build + '\.(png|jpg|jpeg|gif|svg|webp|ico)$', +] + +# File/directory paths to exclude from checking +exclude_path = [ + # Exclude localized content directories + "ja", + "ko", + # Exclude non-documentation directories + "scripts", + "node_modules", + ".github", +] From 131e57651cc5529097d1ad277a5d68c4ee51e84b Mon Sep 17 00:00:00 2001 From: Matt Linville Date: Wed, 14 Jan 2026 12:54:03 -0800 Subject: [PATCH 07/13] Try including Japanese and Korean since this is so fast --- lychee.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/lychee.toml b/lychee.toml index bcfa183b3b..df0072a61a 100644 --- a/lychee.toml +++ b/lychee.toml @@ -41,9 +41,6 @@ exclude = [ # File/directory paths to exclude from checking exclude_path = [ - # Exclude localized content directories - "ja", - "ko", # Exclude non-documentation directories "scripts", "node_modules", From edbf694ae32b3c8b30f59f1130ac4e2baca456d2 Mon Sep 17 00:00:00 2001 From: Matt Linville Date: Wed, 14 Jan 2026 12:58:29 -0800 Subject: [PATCH 08/13] Fix bug that excludes all URLs --- lychee.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lychee.toml b/lychee.toml index df0072a61a..a62763ed06 100644 --- a/lychee.toml +++ b/lychee.toml @@ -30,6 +30,11 @@ scheme = [ "http", ] +# Only check URLs matching these patterns (required when checking URL lists) +include = [ + '^https?://', # Match all http:// and https:// URLs +] + # Logging verbosity verbose = "info" From a27c5e59d27b48d392ace4cd1f5ac781060fb2d1 Mon Sep 17 00:00:00 2001 From: Matt Linville Date: Wed, 14 Jan 2026 13:11:17 -0800 Subject: [PATCH 09/13] Add PR triggers to PR checks so they can run in forks --- .github/workflows/linkcheck-pr.yml | 43 ++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/.github/workflows/linkcheck-pr.yml b/.github/workflows/linkcheck-pr.yml index 5d73c3d7f8..9d4b919f8b 100644 --- a/.github/workflows/linkcheck-pr.yml +++ b/.github/workflows/linkcheck-pr.yml @@ -8,6 +8,11 @@ concurrency: on: workflow_dispatch: deployment_status: + pull_request: + types: [opened, synchronize, reopened] + paths: + - '**.md' + - '**.mdx' permissions: contents: read @@ -18,9 +23,10 @@ jobs: linkChecker: runs-on: ubuntu-latest - # Only run when Mintlify PR deployment succeeds + # Run on: manual trigger, successful Mintlify deployment, or PR events (for forks) if: | github.event_name == 'workflow_dispatch' || + github.event_name == 'pull_request' || (github.event_name == 'deployment_status' && github.event.deployment_status.state == 'success' && github.event.deployment.environment == 'staging' && @@ -72,11 +78,11 @@ jobs: - name: Get changed documentation files id: changed-files - if: steps.pr-context.outputs.pr_number != '' || github.event_name == 'workflow_dispatch' + if: steps.pr-context.outputs.pr_number != '' || github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request' uses: tj-actions/changed-files@v47.0.1 with: - base_sha: ${{ steps.pr-context.outputs.base_sha }} - sha: ${{ steps.pr-context.outputs.head_sha }} + base_sha: ${{ steps.pr-context.outputs.base_sha || github.event.pull_request.base.sha }} + sha: ${{ steps.pr-context.outputs.head_sha || github.event.pull_request.head.sha }} files: | **/*.md **/*.mdx @@ -95,13 +101,14 @@ jobs: format: markdown # GitHub token for API rate limiting token: ${{ secrets.GITHUB_TOKEN }} - # Override base_url with the deployment URL and check only changed files + # Override base_url with deployment URL (if available) or use production + # For forks without Mintlify preview: checks against production site args: >- --base-url ${{ steps.pr-context.outputs.deploy_url || 'https://docs.wandb.ai' }} ${{ steps.changed-files.outputs.all_changed_files || '.' }} - name: Comment PR with link check results - if: steps.pr-context.outputs.pr_number != '' && (steps.changed-files.outputs.any_changed == 'true' || github.event_name == 'workflow_dispatch') + if: (steps.pr-context.outputs.pr_number != '' || github.event_name == 'pull_request') && (steps.changed-files.outputs.any_changed == 'true' || github.event_name == 'workflow_dispatch') uses: actions/github-script@v7 with: script: | @@ -110,26 +117,46 @@ jobs: let commentBody = identifier + '\n'; + const isFork = context.payload.pull_request?.head?.repo?.fork || false; + const deployUrl = '${{ steps.pr-context.outputs.deploy_url }}'; + if (${{ steps.lychee.outputs.exit_code }} === 0) { // Success - no broken links commentBody += '## 🔗 Link Checker Results\n\n'; commentBody += '✅ **All links are valid!**\n\n'; commentBody += 'No broken links were detected in the changed files.\n'; + if (isFork && !deployUrl) { + commentBody += '\n_Note: Checked against production site (https://docs.wandb.ai) since preview deployments are not available for forks._\n'; + } } else { // Issues found - include report const report = fs.readFileSync('./lychee/out.md', 'utf8'); commentBody += '## 🔗 Link Checker Results\n\n'; commentBody += '> [!NOTE]\n'; - commentBody += '> Links to **newly created files** in this PR may be reported as broken because this checks links against the **preview deployment**.\n'; + if (isFork && !deployUrl) { + commentBody += '> This PR is from a fork, so links were checked against the **production site** (https://docs.wandb.ai).\n'; + commentBody += '> \n'; + commentBody += '> Links to **newly created files** in this PR will be reported as broken until the PR is merged.\n'; + } else { + commentBody += '> Links to **newly created files** in this PR may be reported as broken because this checks links against the **preview deployment**.\n'; + } commentBody += '> \n'; commentBody += '> Warnings about **new** files in this PR can be safely ignored.\n\n'; commentBody += '---\n\n'; commentBody += report; } + // Determine PR number + const prNumber = Number('${{ steps.pr-context.outputs.pr_number }}') || + context.payload.pull_request?.number; + + if (!prNumber) { + core.info('No PR number available, skipping comment'); + return; + } + // Find existing comment - const prNumber = Number('${{ steps.pr-context.outputs.pr_number }}'); const { data: comments } = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, From b98aa3b65a2cd3a6a9ae8b99468acd52d76c7bc4 Mon Sep 17 00:00:00 2001 From: Matt Linville Date: Wed, 14 Jan 2026 13:59:18 -0800 Subject: [PATCH 10/13] Add hint about redirects caused by trailing slashes on the Mintlify SaaS --- .github/workflows/linkcheck-pr.yml | 33 ++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linkcheck-pr.yml b/.github/workflows/linkcheck-pr.yml index 9d4b919f8b..da5561ea38 100644 --- a/.github/workflows/linkcheck-pr.yml +++ b/.github/workflows/linkcheck-pr.yml @@ -92,8 +92,8 @@ jobs: if: steps.changed-files.outputs.any_changed == 'true' || github.event_name == 'workflow_dispatch' uses: lycheeverse/lychee-action@v2 with: - # Configuration is in lychee.toml - # Don't fail the workflow on broken links (informational only) + args: "--threads 5 --max-retries 5 --retry-wait-time 2 --exclude '/ja' --exclude '/ko' --include '^https?://' --include '^http?://' --base-url='${{ github.event.deployment_status.environment_url }}' '.'" + format: markdown fail: false # Don't fail if no files to check failIfEmpty: false @@ -128,6 +128,22 @@ jobs: if (isFork && !deployUrl) { commentBody += '\n_Note: Checked against production site (https://docs.wandb.ai) since preview deployments are not available for forks._\n'; } + + // Check if there were redirects in the report + try { + const report = fs.readFileSync('./lychee/out.md', 'utf8'); + if (report.includes('Redirect') || report.includes('redirect')) { + commentBody += '\n\n> [!TIP]\n'; + commentBody += '> **Redirects detected**: If you see redirects for internal docs.wandb.ai links, check if they have trailing slashes.\n'; + commentBody += '> \n'; + commentBody += '> Mintlify automatically removes trailing slashes, causing redirects like:\n'; + commentBody += '> - `https://docs.wandb.ai/models/` → `https://docs.wandb.ai/models`\n'; + commentBody += '> \n'; + commentBody += '> **Fix**: Remove trailing slashes from links to avoid unnecessary redirects.\n'; + } + } catch (e) { + // Ignore if report file doesn't exist + } } else { // Issues found - include report const report = fs.readFileSync('./lychee/out.md', 'utf8'); @@ -143,6 +159,19 @@ jobs: } commentBody += '> \n'; commentBody += '> Warnings about **new** files in this PR can be safely ignored.\n\n'; + + // Add trailing slash tip if redirects are present + if (report.includes('Redirect') || report.includes('redirect')) { + commentBody += '> [!TIP]\n'; + commentBody += '> **Redirects detected**: If you see redirects for internal docs.wandb.ai links, check if they have trailing slashes.\n'; + commentBody += '> \n'; + commentBody += '> Mintlify automatically removes trailing slashes, causing redirects like:\n'; + commentBody += '> - `https://docs.wandb.ai/models/` → `https://docs.wandb.ai/models`\n'; + commentBody += '> - `/weave/quickstart/` → `/weave/quickstart`\n'; + commentBody += '> \n'; + commentBody += '> **Fix**: Remove trailing slashes from links to avoid unnecessary redirects.\n\n'; + } + commentBody += '---\n\n'; commentBody += report; } From b55691087f440a241fba58e178e098d5746a8bad Mon Sep 17 00:00:00 2001 From: Matt Linville Date: Wed, 14 Jan 2026 14:04:37 -0800 Subject: [PATCH 11/13] Remove duplicate args --- .github/workflows/linkcheck-pr.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/linkcheck-pr.yml b/.github/workflows/linkcheck-pr.yml index da5561ea38..e6a473b4b6 100644 --- a/.github/workflows/linkcheck-pr.yml +++ b/.github/workflows/linkcheck-pr.yml @@ -92,8 +92,6 @@ jobs: if: steps.changed-files.outputs.any_changed == 'true' || github.event_name == 'workflow_dispatch' uses: lycheeverse/lychee-action@v2 with: - args: "--threads 5 --max-retries 5 --retry-wait-time 2 --exclude '/ja' --exclude '/ko' --include '^https?://' --include '^http?://' --base-url='${{ github.event.deployment_status.environment_url }}' '.'" - format: markdown fail: false # Don't fail if no files to check failIfEmpty: false From 01193f2920e2df6f15f221e9e779184a3fe5eae7 Mon Sep 17 00:00:00 2001 From: Matt Linville Date: Wed, 14 Jan 2026 13:18:52 -0800 Subject: [PATCH 12/13] Break a link to test the PR link checker --- index.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/index.mdx b/index.mdx index b9b26147e9..a472bd6bfa 100644 --- a/index.mdx +++ b/index.mdx @@ -19,6 +19,7 @@ import {ProductCard} from "/snippets/ProductCard.jsx"; Use W&B Models to manage AI model development. Features include training, fine-tuning, reporting, automating hyperparameter sweeps, and utilizing the model registry for versioning and reproducibility.

+ • Totally invalid link
• Introduction
• Quickstart
• YouTube Tutorial
From 32a02ef1ec40527f2f6a95da8c2137c6ca72535b Mon Sep 17 00:00:00 2001 From: Matt Linville Date: Wed, 14 Jan 2026 13:22:42 -0800 Subject: [PATCH 13/13] Break more links in more files to validate that the PR check only checks changed files --- get-started.mdx | 3 +++ models/quickstart.mdx | 2 +- weave/quickstart.mdx | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/get-started.mdx b/get-started.mdx index 9fb9d882b7..7afa28a84f 100644 --- a/get-started.mdx +++ b/get-started.mdx @@ -26,6 +26,9 @@ Welcome to Weights & Biases! Before getting started with our products, it's impo A video-led course that emphasizes experiment tracking and features quizzes to ensure comprehension. + + Check out example code for getting started (this is a broken test link). + Learn how models are trained, evaluated, developed, and deployed and how you can use wandb at each step of that lifecycle to help build better performing models faster. diff --git a/models/quickstart.mdx b/models/quickstart.mdx index 720caf5fdd..8d6bad7da7 100644 --- a/models/quickstart.mdx +++ b/models/quickstart.mdx @@ -8,7 +8,7 @@ import ApiKeyCreate from "/snippets/en/_includes/api-key-create.mdx"; Install W&B to track, visualize, and manage machine learning experiments of any size. -Are you looking for information on W&B Weave? See the [Weave Python SDK quickstart](/weave/quickstart) or [Weave TypeScript SDK quickstart](/weave/reference/generated_typescript_docs/intro-notebook). +Are you looking for information on W&B Weave? See the [Weave Python SDK quickstart](/weave/quickstart) or [Weave TypeScript SDK quickstart](/weave/reference/generated_typescript_docs/intro-notebook). For advanced features, see the [Advanced Guide](/models/nonexistent-advanced-guide-xyz123). ## Sign up and create an API key diff --git a/weave/quickstart.mdx b/weave/quickstart.mdx index 0f0b3e07da..895cbf101a 100644 --- a/weave/quickstart.mdx +++ b/weave/quickstart.mdx @@ -11,6 +11,7 @@ import WeaveQuickstartPrereqs from "/snippets/en/_includes/weave-quickstart-prer Learn how to track LLM calls with Weave by adding tracing to your code. This quickstart walks you through tracing a request to OpenAI and viewing the results in the Weave UI. @@ -159,4 +160,4 @@ Click the link in your terminal or paste it into your browser to open the Weave ## Next Steps -[Get started evaluating your app](/weave/tutorial-eval) and then see how to [evaluate a RAG application](/weave/tutorial-rag). \ No newline at end of file +[Get started evaluating your app](/weave/tutorial-eval) and then see how to [evaluate a RAG application](/weave/tutorial-rag).