Skip to content

Publish the chart catalog as generated content - #2

Merged
tannerlinsley merged 5 commits into
mainfrom
taren/charts-catalog-content
Jul 29, 2026
Merged

Publish the chart catalog as generated content#2
tannerlinsley merged 5 commits into
mainfrom
taren/charts-catalog-content

Conversation

@tannerlinsley

@tannerlinsley tannerlinsley commented Jul 29, 2026

Copy link
Copy Markdown
Member

Publishes the catalog as a versioned schema-v2 artifact on catalog-dist for native rendering by tanstack.com.

  • emits content-hashed per-case ESM closures
  • keeps comparison implementations out of default closures
  • validates hashes, graph closure, source bindings, and size budgets
  • removes the standalone Cloudflare Worker deployment
  • preserves the local authoring catalog

Summary by CodeRabbit

  • New Features
    • Added an artifact-based catalog publication pipeline that updates a dedicated distribution branch after successful validation.
    • Introduced schema-v2 “catalog artifact” generation and validation.
  • Bug Fixes
    • Strengthened catalog manifest verification, reachable asset/module closure checks, and strict size/path/integrity (byte/hash) enforcement.
  • Documentation
    • Updated conformance and API-friction docs to reflect the schema-v2 artifact and embed/route contract.
  • Refactor
    • Replaced prior site/worker deployment and live smoke checks with graph/artifact validation.
  • Tests
    • Added dedicated artifact creation/check validation coverage.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 16 seconds

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 78fc4b65-a22d-41d6-a413-9f91770e2a71

📥 Commits

Reviewing files that changed from the base of the PR and between bf30f6e and d896e86.

📒 Files selected for processing (12)
  • .github/workflows/chart-library-benchmarks.yml
  • API-FRICTION.md
  • benchmarks/bundle-size/universal-baseline.json
  • benchmarks/comparison/README.md
  • benchmarks/comparison/bundle-baseline.json
  • examples/conformance/vite.config.ts
  • scripts/build-conformance-artifact.mjs
  • scripts/catalog-artifact.mjs
  • scripts/catalog-artifact.test.mjs
  • scripts/check-catalog-loading.mjs
  • scripts/check-conformance-artifact.mjs
  • scripts/compare-chart-libraries.mjs
📝 Walkthrough

Walkthrough

The catalog pipeline now generates a schema-v2 artifact from the Vite manifest, validates its module closure and hashes, uploads it from CI, and publishes it to catalog-dist. Previous site and Worker deployment scripts are removed or replaced with artifact checks and updated documentation.

Changes

Catalog artifact publication

Layer / File(s) Summary
Schema-v2 artifact contract
scripts/catalog-artifact.mjs, scripts/catalog-artifact.test.mjs
Builds and validates catalog metadata, hashed module assets, import closures, comparison visibility, and embed contracts, with tests for determinism, cycles, unsafe paths, and invalid manifests.
Artifact build and validation pipeline
scripts/build-conformance-artifact.mjs, scripts/check-conformance-artifact.mjs, scripts/check-catalog-loading.mjs, examples/conformance/*, package.json
Builds .catalog-artifact from conformance metadata and Vite output, then verifies graph membership, file sets, sizes, hashes, source paths, and schema invariants.
Validated artifact branch publication
.github/workflows/chart-library-benchmarks.yml, .gitignore
Uploads the hidden artifact from validation and publishes changed contents to catalog-dist on pushes to main.
Publication contract documentation
benchmarks/conformance/README.md, API-FRICTION.md
Documents schema-v2 routes, artifact contents, debug comparison modules, embed rules, and generated branch hosting.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ConformanceCases
  participant BuildArtifact
  participant ArtifactValidator
  participant ValidateWorkflow
  participant CatalogDist

  ConformanceCases->>BuildArtifact: provide case metadata and Vite manifest
  BuildArtifact->>ArtifactValidator: construct catalog.json and asset closure
  ArtifactValidator-->>ValidateWorkflow: return validated artifact
  ValidateWorkflow->>CatalogDist: publish catalog.json and hashed assets
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: publishing the chart catalog as generated content instead of via the old deployment path.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch taren/charts-catalog-content

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (5)
scripts/build-conformance-artifact.mjs (1)

115-139: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

validateCaseIdentities duplicates validateCaseEntries in scripts/catalog-artifact.mjs.

Same id/order/regex rules, re-implemented with throw instead of assert. The --check path and the build path can silently drift. Export validateCaseEntries from catalog-artifact.mjs and reuse it here.

♻️ Proposed reuse
 import {
   attachEmbedContract,
   createCatalogArtifact,
   serializeCatalogManifest,
+  validateCaseEntries,
   validateCatalogArtifactManifest,
 } from './catalog-artifact.mjs'
 if (checkOnly) {
-  validateCaseIdentities(cases)
+  validateCaseEntries(cases)
   console.log(`Validated ${cases.length} publishable catalog cases.`)
   process.exit(0)
 }

Then delete validateCaseIdentities and add export to validateCaseEntries in scripts/catalog-artifact.mjs.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/build-conformance-artifact.mjs` around lines 115 - 139, Export
validateCaseEntries from scripts/catalog-artifact.mjs and import and reuse it in
the build script’s validation flow. Remove validateCaseIdentities and its
duplicated id, order, and regex checks so both --check and build paths share the
same validation implementation and assertion behavior.
.github/workflows/chart-library-benchmarks.yml (1)

156-164: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Add a concurrency group so overlapping pushes can't race on catalog-dist.

Two pushes to main in quick succession run this job twice; the second worktree is created from a stale origin/catalog-dist, and the non-fast-forward push simply fails (or, worse, an older revision wins if the ordering flips). A serialized concurrency group makes publication deterministic.

🛠️ Proposed change
   publish-catalog:
     if: github.event_name == 'push' && github.ref == 'refs/heads/main'
     needs:
       - validate
       - conformance
     runs-on: ubuntu-latest
     timeout-minutes: 10
+    concurrency:
+      group: publish-catalog
+      cancel-in-progress: false
     permissions:
       contents: write
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/chart-library-benchmarks.yml around lines 156 - 164, Add a
workflow-level concurrency group to the publish-catalog job, using a stable key
shared by all runs that publish catalog-dist and preventing overlapping
executions. Keep the existing publish-catalog conditions, dependencies,
permissions, and timeout unchanged.
scripts/check-conformance-artifact.mjs (1)

24-33: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Expected catalog counts are duplicated across the two check scripts. scripts/check-conformance-artifact.mjs asserts 100 cases and 68/21/11 renderer counts, and scripts/check-catalog-loading.mjs asserts the same numbers against the Vite graph. Adding or reclassifying a case requires editing both, and a partial update yields a confusing single-script failure.

  • scripts/check-conformance-artifact.mjs#L24-L33: import the expected counts from a shared module (e.g. exported constants in scripts/catalog-artifact.mjs) instead of inlining them.
  • scripts/check-catalog-loading.mjs#L90-L96: consume the same shared constants for the tanstack/plot/recharts/echarts expectations.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/check-conformance-artifact.mjs` around lines 24 - 33, Centralize the
expected catalog counts in shared exports from scripts/catalog-artifact.mjs,
then update the assertions in check-conformance-artifact.mjs and
check-catalog-loading.mjs to consume those constants instead of duplicating
numeric literals. Preserve the existing case-count and renderer-specific
expectations, including the tanstack, plot, recharts, and echarts checks.
scripts/catalog-artifact.test.mjs (1)

171-187: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

The unreferenced-asset case is never actually exercised.

validateCatalogArtifactManifest asserts comparison.visibility === 'debug' well before the closure reachability check, so the injected assets/extra-GGGG7777.js orphan is irrelevant here — the test would pass identically without it. Split into two tests so the "assets outside the implementation closure" assertion is covered.

💚 Proposed split
-  it('rejects unreferenced files and non-debug comparisons', async () => {
+  it('rejects assets outside the implementation closure', async () => {
     const artifact = await createArtifact()
     const catalog = attachEmbedContract(artifact.catalog, {
       protocol: { version: 1 },
     })
     catalog.assets['assets/extra-GGGG7777.js'] = {
       bytes: 1,
       sha256: 'b'.repeat(64),
       imports: [],
       dynamicImports: [],
     }
-    catalog.cases[0].modules.comparison.visibility = 'public'
+
+    expect(() => validateCatalogArtifactManifest(catalog)).toThrow(
+      'assets outside the implementation closure',
+    )
+  })
+
+  it('rejects non-debug comparisons', async () => {
+    const artifact = await createArtifact()
+    const catalog = attachEmbedContract(artifact.catalog, {
+      protocol: { version: 1 },
+    })
+    catalog.cases[0].modules.comparison.visibility = 'public'
 
     expect(() => validateCatalogArtifactManifest(catalog)).toThrow(
       'comparison must be debug-only',
     )
   })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/catalog-artifact.test.mjs` around lines 171 - 187, Split the combined
test around validateCatalogArtifactManifest into separate cases: keep the
non-debug comparison test focused only on visibility, and add a distinct test
that leaves comparison.visibility as debug while injecting
assets/extra-GGGG7777.js, then asserts the unreferenced-asset validation error.
scripts/check-catalog-loading.mjs (1)

16-21: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cross-check depends on two independent Vite builds producing identical content hashes.

inspectCatalogGraph() runs a fresh in-memory build and then verifyPublishedGraph matches artifact asset paths against chunksByFile by hashed filename. Any environment difference between this build and the one behind .catalog-artifact (base path, mode, env vars, plugin ordering) surfaces as a confusing published artifact contains unknown chunk …. Also, a missing artifact fails with a bare ENOENT rather than a hint to run pnpm catalog:build.

♻️ Clearer failure for a missing artifact
-const artifact = JSON.parse(
-  await fs.readFile(path.join(artifactDirectory, 'catalog.json'), 'utf8'),
-)
+const catalogPath = path.join(artifactDirectory, 'catalog.json')
+let artifactSource
+try {
+  artifactSource = await fs.readFile(catalogPath, 'utf8')
+} catch (error) {
+  throw new Error(
+    `Missing ${catalogPath}; run \`pnpm catalog:build\` first.`,
+    { cause: error },
+  )
+}
+const artifact = JSON.parse(artifactSource)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/check-catalog-loading.mjs` around lines 16 - 21, Update the check
flow around inspectCatalogGraph and verifyPublishedGraph so graph inspection
uses the same build inputs or metadata as the catalog artifact instead of
performing an independent build with potentially different configuration. Also
handle missing catalog.json before fs.readFile and report an actionable message
directing the user to run pnpm catalog:build, while preserving
validateCatalogArtifactManifest and verification for existing artifacts.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In @.github/workflows/chart-library-benchmarks.yml:
- Around line 156-164: Add a workflow-level concurrency group to the
publish-catalog job, using a stable key shared by all runs that publish
catalog-dist and preventing overlapping executions. Keep the existing
publish-catalog conditions, dependencies, permissions, and timeout unchanged.

In `@scripts/build-conformance-artifact.mjs`:
- Around line 115-139: Export validateCaseEntries from
scripts/catalog-artifact.mjs and import and reuse it in the build script’s
validation flow. Remove validateCaseIdentities and its duplicated id, order, and
regex checks so both --check and build paths share the same validation
implementation and assertion behavior.

In `@scripts/catalog-artifact.test.mjs`:
- Around line 171-187: Split the combined test around
validateCatalogArtifactManifest into separate cases: keep the non-debug
comparison test focused only on visibility, and add a distinct test that leaves
comparison.visibility as debug while injecting assets/extra-GGGG7777.js, then
asserts the unreferenced-asset validation error.

In `@scripts/check-catalog-loading.mjs`:
- Around line 16-21: Update the check flow around inspectCatalogGraph and
verifyPublishedGraph so graph inspection uses the same build inputs or metadata
as the catalog artifact instead of performing an independent build with
potentially different configuration. Also handle missing catalog.json before
fs.readFile and report an actionable message directing the user to run pnpm
catalog:build, while preserving validateCatalogArtifactManifest and verification
for existing artifacts.

In `@scripts/check-conformance-artifact.mjs`:
- Around line 24-33: Centralize the expected catalog counts in shared exports
from scripts/catalog-artifact.mjs, then update the assertions in
check-conformance-artifact.mjs and check-catalog-loading.mjs to consume those
constants instead of duplicating numeric literals. Preserve the existing
case-count and renderer-specific expectations, including the tanstack, plot,
recharts, and echarts checks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7deeb63a-34a0-4b9d-aa83-dcca8935adb7

📥 Commits

Reviewing files that changed from the base of the PR and between a1f611d and 1fcf2d1.

📒 Files selected for processing (20)
  • .github/workflows/chart-library-benchmarks.yml
  • .gitignore
  • API-FRICTION.md
  • benchmarks/conformance/README.md
  • deploy/catalog/_headers
  • examples/conformance/package.json
  • examples/conformance/vite.config.ts
  • package.json
  • scripts/build-conformance-artifact.mjs
  • scripts/build-conformance-site.mjs
  • scripts/catalog-artifact.mjs
  • scripts/catalog-artifact.test.mjs
  • scripts/catalog-deployment.test.mjs
  • scripts/check-catalog-deployment.mjs
  • scripts/check-catalog-loading.mjs
  • scripts/check-conformance-artifact.mjs
  • scripts/check-conformance-site.mjs
  • scripts/check-local-catalog-worker.mjs
  • scripts/stage-conformance-deployment.mjs
  • wrangler.catalog.jsonc
💤 Files with no reviewable changes (8)
  • wrangler.catalog.jsonc
  • scripts/check-local-catalog-worker.mjs
  • deploy/catalog/_headers
  • scripts/build-conformance-site.mjs
  • scripts/stage-conformance-deployment.mjs
  • scripts/catalog-deployment.test.mjs
  • scripts/check-catalog-deployment.mjs
  • scripts/check-conformance-site.mjs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/chart-library-benchmarks.yml (1)

156-164: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Serialize catalog-dist publication.

Two pushes to main can run this job at the same time, both publish from the same catalog-dist base, and one push will fail on a non-fast-forward update. Add a job-level concurrency group so publications queue instead of racing.

Proposed fix
   publish-catalog:
     if: github.event_name == 'push' && github.ref == 'refs/heads/main'
     needs:
       - validate
       - conformance
     runs-on: ubuntu-latest
     timeout-minutes: 10
+    concurrency:
+      group: catalog-dist-publication
+      cancel-in-progress: false
     permissions:
       contents: write
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/chart-library-benchmarks.yml around lines 156 - 164, Add a
job-level concurrency configuration to publish-catalog so all catalog-dist
publications share one group and queue rather than run concurrently. Keep the
existing publish-catalog conditions, dependencies, permissions, and timeout
unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/chart-library-benchmarks.yml:
- Around line 25-27: Disable persisted checkout credentials for the
artifact-producing jobs by adding persist-credentials: false to the
actions/checkout steps in .github/workflows/chart-library-benchmarks.yml at
lines 25-27, 60-62, 87-89, and 123-125, corresponding to validate, compare,
conformance, and stress. Leave publish-catalog unchanged because it requires
push authentication.

---

Outside diff comments:
In @.github/workflows/chart-library-benchmarks.yml:
- Around line 156-164: Add a job-level concurrency configuration to
publish-catalog so all catalog-dist publications share one group and queue
rather than run concurrently. Keep the existing publish-catalog conditions,
dependencies, permissions, and timeout unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8b8432f1-c1dc-429e-b1ff-a442d7231b37

📥 Commits

Reviewing files that changed from the base of the PR and between 1fcf2d1 and b7d03ad.

📒 Files selected for processing (2)
  • .github/workflows/chart-library-benchmarks.yml
  • API-FRICTION.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • API-FRICTION.md

Comment thread .github/workflows/chart-library-benchmarks.yml
@tannerlinsley
tannerlinsley merged commit 79ae8db into main Jul 29, 2026
8 checks passed
@tannerlinsley
tannerlinsley deleted the taren/charts-catalog-content branch July 29, 2026 06:06
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.

1 participant