Skip to content

Add docs CI gates: frontmatter, code samples, internal links, redirects - #180

Draft
tylergoerzen-mxp with Copilot wants to merge 3 commits into
mainfrom
copilot/tof-447-add-docs-ci-gates
Draft

Add docs CI gates: frontmatter, code samples, internal links, redirects#180
tylergoerzen-mxp with Copilot wants to merge 3 commits into
mainfrom
copilot/tof-447-add-docs-ci-gates

Conversation

Copilot AI commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Adds four Python validation scripts and a GitHub Actions workflow that block merges when docs quality invariants are violated.

CI workflow (.github/workflows/docs-ci.yml)

Runs on every PR and push to main. Four parallel jobs, each permissions: contents: read.

Validation scripts (scripts/)

  • check_frontmatter.py — all MDX pages (excluding snippets/, links/, openapi/) must have a title: in YAML front-matter
  • check_code_samples.py — every fenced code block must declare a language (```python, not bare ```)
  • check_links.py — internal links (/-prefixed, non-asset) must resolve to an existing MDX file or redirect source; wildcard redirect prefixes (e.g. /changelogs/*) handled with an O(n_prefixes) check rather than iterating all valid paths
  • check_redirects.py — redirect sources in docs.json must be unique; destinations must resolve to a known page or another redirect source

Pre-existing violations fixed

To get the gates green from day one:

  • docs.json: 25 broken redirect destinations — stale /changelogs/2022-* subpage URLs → /changelogs; deleted-page destinations updated to current equivalents; one missing leading slash (docs/getting-started/.../docs/what-is-mixpanel)
  • docs/mcp.mdx: URL-encoded dead link /reference/Mixpanel%20APIs/authentication/service-accounts/reference/service-accounts
  • reference/event-deduplication.mdx: stale /docs/data-model#anatomy-of-an-event/docs/data-structure/events-and-properties

@linear-code

linear-code Bot commented Aug 18, 2026

Copy link
Copy Markdown

TOF-447

Co-authored-by: tylergoerzen-mxp <259741734+tylergoerzen-mxp@users.noreply.github.com>
@mintlify

mintlify Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
mixpanel-docs 🟢 Ready View Preview Aug 18, 2026, 7:09 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

Copilot AI changed the title [WIP] Add CI gates for docs validation including links and code samples Add docs CI gates: frontmatter, code samples, internal links, redirects Aug 18, 2026
Copilot AI requested a review from tylergoerzen-mxp August 18, 2026 19:07
@greptile-apps

greptile-apps Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 0/5

The PR is not safe to merge because the required documentation gates remain incomplete and the workflow still executes actions through mutable references.

Redirect-source links and redirect chains still pass, priority examples are not compiled, required frontmatter metadata is not fully checked, OpenAPI validation is absent, and every new job relies on movable action tags.

Files Needing Attention: .github/workflows/docs-ci.yml, scripts/check_links.py, scripts/check_code_samples.py, scripts/check_frontmatter.py, scripts/check_redirects.py

Important Files Changed

Filename Overview
.github/workflows/docs-ci.yml Adds four parallel validation jobs, while the previously reported OpenAPI omission and mutable action references remain.
scripts/check_links.py Adds internal-link scanning, but the previously reported acceptance of redirect-source links remains.
scripts/check_code_samples.py Adds code-fence language validation, but the previously required compile and smoke testing remains absent.
scripts/check_frontmatter.py Adds title-presence validation, but description and title-uniqueness requirements remain absent.
scripts/check_redirects.py Adds redirect validation and cycle detection, but still explicitly permits redirect chains.
docs.json Repoints stale redirect destinations to existing canonical pages.
docs/mcp.mdx Replaces a dead encoded service-account link with its canonical route.
reference/event-deduplication.mdx Updates the event-object link to the current data-structure page.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  PR[Docs pull request] --> CI[Docs CI]
  CI --> F[Frontmatter check]
  CI --> C[Code-fence check]
  CI --> L[Internal-link check]
  CI --> R[Redirect check]
Loading

Reviews (2): Last reviewed commit: "Fix false positives and false negatives ..." | Re-trigger Greptile

Comment thread scripts/check_links.py
Comment on lines +35 to +54
content = fh.read()

in_block = False
for lineno, line in enumerate(content.splitlines(), 1):
stripped = line.strip()
if stripped.startswith("```"):
if in_block:
# Closing fence
in_block = False
else:
# Opening fence — extract language token
rest = stripped[3:].strip()
lang = rest.split()[0] if rest else ""
if not lang:
errors.append(
f"{path}:{lineno}: code block is missing a language identifier"
)
in_block = True

return errors

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Samples are never compiled

When a labeled sample contains invalid syntax, package names, exports, environment variables, or API hosts, this checker examines only the opening fence and still passes it. Uncompilable priority examples therefore remain mergeable despite TOF-447 requiring compile or smoke tests.

Source Used: Linear — AEO QW10: Add docs CI gates (links, code samples, frontmatter, redirects, OpenAPI)

Comment thread scripts/check_frontmatter.py Outdated
Comment on lines +25 to +32

m = FRONTMATTER_RE.match(content)
if not m:
errors.append(f"{path}: missing front-matter block")
return errors

fm = m.group(1)
if not re.search(r"^\s*title\s*:", fm, re.MULTILINE):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Frontmatter requirements remain unchecked

When a page omits its description or duplicates another page's title, this function accepts it as long as a title key exists. Pages that violate TOF-447's description and unique-title requirements therefore pass CI.

Source Used: Linear — AEO QW10: Add docs CI gates (links, code samples, frontmatter, redirects, OpenAPI)

Comment thread scripts/check_redirects.py
Comment on lines +53 to +66

redirects:
name: Redirects check
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Check redirects
run: python scripts/check_redirects.py

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 OpenAPI validation gate is missing

When a PR introduces an invalid OpenAPI specification or nonconforming example, none of these four jobs validates it. The workflow can pass while generated API reference pages render broken or incomplete, contrary to TOF-447's OpenAPI acceptance criteria.

Knowledge Base Used: API Reference (reference/ and openapi/)

Source Used: Linear — AEO QW10: Add docs CI gates (links, code samples, frontmatter, redirects, OpenAPI)

Comment on lines +19 to +20
- uses: actions/checkout@v4
- uses: actions/setup-python@v5

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 security Action dependencies use mutable tags

The new jobs execute actions/checkout@v4 and actions/setup-python@v5 from mutable references, unlike the repository's existing SHA-pinned workflow. Pinning these actions prevents upstream tag movement from changing executable CI code and its results.

How this was verified: All four jobs use mutable major tags, while .github/workflows/stale.yml pins its action to a full commit SHA.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

check_redirects.py
- Honour wildcard redirect sources when resolving a destination. The
  docstring says chained redirects are allowed, but only exact sources
  were matched, so the 461 wildcard sources were ignored. That produced
  25 errors on main of which only 3 were real: an 88% false-positive
  rate that would have fired again on the next redirect anyone added.
- Detect loops. Every node in a cycle is also a source, so the
  chained-redirect rule silently swallowed /self -> /self and /a -> /b -> /a.

check_links.py
- Blank out fenced and inline code before extracting links, so a page
  documenting an example <a href="/docs/..."> does not fail CI. Line
  numbers are preserved.

check_code_samples.py
- Track fence length so a ```python block nested in a ````mdx block does
  not close the outer block early. Drop the unused FENCE_OPEN_RE and
  report repo-relative paths instead of absolute ones.

check_frontmatter.py
- An empty title no longer passes.

Verified: all four pass on this branch, and each rejects a deliberate
bad fixture (empty title, bare fence, dead link, redirect loop).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants