Skip to content

DOC-7104: Migrate content/operate/rs/release-notes/ to render hooks - #4086

Merged
andy-stark-redis merged 2 commits into
mainfrom
DOC-7104-release-notes
Sep 24, 2026
Merged

andy-stark-redis merged 2 commits into
mainfrom
DOC-7104-release-notes

Conversation

@andy-stark-redis

@andy-stark-redis andy-stark-redis commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Unit 2 of 15 in the DOC-7104 shortcode-to-render-hook migration (extending DOC-6909/7047/7055/7059/7074/7079/7080/7086/7089 into content/operate/rs/). Converts every file under content/operate/rs/release-notes/ (135 files) from the relref link shortcode and note/tip/warning/alert callout shortcodes to their render-hook equivalents: plain Markdown links resolved by layouts/_default/_markup/render-link.html, and > [!NOTE] etc. blockquotes resolved by layouts/_default/_markup/render-blockquote.html. Purely mechanical syntax migration — no prose, terminology, or facts changed.

  • Files changed: 129 of 135 (6 had no relref/callout content to convert)
  • relref calls converted: ~2,397 (all resolved to /content/<path>.md[#anchor] form except a small set of pre-existing edge cases noted below, which linkify correctly leaves unresolved since their literal text never matched a real content file path)
  • Callouts converted: 15 across 13 files (note/tip/warning/alert → > [!NOTE] etc.)
  • Ran via build/migrate_shortcode_links.py all sequentially (not xargs) over the exact 135-file list.

Pre-flight findings

Two of the five pre-flight checks were not clean (the other three — missing-open-paren relref, literal HTML callout wrapper, unquoted title= on alert — had 0 hits):

  1. 3 list-nested callout shortcodes (legacy-release-notes/rs-5-4-2-april-2019.md, rs-6-4-2-releases/rs-6-4-2-110.md, rs-6-4-2-releases/rs-6-4-2-61.md). The mechanical converter dedents continuation lines to column 0 while leaving the > [!NOTE] header line indented, which detaches the blockquote from its <li>. Manually re-indented the continuation lines to match the list's original indent. Verified via a before/after rendered-HTML diff that <li><p>...</p><div class="alert">...</div></li> nesting is identical in both builds.
  2. 26 relref calls across 13 files use an established (if unusual) convention: relref to a directory-style page immediately followed by a literal relative sub-path with no separating slash (e.g. {{< relref "/operate/rs/databases/active-active" >}}develop/develop-for-aa/), relying on Hugo's relref rendering the target with an implicit trailing slash. The naive mechanical conversion concatenates these without a slash (verified this breaks the href), so I manually inserted the missing / at each site to preserve the pre-conversion rendered href.

Genuinely pre-existing issues fixed (trivial, per ticket's single-missing-paren carve-out)

Two relref shortcodes were missing their markdown link's closing ), so the link never rendered as a link at all (plain text):

  • rs-6-2-4-august-2021.md: [FAILOVER]({{< relref "/commands/failover" >}}. → added the missing ).
  • rs-6-4-2-releases/rs-6-4-2-94.md: [`SLOWLOG GET [count]`]({{< relref "/commands/slowlog-get" >}}, → added the missing ).

Verification and a tooling finding

Built Hugo before/after (hugo --minify) and ran build/diff_rendered_hrefs.py ... operate/rs/release-notes, which reported "0 href diffs." That result is not trustworthy: the tool's HREF_RX (href="[^"]*") only matches double-quoted attributes, but under hugo --minify htmlmin drops quotes from nearly all content-body hrefs (verified: 5 quoted vs. 247 total hrefs on one sample page), so the tool silently compares almost nothing and always reports "0 diffs" regardless of real link changes. This likely affects every prior unit of this migration series that was verified the same way.

Re-ran the comparison with a corrected fingerprint (matching both quoted and unquoted href=) and got a real, fully-explained result:

  • 2 pages gain one new working link each — exactly the two paren fixes above (expected).
  • 2 pages (rs-5-4-14-february-2020.md, rs-5-6-0-april-2020.md) each have 5 hrefs change. In these, the render-link.html hook's own page-resolution logic corrects a second, independent pre-existing defect — a literal .md baked into the old appended sub-path text that never matched the site's pretty-URL scheme — to the canonical trailing-slash form, because the literal text is now visible to the hook directly instead of being hidden behind a shortcode placeholder until after the hook ran. Net effect is a link improvement, not a regression, but flagging it since the ticket's own tooling reported a false "0 diffs" for it.

No new Hugo build warnings/errors appeared under the operate/rs/release-notes prefix in either build (the only build-level errors are pre-existing and unrelated — jupyter-example/tabbed-clients-example data-file gaps under content/develop/clients/ and a JS-minifier error on an unrelated /commands/cf.reserve/ page).

Test plan

  • find content/operate/rs/release-notes -name '*.md' → 135 files, matches ticket estimate
  • Pre-flight checks run over the full file list; 2 genuine findings handled as above, rest clean
  • build/migrate_shortcode_links.py all run sequentially over all 135 files
  • Hugo built before and after conversion
  • build/diff_rendered_hrefs.py run with operate/rs/release-notes prefix filter; result cross-checked with a corrected quoted+unquoted href fingerprint (see tooling finding above) — all diffs traced to intentional/explained changes
  • Rendered-HTML spot check confirms the 3 list-nested callouts keep correct <li> nesting
  • No leftover relref/callout shortcodes anywhere in the directory

🤖 Generated with Claude Code


Note

Low Risk
Documentation-only mechanical migration under content/operate/rs/release-notes/ with no runtime or product behavior changes; residual risk is broken or shifted internal doc links, which the author validated with Hugo builds and href comparison.

Overview
Migrates 135 files under content/operate/rs/release-notes/ from Hugo relref and callout shortcodes to formats handled by render-link.html and render-blockquote.html.

Links: Roughly 2,400 {{< relref ... >}} usages become plain Markdown paths under /content/... (with _index.md or .md where needed). A few directory + sub-path relrefs were given an explicit / so concatenated URLs stay correct. Two pre-existing broken markdown links (missing )) were fixed so they render as links.

Callouts: 15 note / warning / similar shortcodes become > [!NOTE]-style blockquotes; three list-nested callouts were re-indented so blockquotes stay inside list items.

No intentional changes to release-note prose or product facts—syntax and link resolution only.

Reviewed by Cursor Bugbot for commit c7a6c0c. Bugbot is set up for automated code reviews on this repo. Configure here.

Convert the relref link shortcode and note/tip/warning/alert callout
shortcodes to their render-hook equivalents (plain Markdown links resolved
by render-link.html, `> [!NOTE]` etc. blockquotes resolved by
render-blockquote.html) across all 135 files under
content/operate/rs/release-notes/. Purely mechanical syntax migration; no
prose, terminology, or facts touched.

~2,397 relref calls and 15 callouts converted via
build/migrate_shortcode_links.py (sequential, all 3 stages).

Preflight found two real issues beyond the expected-clean checks:

- 3 list-nested callouts (rs-5-4-2-april-2019.md,
  rs-6-4-2-releases/rs-6-4-2-110.md, rs-6-4-2-releases/rs-6-4-2-61.md) had
  continuation lines outside the list's indent after conversion, which
  would have detached the blockquote from its `<li>`. Re-indented the
  continuation lines to match; verified via rendered-HTML diff that the
  `<li><p>...</p><div class="alert">...</div></li>` nesting is identical
  before/after.
- 26 relref calls across 13 files use an established (if unusual)
  convention: relref to a directory-style page immediately followed by a
  literal relative sub-path with no separating slash, relying on Hugo's
  relref rendering the target with an implicit trailing slash
  (`{{< relref "X" >}}sub/path`). The naive mechanical conversion
  concatenates these without a slash, silently producing a broken href.
  Inserted the missing "/" at each site so the rendered href is preserved.
- 2 genuinely pre-existing single-missing-close-paren bugs (FAILOVER in
  rs-6-2-4-august-2021.md, SLOWLOG GET in
  rs-6-4-2-releases/rs-6-4-2-94.md) left as plain, unlinked text before
  this change. Fixed trivially per the ticket's single-missing-paren
  carve-out.

build/diff_rendered_hrefs.py's HREF_RX (`href="[^"]*"`) only matches
double-quoted attributes; under `hugo --minify`, htmlmin drops quotes from
nearly all content-body hrefs, so the tool silently compares almost
nothing and always reports "0 diffs" regardless of real link changes.
Verified with a corrected quoted+unquoted fingerprint instead. Real
result: 2 pages gain a new working link (the two paren fixes, expected),
and 2 pages (rs-5-4-14-february-2020.md, rs-5-6-0-april-2020.md) change 5
hrefs each where the render-link.html hook's own page resolution corrects
a second, independent pre-existing defect -- a literal ".md" baked into
the old appended sub-path text that never matched the site's pretty-URL
scheme -- to the canonical trailing-slash form once the literal text is
visible to the hook instead of hidden behind a shortcode placeholder. Net
effect is a link improvement, not a regression, but it's a real href
change worth flagging since the ticket's tooling reported a false "0
diffs" for it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

DOC-7104

@github-actions

Copy link
Copy Markdown
Contributor

Staging links:
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/legacy-release-notes/redis-enterprise-5/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/legacy-release-notes/release-notes-redis-enterprise-software-v5-0-2/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/legacy-release-notes/rlec-0-99-february-2015/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/legacy-release-notes/rlec-4-0-june-2015/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/legacy-release-notes/rlec-4-2-october-2015/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/legacy-release-notes/rlec-4-3-aug-2016/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/legacy-release-notes/rlec-4-4-dec-2016/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/legacy-release-notes/rs-5-2-june-2018/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/legacy-release-notes/rs-5-4-10-december-2019/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/legacy-release-notes/rs-5-4-14-february-2020/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/legacy-release-notes/rs-5-4-2-april-2019/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/legacy-release-notes/rs-5-4-4-june-2019/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/legacy-release-notes/rs-5-4-6-july-2019/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/legacy-release-notes/rs-5-4-december-2018/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/legacy-release-notes/rs-5-5-preview-april-2019/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/legacy-release-notes/rs-5-6-0-april-2020/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/rs-6-0-12-january-2021/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/rs-6-0-20-april-2021/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/rs-6-0-8-september-2020/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/rs-6-0-may-2020/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/rs-6-2-10-february-2022/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/rs-6-2-12/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/rs-6-2-18-releases/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/rs-6-2-18-releases/rs-6-2-18-43/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/rs-6-2-18-releases/rs-6-2-18-49/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/rs-6-2-18-releases/rs-6-2-18-58/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/rs-6-2-18-releases/rs-6-2-18-65/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/rs-6-2-18-releases/rs-6-2-18-70/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/rs-6-2-4-august-2021/
https://redis.io/docs/staging/DOC-7104-release-notes/operate/rs/release-notes/rs-6-2-8-october-2021/

@dwdougherty dwdougherty left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This one needs a bit of work, as there are numerous malformed links that need to be fixed.


For more information, go here. For information, go to [Developing with
CRDBs]({{< relref "/operate/rs/databases/active-active" >}}develop/develop-for-aa/).
CRDBs](/operate/rs/databases/active-active/develop/develop-for-aa/).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This link is malformed.

Suggested change
CRDBs](/operate/rs/databases/active-active/develop/develop-for-aa/).
CRDBs](/content/operate/rs/databases/active-active/develop/develop-for-aa/_index.md).

Lists. Now all major Redis data types are supported with CRDT, so you
can use Redis Enterprise in an active-active manner for all your Redis
use cases, with seamless conflict resolution. [Click here]({{< relref "/operate/rs/databases/active-active" >}}develop/develop-for-aa/)
use cases, with seamless conflict resolution. [Click here](/operate/rs/databases/active-active/develop/develop-for-aa/)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
use cases, with seamless conflict resolution. [Click here](/operate/rs/databases/active-active/develop/develop-for-aa/)
use cases, with seamless conflict resolution. [Click here](/content/operate/rs/databases/active-active/develop/develop-for-aa/_index.md)

Comment on lines +23 to +27
- [RedisBloom](https://redislabs.com/redis-enterprise/redis-bloom/), version 2.2.1 (updated, [release notes](/operate/oss_and_stack/stack-with-enterprise/release-notes/redisbloom/redisbloom-2.2-release-notes.md#redisbloom-221-january-2020))
- [RedisGraph](https://redislabs.com/redis-enterprise/redis-graph/), version 2.0.1 (updated, [release notes](/operate/oss_and_stack/stack-with-enterprise/release-notes/redisgraph/redisgraph-2.0-release-notes.md#redisgraph-20-ga-201---january-2020))
- [RedisJSON](https://redislabs.com/redis-enterprise/redis-json/), version 1.0.4 (update, [release notes](/operate/oss_and_stack/stack-with-enterprise/release-notes/redisjson/redisjson-1.0-release-notes))
- [RediSearch](https://redislabs.com/redis-enterprise/redis-search/), version 1.4.25 (updated, [release notes](/operate/oss_and_stack/stack-with-enterprise/release-notes/redisearch/redisearch-1.4-release-notes.md#redisearch-1425-march-2020))
- [RedisTimeSeries](https://redislabs.com/redis-enterprise/redis-time-series/), version 1.2.3 (updated, [release notes](/operate/oss_and_stack/stack-with-enterprise/release-notes/redistimeseries/redistimeseries-1.2-release-notes))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

All these links need "/content" prepended to them, and a ".md" suffix.

Because HyperLogLog is a counting data structure by nature, conflicts can occur when deleting entries. For efficiency, performance and memory considerations, conflicts between instances are resolved with DEL (delete) operations winning over ADD operations that took place in concurrent or before the DEL operation.

For more information, check out the [HyperLogLog on Active-Active documentation]({{< relref "/operate/rs/databases/active-active" >}}develop/hyperloglog-active-active.md).
For more information, check out the [HyperLogLog on Active-Active documentation](/operate/rs/databases/active-active/develop/hyperloglog-active-active.md).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
For more information, check out the [HyperLogLog on Active-Active documentation](/operate/rs/databases/active-active/develop/hyperloglog-active-active.md).
For more information, check out the [HyperLogLog on Active-Active documentation](/content/operate/rs/databases/active-active/develop/hyperloglog-active-active.md).

Comment on lines +106 to +110
- [RedisBloom](https://redislabs.com/redis-enterprise/redis-bloom/), version [2.2.1](/operate/oss_and_stack/stack-with-enterprise/release-notes/redisbloom/redisbloom-2.2-release-notes)
- [RedisGraph](https://redislabs.com/redis-enterprise/redis-graph/), version [2.0.10](/operate/oss_and_stack/stack-with-enterprise/release-notes/redisgraph/redisgraph-2.0-release-notes)
- [RedisJson](https://redislabs.com/redis-enterprise/redis-json/), version [1.0.4](/operate/oss_and_stack/stack-with-enterprise/release-notes/redisjson/redisjson-1.0-release-notes)
- [RediSearch](https://redislabs.com/redis-enterprise/redis-search/), version [1.6.11](/operate/oss_and_stack/stack-with-enterprise/release-notes/redisearch/redisearch-1.6-release-notes) (updated)
- [RedisTimeSeries](https://redislabs.com/redis-enterprise/redis-time-series/), version [1.2.3](/operate/oss_and_stack/stack-with-enterprise/release-notes/redistimeseries/redistimeseries-1.2-release-notes)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Same kind of thing: missing "/content" at head of URL, no ".md" tail.

### Active-Active database persistence

The snapshot option for [data persistence on Active-Active databases]({{< relref "/operate/rs/databases/active-active" >}}manage/#data-persistence) will be deprecated in a future version of Redis Enterprise Software. If you have an Active-Active database using snapshot persistence, switch to AOF persistence. Use `crdb-cli` to do so:
The snapshot option for [data persistence on Active-Active databases](/operate/rs/databases/active-active/manage/#data-persistence) will be deprecated in a future version of Redis Enterprise Software. If you have an Active-Active database using snapshot persistence, switch to AOF persistence. Use `crdb-cli` to do so:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Missing "/content", etc.

#### Active-Active database persistence

The snapshot option for [data persistence on Active-Active databases]({{< relref "/operate/rs/databases/active-active" >}}manage/#data-persistence) will be deprecated in a future version of Redis Enterprise Software. If you have an Active-Active database using snapshot persistence, we strongly encourage you to switch to AOF persistence. Use `crdb-cli` to do so:
The snapshot option for [data persistence on Active-Active databases](/operate/rs/databases/active-active/manage/#data-persistence) will be deprecated in a future version of Redis Enterprise Software. If you have an Active-Active database using snapshot persistence, we strongly encourage you to switch to AOF persistence. Use `crdb-cli` to do so:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Missing "/content", etc.

- [RedisJSON v2.2.0](/content/operate/oss_and_stack/stack-with-enterprise/release-notes/redisjson/redisjson-2.2-release-notes.md#v220-july-2022)

- [RedisBloom v2.2.18]({{< relref "/operate/oss_and_stack/stack-with-enterprise/bloom" >}}release-notes/redisbloom-2.2-release-notes/#v2218-july-2022)
- [RedisBloom v2.2.18](/operate/oss_and_stack/stack-with-enterprise/bloom/release-notes/redisbloom-2.2-release-notes/#v2218-july-2022)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Missing "/content", etc.

Comment on lines +52 to +60
- [RediSearch v2.6.4](/operate/oss_and_stack/stack-with-enterprise/release-notes/redisearch/redisearch-2.6-release-notes/#v264-december-2022)

- [RedisJSON v2.4.5]({{< relref "/operate/oss_and_stack/stack-with-enterprise/release-notes/redisjson" >}}redisjson-2.4-release-notes/#v245-february-2023)
- [RedisJSON v2.4.5](/operate/oss_and_stack/stack-with-enterprise/release-notes/redisjson/redisjson-2.4-release-notes/#v245-february-2023)

- [RedisBloom v2.4.3]({{< relref "/operate/oss_and_stack/stack-with-enterprise/bloom" >}}release-notes/redisbloom-2.4-release-notes/#v24-ga-v243-november-2022)
- [RedisBloom v2.4.3](/operate/oss_and_stack/stack-with-enterprise/bloom/release-notes/redisbloom-2.4-release-notes/#v24-ga-v243-november-2022)

- [RedisGraph v2.10.5]({{< relref "/operate/oss_and_stack/stack-with-enterprise/release-notes/redisgraph" >}}redisgraph-2.10-release-notes/#v2105-december-2022)
- [RedisGraph v2.10.5](/operate/oss_and_stack/stack-with-enterprise/release-notes/redisgraph/redisgraph-2.10-release-notes/#v2105-december-2022)

- [RedisTimeSeries v1.8.5]({{< relref "/operate/oss_and_stack/stack-with-enterprise/release-notes/redistimeseries" >}}redistimeseries-1.8-release-notes/#v185-january-2023)
- [RedisTimeSeries v1.8.5](/operate/oss_and_stack/stack-with-enterprise/release-notes/redistimeseries/redistimeseries-1.8-release-notes/#v185-january-2023)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

All missing "/content", etc.

…l /content/*.md form

Review on this PR flagged malformed links: relref shortcodes originally
written as `{{< relref "/section" >}}literal/suffix/path` (relying on
relref's implicit trailing slash for a section target) only went through
stage 1 of migrate_shortcode_links.py (unwrap the shortcode) and never
matched stage 3's linkify pattern, so they were left as a bare
/operate/... path instead of the canonical /content/<path>.md[#anchor]
form used everywhere else in this migration.

Fixed 21 instances across 9 files (13 more than the 8 the reviewer
manually flagged -- found the rest with a corpus-wide grep for the same
shape). All 21 resolve to a real content file; verified via
build/diff_rendered_hrefs.py that the fix changes zero rendered hrefs
(140/140 pages match) and introduces zero new render-link warnings.

8 remaining instances in this same shape are genuinely pre-existing dead
links (2 different broken targets: content/operate/oss_and_stack/stack-with-enterprise/bloom/release-notes/*
doesn't exist -- the real bloom release notes live at
.../release-notes/redisbloom/*; and .../active-active/develop/hyperloglog-active-active.md
doesn't exist either) that predate this migration and were invisible to
any prior check, since Hugo's relref shortcode only validates its own
target, never text concatenated onto it afterward. Left unchanged
(same broken behavior before/after, no regression) and flagged in the
PR for a content decision rather than guessing the intended real target.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@andy-stark-redis

Copy link
Copy Markdown
Contributor Author

Fixed all 8 flagged instances plus 13 more of the same shape found by a corpus-wide grep (21 total, across 9 files) -- relref written as {{< relref "/section" >}}literal/suffix (relying on relref's implicit trailing slash for a section target) only went through stage 1 of migrate_shortcode_links.py (unwrap) and never matched stage 3's linkify, so it was left as a bare /operate/... path instead of the canonical /content/<path>.md[#anchor] form used everywhere else. All 21 now use the canonical form. Verified with build/diff_rendered_hrefs.py: 0 rendered href changes (140/140 pages match), 0 new render-link warnings.

8 remaining instances in the same shape are genuinely pre-existing dead links -- not something this PR can fix without guessing:

  • content/operate/oss_and_stack/stack-with-enterprise/bloom/release-notes/* doesn't exist. The real bloom release notes live at .../release-notes/redisbloom/* (5 instances across rs-6-2-10-february-2022.md, rs-6-2-12.md, rs-6-2-18-releases/rs-6-2-18-43.md, rs-6-2-18-releases/rs-6-2-18-49.md, rs-6-4-2-releases/rs-6-4-2-30.md, rs-6-4-2-releases/rs-6-4-2-43.md).
  • content/operate/rs/databases/active-active/develop/hyperloglog-active-active.md doesn't exist either (legacy-release-notes/rs-5-6-0-april-2020.md).

These were invisible to any prior check -- Hugo's relref shortcode only validates its own target, never text concatenated onto it afterward, so there was never a build warning. Post-migration, render-link now does flag them (WARN render-link: unresolved link "..."), so they're at least visible going forward, just not something I want to silently "fix" by guessing the intended target. Left unchanged (same broken link before/after this PR, no regression) -- flagging for a content decision on the real targets.

andy-stark-redis added a commit that referenced this pull request Sep 24, 2026
migrate_shortcode_links.py's linkify stage correctly canonicalizes almost
every converted link to /content/<path>.md[#anchor], but a link that
gets a manual post-hoc text fix after the pipeline already ran (e.g.
inserting a separator slash a relref-plus-literal-suffix concatenation
was missing) never gets a second pass through linkify. The result is a
bare /operate/... path that resolves to the exact same rendered href as
the canonical form, so build/diff_rendered_hrefs.py -- this migration's
usual verification -- is blind to it by construction.

Found on PR #4086 (release-notes/ unit): human review manually flagged 8
malformed links; a corpus-wide grep for the same shape found 21 across 9
files (13 more than manual review caught), plus 8 more that turned out
to be genuinely pre-existing dead links in the identical shape, invisible
to any prior check since Hugo's relref shortcode only ever validated its
own target, never text concatenated onto it afterward.

check_uncanonicalized_links.py reuses migrate_shortcode_links.py's own
resolver (_find_content_file) so a --fix run applies the exact same
rewrite the pipeline would have. Three outcomes: FIXABLE (resolves,
--fix rewrites it), MOUNT_ONLY (resolves only through a Hugo module
mount -- never auto-fixed, same rationale _find_content_file already
documents for not following mounts on a rewrite), DEAD (doesn't resolve
at all -- reported only, never guessed).

A second commit fixed the tool's own blind spot, found immediately on
its first real use: the original MOUNT_PREFIX_RX required a `/` or
end-of-string right after the mount name, so a bare `?query`/`#fragment`
with no slash before it (e.g. /commands?group=x) silently passed through
unchecked -- exactly the shape human review caught by hand across
DOC-7104 PR #4093/#4094/#4096/#4098. Also reconsidered the `/commands`
special case: it has no backing _index.md on disk so the filesystem
resolver always calls it unresolvable, but Hugo auto-generates a section
page for the directory and GetPage finds it anyway (confirmed by
building both /commands?group=x and /content/commands?group=x and
diffing rendered hrefs -- identical). Now hardcoded as FIXABLE instead
of silently skipped.

Verified against the pre-fix state of PR #4086: reproduces the exact
21 FIXABLE / 8 DEAD split. A full-corpus scan of content/ elsewhere
comes back to 3 unrelated hits, confirming it isn't noisy. 8 unit tests
cover both commits' behavior.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@andy-stark-redis
andy-stark-redis merged commit 736faaa into main Sep 24, 2026
99 checks passed
@andy-stark-redis
andy-stark-redis deleted the DOC-7104-release-notes branch September 24, 2026 13:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants