Skip to content

[Release notes] Product scoped amend and rebuilt registry - #4122

Open
lcawl wants to merge 6 commits into
mainfrom
changelog-note-registry-fixes-2
Open

lcawl wants to merge 6 commits into
mainfrom
changelog-note-registry-fixes-2

Conversation

@lcawl

@lcawl lcawl commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

Summary

NoteAmend is scoped to products in the notes map and those products get a registry plus shallow rebuild.
This PR is the third phase of fixes for changelog note registry issues.

Background

Relates to #4090, #4103

Per #4103 (comment), since the related issues touch the same areas of the code and have a significant, overlapping impact, this PR is part of a multi-PR phased approach.

Details

NoteAmend. It no longer lists every bundle/{product}/ prefix. It only processes products that appear in the product×version notes map, writes bundle_seq on product-scoped indexes, and still refreshes the legacy notes-{version}.json path list. Other products’ .amend-notes.yaml files are not deleted. ReconcileAsync returns products that had a sidecar write, skip-unchanged, or delete.

Scrubber. After notes work, each returned product runs BundleRegistryReconciler.ReconcileGroupAsync and is added to the bundle shallow map, using the same SQS message ids. A registry failure fails those notes messages.

Tests and docs. Isolation coverage is in NoteAmendReconcilerTests and ScrubberProcessorTests. cmd-note.md and changelog-bundle-registry.md describe the per-product sidecar and registry rebuild.

Screenshots

When I revert work-arounds (remove local copy of note amend bundles and change the directive to pull from CDN):

:::{changelog} cloud-enterprise
:config: /changelog.yml
:link-visibility: keep-links
:description-visibility: keep-descriptions
:highlights:
:::

...it's now successfully finding and rendering the cloud-4.2.0.amend-notes.yaml:

image

I do not know how to test the other S3 file handling changes until the stacked PRs are merged.

Generative AI disclosure

  1. Did you use a generative AI (GenAI) tool to assist in creating this contribution?
  • Yes
  • No
  1. If you answered "Yes" to the previous question, please specify the tool(s) and model(s) used (e.g., Google Gemini, OpenAI ChatGPT-4, etc.).

Tool(s) and model(s) used: Cursor Grok 4.6

@github-actions

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

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.

Requesting changes due to a high-confidence correctness regression noted inline that can leave product registry state stale after partial failure/retry.


What is this? | From workflow: PR Review

Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.

@github-actions github-actions Bot left a comment

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.

Requesting changes based on a high-confidence correctness regression noted inline.


What is this? | From workflow: PR Review

Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.

@github-actions github-actions Bot left a comment

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.

Requesting changes due to a correctness issue called out inline.


What is this? | From workflow: PR Review

Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.

@github-actions github-actions Bot left a comment

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.

Requesting changes due to a high-confidence correctness issue in the no-late-notes retry path that can leave stale amend sidecar/registry state.


What is this? | From workflow: PR Review

Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.

@github-actions github-actions Bot left a comment

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.

Requesting changes due to a high-confidence correctness regression noted inline.


What is this? | From workflow: PR Review

Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.

@github-actions github-actions Bot left a comment

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.

Approved: no new actionable issues found.


What is this? | From workflow: PR Review

Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.

Comment on lines +123 to +128
if (write.Notes.Count == 0)
{
if (touchedProducts.Contains(write.Product))
emptyIndexes.Add(new NoteAmendEmptyIndex(write.Product, indexKey));
return;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Severity: P2 (Medium)

Vanished indexes are only queued for deletion when their product touched a sidecar. If a note is deleted or retargeted before any bundle ships, ProcessProductAsync returns false and the old product-scoped index remains, even on subsequent reconciles. It still lists the old note path; CDN note fetching treats that list as authoritative and fails bundling when the deleted note cannot be fetched. Allow stale-index cleanup when no published bundle needs sidecar work.

Generated by Libra. React with 👍 or 👎 to give feedback on this comment.

Comment on lines +139 to +145
foreach (var (product, version) in vanished)
{
if (!map.TryGetValue(product, out var byVer))
map[product] = byVer = [with(StringComparer.Ordinal)];
if (!byVer.ContainsKey(version))
byVer[version] = [];
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Severity: P3 (Low)

These empty buckets also represent failed reads, not just vanished notes: ExtractProductVersionsAsync catches a source GET failure and returns no pairs. Passing that result to amend reconciliation now deletes a live note's published .amend-notes sidecar and refreshes the registry without it. The batch can then succeed, so the note stays unpublished until another event triggers reconciliation. Propagate source-read failures instead of treating an incomplete inventory as evidence of deletion.

Generated by Libra. React with 👍 or 👎 to give feedback on this comment.

Comment on lines +151 to +156
AddShallow(shallowWork, bundleScope, messageId);
foreach (var empty in amend.EmptyProductIndexes)
{
if (!string.Equals(empty.Product, product, StringComparison.Ordinal))
continue;
await notesReconciler.DeleteIndexAsync(empty.Key, ctx);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Severity: P3 (Low)

Keep the vanished-product index until the bundle shallow-map update also succeeds. On the last-note deletion, this removes the retry breadcrumb before the later shallow pass runs. If writing bundle/registry.json fails, the message is redelivered, but the product is now absent from the notes map and no bundle shallow work is scheduled on retry. The shallow change token therefore remains stale despite a successful retry.

Generated by Libra. React with 👍 or 👎 to give feedback on this comment.

Base automatically changed from changelog-note-registry-fixes to main November 4, 2026 13:01
@Mpdreamz
Mpdreamz force-pushed the changelog-note-registry-fixes-2 branch from 38bf4d9 to 75cddb8 Compare November 4, 2026 13:01

@Mpdreamz Mpdreamz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Reviewed the source and tests. The scoping of amend to the products in the notes map, the reconciler-owned sidecars and the retry-after-registry-failure path all look right. One gap I'd fix before merging.

A vanished product-scoped index is only deleted when its product was "touched". RewriteNotesIndexesAsync adds an empty index to emptyIndexes only if (touchedProducts.Contains(write.Product)). ProcessProductAsync returns false, so the product is not touched, when the product has no bundle registry (404, or no bundles) or no parent bundle matches the version. In both cases the index is not rewritten and not deleted.

Scenario:

  1. A note for kibana at 9.0.0 is published, so notes-kibana-9.0.0.json lists it.
  2. The note is removed before any 9.0.0 bundle exists.
  3. ReconcileRepoAsync returns kibana → 9.0.0 → [] and keeps the key, which is what ReconcileRepo_ProductScopedStale_ReturnedAsEmptyBucketWithoutDeleting asserts.
  4. Amend finds no registry or parent bundle, so kibana is not touched, and the key stays with its old note list.
  5. When kibana@9.0.0 is bundled later, FetchNotesAsync finds the product index, so it does not fall back to the legacy key. The removed note 404s, and the fetch reports "listed in the notes index but could not be fetched".

Every later reconcile finds the same vanished index and skips it the same way. Before this stack, DeleteStaleIndexes removed the stale index in the same pass.

I did not run this. It comes from reading RewriteNotesIndexesAsync, ProcessProductAsync and the tests: NoPublishedBundle_NoAmend and NoBundleForVersion_NoAmend_SeqRemainsZero don't pass a vanished product, and the other tests cover only the case where a bundle exists.

Suggested fix: when a product has no sidecar to drop (no registry, or no matching parent bundle), delete its empty index in the same pass. Then add a test for a vanished product with no published bundle, asserting the key is deleted.

I merged #4120, so this branch needs a rebase onto main.

This branch had an error being deployed

1 failed and 1 active deployments
docs-preview — 206da91e Deployed Nov 4, 2026 by github-actions[bot]
assembler-preview — 206da91e Deployed Nov 4, 2026 by github-actions[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants