feat(docs): add fork-preview banner, dual Atom feeds, gh-pages reset - #449
Draft
netravnen wants to merge 17 commits into
Draft
feat(docs): add fork-preview banner, dual Atom feeds, gh-pages reset#449netravnen wants to merge 17 commits into
netravnen wants to merge 17 commits into
Conversation
A codebase-onboarding pass flagged two minor doc issues: README.md's
CentOS setup step predates this repo's move to a venv + uv workflow,
and mkdocs.yml's commented-out repo_url ("Edit on GitHub" link) had
only a generic comment with no indication of whether it was disabled
on purpose. Confirmed via git history that the link was deliberately
removed (commit fcb252c, "Removed the 'Edit on GitHub' link.",
2024-02-05), though that commit itself records no reason -- so this
leaves it disabled and documents that provenance instead of guessing
at intent either way.
Changes:
- README.md: CentOS install step used `yum install python-pip`,
the Python 2 package name on a package manager CentOS has since
moved on from; updated to `dnf install python3 python3-pip` to
match the rest of the guide's python3/venv-based setup
- mkdocs.yml: replace the one-line "This line adds the Edit on
GitHub link" comment above the commented-out repo_url with one
that records why it's off (deliberate removal, reason
undocumented) so it reads as a known state, not leftover cruft
Security:
- N/A -- documentation only
Testing:
- N/A -- text-only changes; no build step to run for README.md, and
mkdocs.yml's only functional line (repo_url) is unchanged, still
commented out
Backwards Compatibility:
- N/A -- no behavior change; the Edit on GitHub link remains off,
matching current site behavior
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ber steps
The getting-started path was scattered: index.md buried the
role-specific HOWTOs under 45 lines of archival material (release
notes, tools, presentations, beta server, historical data), the four
get-started-*.md guides each repeated an identical 370+ word "About
PeeringDB" paragraph, and their setup steps were an unordered list
that read more like notes than instructions. This restructures the
front door so a new user hits a role picker first and each guide
gets straight to numbered steps.
Changes:
- docs/index.md: move "Getting started" to the second section (after
the intro video, before Policies); consolidate Release
notes/Tools/Presentations/Open source/Beta/Historical data into a
compact "Learn more" bullet list; move the tutorial/workshop list
out to presentations.md; trimmed from 123 to 92 lines
- docs/howtos.md: add a "New here? Start with your role" intro
linking the four get-started guides, and list query_the_api.md
alongside search.md
- docs/howto/get-started-{operator,exchange,facility,carrier}.md:
replace the duplicated "About PeeringDB" boilerplate with a single
pointer to index.md; number the setup steps (create account,
create org, create the role-specific object, follow-up step);
standardize the "Why should I add my network?" heading to "Why?"
to match the other three guides; add the missing "More
information" section to get-started-carrier.md so all four guides
match
- docs/presentations.md: add "Tutorials and workshops" section at
top with the 7 entries moved from index.md
Security:
- N/A -- documentation only
Testing:
- mkdocs build --strict passes with 0 warnings; internal links
between index.md, howtos.md, and the four get-started guides
verified to resolve
Backwards Compatibility:
- N/A -- no URLs or anchors removed; index.md's #mailing-lists
anchor (linked from 60+ blog posts) is unchanged
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
search.md had grown to 355 lines serving two audiences at once: a
beginner walkthrough of UI/browser-extension search, and a full API
reference (object types, authentication, curl/Python/jq examples).
Separately, authenticate.md's MFA section was four sentences with
three screenshots sitting unused in the images directory, leaving
users to figure out setup and org-level enforcement on their own.
Changes:
- docs/howto/query_the_api.md: new file (175 lines) with the API
reference content moved from search.md -- object types
(basic/derived), API key authentication, making requests, GET
operations on single/multiple objects, nested sets/objects, and
real-world query examples using curl, Python, and jq
- docs/howto/search.md: trimmed from 355 to 189 lines, now focused
on UI/extension search; replaced the removed content with a
pointer to query_the_api.md
- docs/howto/authenticate.md: expanded the MFA section into a full
walkthrough with two new subsections ("Setting up your second
factor", "Requiring MFA for your organization"), wiring in the
three previously orphaned screenshots
(Location_of_MFA_button.png, MFA_management.png,
require_users_to_enable_2fa.png) with captions
- docs/howto/work_within_peeringdbs_query_limits.md,
docs/release_notes/release_notes_2023.md: update cross-references
from /howto/search to /howto/query_the_api/ to match the split
Security:
- N/A -- documentation only
Testing:
- mkdocs build --strict passes with 0 warnings; verified
query_the_api.md anchors referenced by other pages resolve
Backwards Compatibility:
- search.md's URL is unchanged; only its content and length
changed, so existing external links to /howto/search/ still
resolve, just to a narrower page
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A link sweep across the docs site found three broken references unrelated to the getting-started or API-split work: an FAQ anchor pointing at a section that no longer exists, and two blog posts linking to HOWTO pages that were renamed or never existed. Changes: - docs/faq.md: "How do I get started?" linked to http://docs.peeringdb.com/#quick-start, an anchor that doesn't exist in index.md; replaced with a link to /howtos/ describing the role-based guides - docs/blog/mfa_mandatory.md: "second factor" linked to /howto/enable_require_2fa/, a page that was never published; redirected to /howto/authenticate/#multi-factor-authentication-mfa - docs/blog/peeringdb_2022_user_survey.md: "HOWTO documentation series" linked to /howto/ (404, missing the plural); fixed to /howtos/ Security: - N/A -- documentation only Testing: - mkdocs build --strict passes with 0 warnings; confirmed /howto/authenticate/#multi-factor-authentication-mfa resolves in the generated HTML Backwards Compatibility: - N/A -- these links were already broken; no working URLs changed Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The Admin Committee's public-facing Deskpro response snippets (triggered via ;code shortcuts like ;net-approved) had no human-readable index, making them hard to review or reference outside the Deskpro UI itself. Changes: - docs/committee/admin/deskpro_snippets.md: new file indexing the public (non-staff-only, non-trivial) Deskpro snippets by category -- network registration & approvals, facility & carrier management, organization recovery & account verification, IP/IX-F conflict resolution, and general administrative responses -- with snippet ID, shortcut code, and full text for each Security: - N/A -- documentation only; content already public-facing via Deskpro shortcuts, this just mirrors it Testing: - mkdocs build --strict passes with 0 warnings Backwards Compatibility: - N/A -- new page, no existing links affected Co-Authored-By: Gemini 3.6 Flash <noreply@google.com>
…uidance Facility, exchange, and carrier applicants were finding out they didn't qualify only after submitting and getting rejected, because the eligibility bar for each object type lived only in the Admin Committee's Deskpro response snippets, not in the public HOWTOs. Likewise, none of the three guides warned that facility and IX prefix objects can't be deleted once other records depend on them, so operators hit that block with no context. Changes: - docs/howto/get-started-facility.md: add "Facility qualification & approval criteria" section (ownership/operation, public colocation, multi-carrier interconnection, public documentation, and explicitly ineligible site types) and a "Deleting a facility" warning admonition covering the connected-networks deletion lock - docs/howto/get-started-exchange.md: add a "3-ASN minimum" callout covering the participant threshold, route-server/affiliated-ASN exclusions, and RDAP-verifiable prefix requirements, plus a "Deleting an IX prefix" warning admonition covering the connected-networks deletion lock - docs/howto/get-started-carrier.md: add "Carrier infrastructure qualification checklist" distinguishing eligible carrier-grade services (dark fibre, DWDM/wavelengths, Ethernet transport, MPLS VPN over owned infrastructure) from ineligible resold/leased transport Content is sourced from the Admin Committee's public Deskpro snippets already indexed in committee/admin/deskpro_snippets.md (;fac-rejected, ;ix-rejected, ;car-rejected, ;deletion-fac, ;deletion-ixpfx) -- this makes criteria the committee already applies visible to applicants before they submit. Security: - N/A -- documentation only Testing: - mkdocs build --strict passes with 0 warnings; admonition blocks confirmed to render as `class="admonition warning"` / `class="admonition important"` in the generated HTML Backwards Compatibility: - N/A -- additive content only, no headings renamed or removed, no existing anchors changed Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Plan-By: Gemini 3.6 Flash <noreply@google.com>
…locks Two recurring support patterns had no self-serve documentation: users whose account email didn't match their ASN's RDAP record had no way to learn that adding a secondary email would unblock automated affiliation approval, and users who inherited an ASN or lost contact with their org's admins had no documented path to reclaim access. Separately, faq.md's Technical section covered API and sync mechanics but nothing about why object deletion sometimes gets blocked. Changes: - docs/howto/authenticate.md: add "Organization affiliation & admin succession" section with two subsections -- "RDAP email verification" (how the RDAP match works, why adding a secondary email is faster than changing your login email) and "Claiming admin rights for an existing organization" (contacting a reachable admin first, falling back to RDAP-verifiable proof via support, and what to provide after an ASN acquisition) - docs/faq.md: add "Why can't I delete my Facility, IX Prefix, or Point of Contact?" under Technical, covering all three deletion locks and how to resolve each Content is sourced from the Admin Committee's public Deskpro snippets already indexed in committee/admin/deskpro_snippets.md (;mismatch-email, ;contacts-existing-admins, ;deletion-fac, ;deletion-ixpfx, ;deletion-poc). Security: - N/A -- documentation only; no new authentication mechanism described, just an explanation of an existing one Testing: - mkdocs build --strict passes with 0 warnings; new mailto and RDAP links verified to resolve Backwards Compatibility: - N/A -- additive content only, no headings renamed or removed Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Plan-By: Gemini 3.6 Flash <noreply@google.com>
committee/admin/deskpro_snippets.md and howto/query_the_api.md were only reachable via inline links from their parent pages -- mkdocs build listed both as present but not included in nav. Neither is a broken build (mkdocs only warns at INFO level for this), but it meant visitors browsing the site nav tree had no way to discover either page. Changes: - mkdocs.yml: nest "Admin Committee" into "Overview" (index.md) and "Deskpro Snippets" (deskpro_snippets.md); nest "HOWTOs" into "Overview" (howtos.md) and "Query the API" (query_the_api.md) Security: - N/A -- documentation only Testing: - mkdocs build --strict passes with 0 warnings; both pages no longer appear in the "not included in nav" info listing Backwards Compatibility: - N/A -- existing page URLs are unchanged; this only adds entries to the nav tree Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Plan-By: Gemini 3.6 Flash <noreply@google.com>
The FAQ had no guidance for a recurring support scenario: a company acquires another company and wants to bring the acquired organization's PeeringDB resources under its own management. Users hitting this had to file a support ticket cold, with no documented process or expectations set in advance. This also complements the "Organization affiliation & admin succession" section already added to authenticate.md, which covers the adjacent but distinct case of claiming admin rights when the original admins can't be reached. Changes: - docs/faq.md: add "Mergers and Acquisitions" under General, right after "Affiliation requests" -- covers the acquisition scenario, a worked example (Company A acquired by Company B), the support ticket process, and what speeds up review (writing from an email address that admins both organizations); cross-references authenticate.md's admin-succession guidance for the unreachable-admin case - docs/howto/authenticate.md: add a reverse cross-reference from "Claiming admin rights for an existing organization" to the new FAQ entry, for the voluntary-handoff case where the acquired organization's admins are still reachable Security: - N/A -- documentation only Testing: - mkdocs build --strict passes with 0 warnings; both cross-reference anchors (#mergers-and-acquisitions, #claiming-admin-rights-for-an-existing-organization) confirmed present in the generated HTML Backwards Compatibility: - N/A -- new content only, no existing links or anchors changed Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
docs.peeringdb.com is served via GitHub Pages today, but entirely manually -- someone runs `mkdocs gh-deploy --clean` from their own machine, which pushes the built site to upstream's `gh-pages` branch. There is no CI/CD in this repo's history at all, so nothing catches a broken link or nav omission before it ships, and the fork has no equivalent preview of its own. This adds two workflows scoped to this fork only -- upstream's manual production deploy is untouched. Changes: - .github/workflows/docs-build-check.yml: runs `mkdocs build --strict` on every pull request and on push to master/ admincom/docs-improvements, using uv to install the pinned dependency set from uv.lock. Fails the check on any warning (broken links, pages missing from nav, etc.) -- the automated version of the manual --strict checks run throughout this session's doc work. - .github/workflows/docs-deploy.yml: automates the exact `mkdocs gh-deploy --clean` command README.md already documents as the manual process, targeting the fork's own (currently nonexistent) gh-pages branch. Strips docs/CNAME before building first, since that file lives inside docs_dir and would otherwise get copied into the built site and wrongly claim docs.peeringdb.com as the fork's own custom domain. Runs on push to master/admincom/docs-improvements plus workflow_dispatch for manual redeploys; --force is required since a stateless CI runner never has prior gh-pages history to compare against. Security: - Deploy workflow requests `contents: write` on GITHUB_TOKEN, scoped to this repo only; PR-check workflow stays `contents: read` since it never publishes anything. Neither workflow runs on pull_request_target or handles third-party PR code with elevated permissions, so forked-PR privilege escalation isn't a concern. Testing: - Both YAML files parse cleanly with PyYAML; `mkdocs build --strict` still passes with 0 warnings locally. End-to-end verification (Actions tab going green, gh-pages branch creation, Pages URL serving correctly) requires pushing to GitHub and is documented as follow-up manual verification, not achievable from a local clone. Backwards Compatibility: - N/A -- new files only; no existing workflow, branch, or build behavior is changed. Upstream's manual deploy process is completely unaffected. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The blog page listed posts in docs/blogs.md with no way to subscribe to new ones. Add a mkdocs hook that regenerates docs/atom.xml from that list on every build, so a feed reader can follow new posts without manually checking the page. Post dates come from git history rather than blogs.md's hand-typed date text: a bulk git-log pass over docs/blog/ resolves each post's first-added commit date in one shot, falling back to a slower per-file `git log --follow` lookup only for the handful of posts that pass has missed (files introduced via a rename, which git classifies as an R event rather than A, so a --diff-filter=A bulk pass silently skips them). This gives real commit timestamps (time of day, correct timezone) instead of a hand-typed day-only date, and self-corrects if blogs.md's date text is ever wrong or stale. The feed's self-link is driven by an ATOM_SITE_URL environment variable (falling back to mkdocs.yml's site_url) rather than always hardcoding the production URL, so this fork's own preview deploy can correctly self-reference wherever it actually serves from instead of falsely claiming to be docs.peeringdb.com. docs-deploy.yml sets it from GitHub Actions context; docs-build-check.yml gets fetch-depth: 0 added to its checkout, which the git-log date lookups require -- without full history, every post would appear to have no git history at all, and mkdocs build --strict promotes that warning to a failure. Duplicate timestamps (two posts added in the same commit) are nudged apart by 1-second increments after date resolution, so every entry's atom:updated value stays unique per the W3C Feed Validator's interoperability recommendation, without affecting sort order. Changes - scripts/generate_atom_feed.py (new): on_pre_build hook. Bulk + per-file git-log date lookup, markdown-to-plaintext excerpt extraction for each entry's summary, ISO-8601 formatting (normalized to UTC for git's real commit timezones), duplicate-timestamp dedupe, Atom 1.0 XML construction via stdlib ElementTree/minidom -- no third-party feed library. - mkdocs.yml: register the hook under hooks:. - docs/blogs.md: "Subscribe via Atom feed" line; also the underlying source list this hook parses. - peeringdb_theme/main.html: <link rel="alternate"> feed-discovery tag. - .gitignore: docs/atom.xml is a generated build artifact, not tracked. - .github/workflows/docs-build-check.yml, .github/workflows/docs-deploy.yml: fetch-depth: 0 (required for the git-log date lookups); docs-deploy.yml sets ATOM_SITE_URL from GitHub Actions context and strips any production docs/CNAME before building, so this fork's preview never falsely claims to be docs.peeringdb.com. Security - N/A Testing - uv run mkdocs build --strict: 0 warnings. - Spot-checked generated dates against git log for several posts, including a renamed file resolved via the --follow fallback. - Confirmed duplicate-timestamp entries get distinct atom:updated values while preserving their original relative order. Backwards Compatibility - N/A Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The fork's preview site needs its own domain, distinct from upstream production's docs.peeringdb.com -- docs-dev.peeringdb.dk. The straightforward way to do this (edit docs/CNAME's tracked content directly) has the same problem as removing it outright: docs/CNAME is the same file both this fork's automation and upstream's manual `mkdocs gh-deploy --clean` rely on, so whatever value sits in it on this branch would silently become production's value the moment this branch merges upstream -- either breaking the custom domain entirely (if removed) or replacing it with the wrong one (if hardcoded to the dev domain). Instead of choosing a value to store, generate the file at build time from configuration, mirroring the pattern already used for the atom feed's self-link: an optional SITE_URL_OVERRIDE env var takes priority when set, falling back to mkdocs.yml's site_url (https://docs.peeringdb.com/) when unset. This makes the merge-safety concern moot rather than just documented: upstream's deploy process sets no override, so it always regenerates the correct production CNAME automatically, with no manual edit required at merge time. Changes: - scripts/generate_cname.py: new mkdocs on_pre_build hook. Derives the GitHub Pages custom domain from SITE_URL_OVERRIDE if set, else config.site_url, via urllib.parse (stdlib only, no new dependency), and writes docs/CNAME before mkdocs collects static files -- same timing/mechanism already used for the atom feed. - scripts/generate_atom_feed.py: rename the ATOM_SITE_URL env var to SITE_URL_OVERRIDE, since it now drives two hooks, not just the feed. - mkdocs.yml: register the new hook alongside the existing one. - docs/CNAME: untracked (git rm --cached) and added to .gitignore, alongside docs/atom.xml -- both are now build artifacts regenerated every run, not source content. - .github/workflows/docs-deploy.yml: drop the now-unnecessary "strip CNAME" step, and set SITE_URL_OVERRIDE from a repo variable (Settings -> Actions -> Variables -> SITE_URL_OVERRIDE, already configured to https://docs-dev.peeringdb.dk) rather than hardcoding the domain in the workflow file. Security: - N/A -- documentation only. urllib.parse.urlparse on a value from a repo-scoped Actions variable is not an injection vector. Testing: - mkdocs build --strict passes with 0 warnings in both modes: with no SITE_URL_OVERRIDE set, site/CNAME correctly resolves to docs.peeringdb.com (config.site_url fallback, matching current production behavior exactly); with SITE_URL_OVERRIDE= https://docs-dev.peeringdb.dk/, site/CNAME resolves to docs-dev.peeringdb.dk and the atom feed's self-link matches it too, confirming both hooks stay in sync off the same override. Backwards Compatibility: - N/A for upstream -- unchanged behavior when no override is set. For this fork specifically, docs/CNAME's tracked value changes from a static docs.peeringdb.com to being generated at build time from the SITE_URL_OVERRIDE repo variable; the fork's actual GitHub Pages custom-domain setting and docs-dev.peeringdb.dk DNS record still need to be configured to match (outside this branch's scope). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
generate_cname.py and generate_atom_feed.py each independently resolved SITE_URL_OVERRIDE-or-site_url with slightly different fallback logic. Extract one shared policy so both (and later hooks) always agree on what "the site URL" is for a given build. scripts/site_url.py's resolve_site_url() resolves in this order: 1. PROD=TRUE -- real production, full stop. 2. SITE_URL_OVERRIDE, if set. 3. The local dev-server address mkdocs itself is serving on (e.g. http://127.0.0.1:8000/), if `mkdocs serve` is what's actually running. Requires callers to be wired to on_pre_build, not on_config: mkdocs's own serve.py only overwrites config.site_url with the dev address *after* on_config has already run (see commands/serve.py's `config.site_url = f'http://{config.dev_addr}...'`, right before it calls build()), so on_config never sees it. 4. LOCAL_SITE_URL ("http://localhost:8000/", mkdocs's own default --dev-addr) -- the fallback when none of the above apply: a plain `mkdocs build` with no env vars and no live dev server, e.g. docs-build-check.yml's CI check or a one-off local build served separately afterward (a static server started after the build already finished can't be predicted at build time -- there's nothing to detect there). Deliberately assumes "local" rather than guessing a real GitHub Pages URL from `git remote get-url origin`: a real checkout always has an `origin` remote, so a git-remote-based guess would almost always "succeed" with a URL that doesn't correspond to anything actually being served, which is more misleading than an honest localhost default. Changes - scripts/site_url.py (new): resolve_site_url() and origin_repo_url(), the shared policy described above. - scripts/generate_cname.py: use the shared resolver instead of its own SITE_URL_OVERRIDE-or-site_url fallback. Also now skips writing docs/CNAME when the resolved host is a loopback address, since a CNAME file only means anything for a real GitHub Pages deploy. - scripts/generate_atom_feed.py: use the shared resolver instead of its own fallback. Security - N/A Testing - uv run mkdocs build --strict in four scenarios (no env vars / SITE_URL_OVERRIDE / PROD=TRUE / both), all 0 warnings. - Real `mkdocs serve` run: both docs/CNAME and the feed's self-link correctly resolve to the actual dev-server address, confirmed via curl that the server responded at that address. - Confirmed a plain `mkdocs build` with no env vars and no dev server running resolves to http://localhost:8000/ rather than a GitHub Pages guess, and that docs/CNAME is correctly left untouched (a loopback host skips the write). Backwards Compatibility - N/A Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This fork's preview deploy currently looks identical to real
production, making it easy to mistake one for the other. Add a
banner above the nav bar showing the fork's repo, the URL currently
serving the page, and where production actually lives.
The banner is on by default -- any build without further signal is
assumed to be a dev/fork build -- and is suppressed only when PROD=TRUE
is set at build time, deliberately the opposite default from
site_url.resolve_site_url()'s own production-safe fallback, since a
real production deploy lives outside this repo and can set PROD=TRUE
explicitly.
Changes
- scripts/generate_banner.py (new): on_pre_build hook that exposes
fork repo/live/production URLs to templates via
config.extra.fork_banner, gated on PROD=TRUE. Uses on_pre_build
(like the cname/atom-feed hooks) rather than on_config, required for
resolve_site_url()'s local-serve detection tier to see mkdocs's
overwritten config.site_url.
- peeringdb_theme/base.html (new): full copy of mkdocs 1.4.3's packaged
base.html (pinned version) with the banner markup inserted before the
nav bar div, since no block wraps that div for main.html to override.
- docs/extra.css: .fork-banner styling. Height is fixed to 3.5rem to
match the nav bar's own documented height (mkdocs's base.css:
scroll-padding-top comment), which .nav-link's 1rem/1rem padding plus
Bootstrap's 1.5rem line-height already add up to -- no JS measurement
needed. The banner is sticky at top:0 with the nav bar offset below it
(body.has-fork-banner .navbar.fixed-top { top: 3.5rem }) so both stay
pinned together while scrolling.
- mkdocs.yml: register generate_banner.py in hooks:.
Security
- N/A
Testing
- uv run mkdocs build --strict in the same four scenarios as the
previous commit, all 0 warnings, banner present/absent as expected
in each.
- Visually verified in-browser: banner height matches the nav bar,
stays sticky above it while scrolling, single-line content doesn't
wrap.
Backwards Compatibility
N/A -- peeringdb_theme/base.html duplicates mkdocs 1.4.3's packaged
base.html. If mkdocs is ever upgraded, this file needs to be re-diffed
against the new packaged version and the banner insertion reapplied.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The blog feed generator (generate_atom_feed.py) inlined its Atom feed/entry XML construction, ISO-8601 formatting, markdown-link stripping, and timestamp-collision dedupe logic (commit a02694c6). A second, independent feed for release notes is coming in a follow-up commit -- pull the generic, non-blog-specific pieces out into a shared scripts/atom_common.py first so that feed doesn't have to duplicate ~60 lines of ElementTree/minidom boilerplate. Rename generate_atom_feed.py to generate_blog_atom_feed.py for symmetry with the upcoming generate_release_notes_atom_feed.py, and relocate its output from docs/atom.xml to docs/blog/atom.xml so the feed is co-located with its source content the same way the release notes feed will be (docs/blog/ + docs/release_notes/). Changes - scripts/atom_common.py (new): build_feed(), dedupe_published(), isoformat(), plain_text(), truncate() -- extracted unchanged from generate_atom_feed.py. - scripts/generate_atom_feed.py -> scripts/generate_blog_atom_feed.py (renamed + refactored): keeps its blog-specific git-log date derivation and post-excerpt logic, now calls atom_common.build_feed() instead of inlining feed construction. Output moved to docs/blog/atom.xml. - mkdocs.yml: hooks: entry updated for the rename. - peeringdb_theme/main.html: blog feed's <link rel="alternate"> href updated to blog/atom.xml. - docs/blogs.md: "Subscribe via Atom feed" link updated to the new blog/atom.xml path. - .gitignore: docs/atom.xml entry updated to docs/blog/atom.xml. Security - N/A Testing - uv run mkdocs build --strict in four scenarios (no env vars / SITE_URL_OVERRIDE / PROD=TRUE / both), all 0 warnings. - Diffed the feed's content against a pre-refactor build: byte- identical apart from the self-link, confirming the atom_common extraction and the file move didn't change any feed data. - Confirmed docs/blogs.md's and site/blogs/index.html's rendered Subscribe links resolve to the new blog/atom.xml path. Backwards Compatibility Subscribers following the old docs/atom.xml URL on this fork's preview will need to resubscribe at docs/blog/atom.xml -- flagging since it's a real, if minor, break. Production (docs.peeringdb.com) has never had this feed live, so nothing changes there. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The blog feed was the only Atom feed this repo generated. Add a
second, independent feed for release notes, sourced from
docs/release_notes/index.md's `## Release X.Y.Z` sections, so
subscribers can follow releases without also getting blog posts (and
vice versa). Builds on the shared scripts/atom_common.py extracted in
the previous commit.
Release notes entry dates come straight from each section's
`Release Date:` line (falling back to `Beta Announcement Date:` if
absent) rather than git history -- unlike blog posts, this content is
already hand-dated inline, so there's no gap to fill. Entry URLs are
built with markdown.extensions.toc.slugify() (mkdocs's own anchor
slugifier, confirmed against the real built HTML: "Release 2.81.0"
becomes id="release-2810") rather than a hand-rolled one, guaranteeing
they always match the real heading IDs mkdocs generates. Entry
summaries are a plain issue count ("N GitHub issues addressed in this
release"), counted by matching table rows starting with `| [` rather
than parsing cell contents -- the summary column has occasional
unescaped `{`/`[`/`'` characters that would make a content-parsing
regex fragile for no real benefit, since a feed entry's job is to
notify, not replace the page a click away. Only index.md is scoped in,
not the per-year release_notes_YYYY.md archives -- a feed is about
what's new, and index.md alone already covers back to release 2.75.0.
Changes
- scripts/generate_release_notes_atom_feed.py (new): on_pre_build hook
parsing docs/release_notes/index.md into feed entries as described
above, writing docs/release_notes/atom.xml via atom_common.build_feed().
- mkdocs.yml: hooks: entry for the new hook.
- peeringdb_theme/main.html: second <link rel="alternate"> for the
release notes feed.
- docs/release_notes/index.md: "Subscribe via Atom feed" line, matching
docs/blogs.md's existing convention.
- .gitignore: docs/release_notes/atom.xml entry -- a build artifact,
not tracked.
Security
- N/A
Testing
- uv run mkdocs build --strict in four scenarios (no env vars /
SITE_URL_OVERRIDE / PROD=TRUE / both), all 0 warnings, both feeds'
self-links agreeing with docs/CNAME in every scenario.
- Spot-checked the feed: Release 2.81.0's entry URL
(.../release_notes/#release-2810) matches the real anchor ID in the
built HTML, published date matches its Release Date line, and the
issue count (8) matches a manual count of that section's table rows.
Backwards Compatibility
N/A -- new feed, nothing previously depended on this URL.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
mkdocs gh-deploy already regenerates the whole site tree from the current branch on every run, so removed pages never linger. What wasn't guaranteed was the gh-pages branch's commit history: without --no-history, ghp-import fetches the existing gh-pages HEAD and commits on top of it, so the branch's state technically depends on whatever was already there rather than purely on this run's build. --no-history makes every deploy a single force-pushed root commit, so gh-pages is unconditionally reset on top of whatever this branch built, with no path for prior branch state to carry forward. Changes: - Added --no-history to the mkdocs gh-deploy invocation in docs-deploy.yml, alongside the existing --clean --force flags. Security: - N/A Testing: - Not run through an actual gh-deploy (would force-push the shared gh-pages branch); verified by reading mkdocs/ghp-import's documented --no-history behavior against the existing --force (permissions: contents: write) setup already in this workflow. Backwards Compatibility: - gh-pages loses its multi-commit history going forward (each deploy now replaces it with one commit instead of appending). The served site content is unaffected; only the branch's own commit log style changes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Author
|
I run a public dev preview of this branch at |
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.
Draft PR for early feedback.
This branch started as infra for running a dev/preview fork of this
site, and grew to fix a few problems that showed up while doing that:
preview deploys were indistinguishable from production in a browser,
the two content streams (blog posts and release notes) only had one
combined feed to subscribe to, and
gh-pagesaccumulated deployhistory that made no promise about matching the branch that built it.
A batch of unrelated content fixes rode along in the same session and
is included here too.
Opening as draft because part of this (the fork-preview banner) is
fork-specific scaffolding that may not be wanted upstream as-is;
flagging for discussion rather than asking for a merge.
Relates to #448
Changes
and where production lives, so a preview deploy is never mistaken
for the real site. Suppressed via
PROD=TRUE.docs/blog/atom.xmlanddocs/release_notes/atom.xml, so blog and release-notes readers cansubscribe separately. Share a common
scripts/atom_common.py.Release-notes entries are parsed from
release_notes/index.md'sexisting
## Release X.Y.Zsections.scripts/site_url.py): one sharedprecedence (
PROD=TRUE>SITE_URL_OVERRIDE> detected localdev-server address >
http://localhost:8000/) used by the banner,both feeds, and dynamic
docs/CNAMEgeneration, so they can'tdisagree about what URL they're building for.
--no-historyso every deploy is asingle fresh commit built from the current branch, instead of
accumulating commits on top of whatever was already there.
stale CentOS setup step, FAQ additions (RDAP affiliation, admin
succession, deletion locks, Mergers & Acquisitions guidance),
getting-started clarifications, a Deskpro public-response snippets
index, and nav registration for pages that existed but weren't
linked from the sidebar.
Testing
uv run mkdocs build --strict-- 0 warnings.mkdocs serveand aseparately-served static build.
PROD=TRUE.Notes for reviewers
scripts/generate_banner.pyand theSITE_URL_OVERRIDEdev-domainplumbing in
docs-deploy.ymlare the pieces most likely to needchanges, or removal, before this could land on
masteras-is. Happyto split those out of the eventual mergeable set if preferred.