ci: add link check and changelog sync, harden Mintlify workflow - #2
Merged
Conversation
Bring docs-mantis up to parity with docs-privacysentinel (the surviving canonical copy — docs-privacytracker is an empty repo): - linkcheck.yml: npm run check (nav/internal links/anchors/frontmatter) plus cached lychee external-link check on PR/push/weekly schedule, with an auto-filed issue when the scheduled run finds breakage. - sync-changelog.yml: daily cron regenerates changelog.mdx and opens a PR via peter-evans/create-pull-request when it moved. - scripts/check-docs.mjs: ported from the sibling; nav pages may be .md or .mdx, navigation.groups (this repo's shape) is walked in addition to tabs[].groups[], and inline code spans are excluded from link scanning so syntax examples in tables don't false-positive. - scripts/sync-changelog.mjs: mantis has no releases.json — its release manifest is GitHub Releases (cli-v* = CLI, v* = server), so the script reads the Releases API with the workflow's built-in token, keeping the sibling's MANIFEST_URL/MANIFEST_FILE overrides. - changelog.mdx: initial generated page, added to docs.json nav so the nav check passes from the first run. - mintlify.yml hygiene: top-level contents: read, concurrency with cancel-in-progress, timeout-minutes, persist-credentials: false. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The sibling's canonical args pass --base ., which lychee now rejects (base must be a full URL or an absolute path). Internal links, anchors and nav are already covered by npm run check, so restrict lychee to http/https schemes — external links only, as the step name says. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The scheme filter excludes local files from checking, but lychee still resolves root-relative links first and errors without a root dir. Verified locally with lychee 0.24.2: 34 external links OK, 0 errors. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Root cause
This docs repo was missing the two CI workflows its siblings share: no link checking beyond
mint broken-linkson PRs (so external-link rot went unnoticed between PRs), and no changelog sync (so the docs never surfaced product releases at all — there was no changelog page). The intended canonical source,privacykey/docs-privacytracker, turned out to be an empty repo (zero refs), so the workflows were taken from the other sibling,privacykey/docs-privacysentinel, which carries the same canonical versions.What changed
New:
.github/workflows/linkcheck.yml— same shape as the sibling:npm run check(navigation, internal links, anchors, assets, frontmatter) then cached lychee for external links, on PR/push/weekly cron/manual dispatch, and the scheduled run auto-files an issue on breakage viapeter-evans/create-issue-from-file.One deviation from the sibling's args, found when this PR's first CI run failed: the canonical file passes
--base ., which current lychee releases reject outright (Base must either be a full URL (with scheme) or an absolute local path) — the siblings' scheduled runs are hitting the same error. Since internal links and anchors are already covered bynpm run check, lychee here is scoped to external links only (--scheme https --scheme http), with--root-dir ${{ github.workspace }}so root-relative links like/updatingresolve instead of erroring before the scheme filter excludes them. Verified against lychee 0.24.2 locally (34 external links OK, 0 errors) and green in this PR's CI. The siblings should pick up the same fix.New:
.github/workflows/sync-changelog.yml— daily 12:00 UTC cron (same as sibling): check → regeneratechangelog.mdx→ re-check →peter-evans/create-pull-requestopens a PR only when the file moved.New:
scripts/check-docs.mjs— ported from the sibling with three generic adaptations:.mdas well as.mdx(this repo's pages are mostly.md);navigation.groups(this repo's docs.json shape, incl. grouproot) is walked in addition to the sibling'snavigation.tabs[].groups[];/<img src="...">syntax examples that false-positived otherwise.New:
scripts/sync-changelog.mjs— the sibling reads its product repo'sreleases.jsonvia a raw.githubusercontent.com URL. Mantis has noreleases.json— its release manifest is GitHub Releases onprivacykey/mantis(cli-v*tags = CLI, plainv*tags = server, exactly as/updatingdocuments), so the script reads the Releases API instead, keeping the sibling'sMANIFEST_URL/MANIFEST_FILEoverride mechanism. Tag prefix becomes the component label, published date the date line, and the first prose paragraph of the release body the summary.New:
changelog.mdx+ docs.json nav entry (Reference group, after Updating) — generated by running the script, committed now so the nav check passes from the first run. Regeneration is idempotent (verified: second run reports "already up to date").Hardened:
.github/workflows/mintlify.yml— top-levelpermissions: contents: read, concurrency group with cancel-in-progress,timeout-minutes: 15,persist-credentials: falseon the checkout. The two new workflows carry the same baseline (top-level read-only permissions with job-level elevation where needed, timeouts,persist-credentials: falseon the non-pushing linkcheck checkout).Required setup: none. The sibling's sync needs no secret (public raw fetch) and neither does this one — the workflow passes the built-in
GITHUB_TOKENto the Releases API call purely to avoid runner-IP rate limits. Note:GITHUB_TOKEN-created PRs don't trigger otherGITHUB_TOKEN-driven workflows, so checks won't auto-run on the sync bot's PRs; if the org later wants that, a PAT in thecreate-pull-requesttokeninput is the standard upgrade — same caveat applies to the siblings.How to verify
mint validate+mint broken-linkson node 22, validating the new changelog.mdx and nav entry) and the new Link check workflow (npm run check+ lychee external sweep).npm run check(passes: 32 linked files), thenGITHUB_TOKEN=$(gh auth token) npm run sync-changelogtwice — first run writeschangelog.mdxwith the 6 published CLI releases, second reports no change.🤖 Generated with Claude Code