Skip to content

Conversation

@sagarkori143
Copy link
Contributor

@sagarkori143 sagarkori143 commented Aug 24, 2025

Description

  • Startin writing the intergration tests
  • Just Started with a basic setup and base tests for post list file

Summary by CodeRabbit

  • New Features

    • Build runners now accept CLI options for customizing input/output paths and can be invoked directly without changing defaults.
  • Content

    • Added new language tags (FastAPI, Django); simplified meetings list to a single "Community Meeting"; refreshed newsroom videos and two new blog posts.
  • Refactor

    • Test discovery updated to exclude integration tests by default.
  • Tests

    • Many comprehensive integration suites added to validate end-to-end outputs (pages, posts, dashboard, adopters, tools, meetings, finance, newsroom videos, etc.).
  • Chores

    • Consolidated test flow into a single script that runs unit then integration.

@netlify
Copy link

netlify bot commented Aug 24, 2025

Deploy Preview for asyncapi-website ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit 6b187fe
🔍 Latest deploy log https://app.netlify.com/projects/asyncapi-website/deploys/691a353c28c18a000826635d
😎 Deploy Preview https://deploy-preview-4353--asyncapi-website.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 24, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

Exports many runner interfaces/functions, tightens CLI execution guards (module vs test), changes scripts API (adopters), centralizes test wiring in package.json, adds extensive integration tests, test fixtures/helpers, and updates several config JSON/data files.

Changes

Cohort / File(s) Summary
Test config & scripts
jest.config.js, package.json
Remove integration glob from Jest testMatch (comment updated to "except integration"); add composite test script that runs test:unit then test:integration; adjust test:unit/test:integration patterns; add nock dependency.
Runners — exports & CLI guards
npm/runners/*
npm/runners/build-pages-runner.ts, .../build-post-list-runner.ts, .../build-adopters-list-runner.ts, .../build-dashboard-runner.ts, .../build-meetings-runner.ts, .../build-newsroom-videos-runner.ts, .../build-tools-runner.ts, .../case-studies-runner.ts
Export BuildOptions interfaces and runBuild functions (where added), change top-level execution to guarded module run (import.meta.url or NODE_ENV/VITEST_WORKER_ID checks) instead of always auto-running in runtime/tests, add CLI arg parsing (e.g., --outputFile, --basePath), and enhance error context/logging in multiple runners.
Scripts API change
scripts/adopters/index.ts, scripts/index.ts
Change buildAdoptersList signature to accept (sourcePath: string, targetPath: string); add input validation and contextual errors; update call site in scripts/index.ts.
New & updated integration tests & fixtures
tests/integration/*, tests/integration/fixtures/*, tests/integration/helpers/*
Add many integration suites (pages, post-list, dashboard, tools, adopters, meetings, newsroom-videos, finance, case-studies, compose-blog, build-tools, etc.), extensive nock fixtures and mock data, and helpers (file-utils, build-pages lock). Tests cover happy paths, errors, edge cases, pagination, and export/type safety.
Unit & other tests updates
tests/* (various)
Update unit tests: adopters tests updated for new signature; build-rss/locals/edit-links tests extended; index/finance tests added; use fs.promises in cleanup; format changes in jest.doMock calls.
Config/data updates
config/all-tags.json, config/meetings.json, config/newsroom_videos.json
Add new language entries ("FastAPI", "Django") in tags JSON; replace many meetings entries with a single "Community Meeting" object; replace/reshape newsroom videos array (content edits).
Script & helper function API changes
scripts/adopters/index.ts, scripts/index.ts, scripts/*
Change function signature and call sites for adopters builder; adjust writes to accept explicit target paths; strengthen input validation and error wrapping.
Misc test helpers
tests/integration/helpers/file-utils.ts, tests/integration/helpers/build-pages-lock.ts
Add recursive getAllFiles and build-pages lock/wait helpers for integration tests.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant CLI as Runner module (CLI)
  participant MOD as Module import (tests)
  participant FS as File System
  participant TEST as Test code

  CLI->>CLI: module executed directly (import.meta.url / process checks)
  CLI->>CLI: parse CLI args (--outputFile/--basePath)
  CLI->>FS: runBuildX(options) reads/writes files
  CLI-->>CLI: exit(0) / exit(1) on error

  Note right of MOD: when imported (tests)
  TEST->>MOD: import runBuildX
  TEST->>MOD: call runBuildX({ ... })
  MOD->>FS: perform operations, return Promise
  TEST-->>MOD: assert outputs
Loading
sequenceDiagram
  autonumber
  participant Pages as build-pages-runner
  participant PostList as build-post-list-runner
  participant Temp as Temp dir
  participant FS as File System

  Temp->>Pages: provide basePath
  Pages->>FS: generate pages into basePath
  Pages-->>Temp: pages created
  Temp->>PostList: call with basePath + outputPath
  PostList->>FS: read pages, write posts.json to outputPath
  PostList-->>Temp: posts.json created
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Potential hotspots to inspect:

  • Consistency of CLI guard logic across all runners (import.meta.url vs NODE_ENV/VITEST_WORKER_ID).
  • Public API changes: exported interfaces/functions and scripts/adopters signature + callers.
  • New integration nock fixtures for flakiness/race conditions.
  • Large JSON content replacements (meetings/newsroom_videos) for accuracy.

Possibly related PRs

Suggested reviewers

  • derberg
  • akshatnema
  • sambhavgupta0705
  • vishvamsinh28
  • devilkiller-ag
  • anshgoyalevil
  • TRohit20

Poem

I hop through code with nimble paws,
Exports unpacked and guarded claws.
Tests now bloom in temp-land rows,
JSON carrots in tidy rows.
A rabbit's cheer for builds that pass — hooray! 🥕🐇

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'test: adding integration tests setup' is directly related to the main objective of the pull request, which is to set up integration tests infrastructure and add comprehensive integration test files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@sagarkori143 sagarkori143 changed the title Adding integration tests setup test: Adding integration tests setup Aug 24, 2025
@sagarkori143 sagarkori143 changed the title test: Adding integration tests setup test: adding integration tests setup Aug 24, 2025
@codecov
Copy link

codecov bot commented Aug 24, 2025

Codecov Report

❌ Patch coverage is 40.00000% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 55.25%. Comparing base (8ddbe47) to head (6b187fe).

Files with missing lines Patch % Lines
scripts/adopters/index.ts 42.85% 6 Missing and 2 partials ⚠️
scripts/index.ts 0.00% 1 Missing ⚠️
Additional details and impacted files
@@                    Coverage Diff                     @@
##           add-integration-tests    #4353       +/-   ##
==========================================================
- Coverage                 100.00%   55.25%   -44.75%     
==========================================================
  Files                         21       21               
  Lines                        828      838       +10     
  Branches                     165      169        +4     
==========================================================
- Hits                         828      463      -365     
- Misses                         0      340      +340     
- Partials                       0       35       +35     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@akshatnema akshatnema added the gsoc This label should be used for issues or discussions related to ideas for Google Summer of Code label Aug 24, 2025
@akshatnema
Copy link
Member

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 24, 2025

✅ Actions performed

Full review triggered.

outputPath = path.join(tempDir, outputFileName);

// Run the build-pages-runner before build-post-list-runner
execSync('npx tsx npm/runners/build-pages-runner.ts', { stdio: 'inherit' });
Copy link
Member

Choose a reason for hiding this comment

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

Can't we directly run npm scripts?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can't use an npm script here because the test creates a unique temporary directory for each run and expects the runner to write the output file inside that directory.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's why for every command I am passing the base path and file name for using it as a temp location for the outputs.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 24, 2025

✅ Actions performed

Full review triggered.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (2)
npm/runners/build-post-list-runner.ts (2)

31-38: Honor basePath when deriving default directories

Defaults for postDirectories are hardcoded relative to currentDirPath, so providing options.basePath won’t affect discovery. Compute basePath first, then derive directories from it. This is important when the CLI passes a basePath.

-    // Use provided options or fall back to default production paths
-    const postDirectories = options.postDirectories || [
-      [resolve(currentDirPath, '../../pages/blog'), '/blog'],
-      [resolve(currentDirPath, '../../pages/docs'), '/docs'],
-      [resolve(currentDirPath, '../../pages/about'), '/about']
-    ];
-    const basePath = options.basePath || resolve(currentDirPath, '../../pages');
+    // Use provided options or fall back to default production paths
+    const basePath = options.basePath || resolve(currentDirPath, '../../pages');
+    const postDirectories = options.postDirectories || [
+      [resolve(basePath, 'blog'), '/blog'],
+      [resolve(basePath, 'docs'), '/docs'],
+      [resolve(basePath, 'about'), '/about']
+    ];
     const outputPath = options.outputPath || resolve(currentDirPath, '../../config', 'posts.json');

53-77: CLI bug: --basePath is ignored and the runner always uses defaults; also add “main” guard and minimal arg validation

  • The CLI computes outputPath from --basePath but never passes basePath into runBuildPostList, so the script still uses the default pages base. This is surprising and breaks the expected contract of the option.
  • The runner self-executes on import. If any module imports this file for types or helpers, you’ll trigger a build as a side effect.
  • If a flag is present without a value (e.g., --outputFile at the end), you’ll read undefined.

Fix: guard execution to “run when main”, minimally validate args, and pass basePath through.

-// Self-executing async function to handle top-level await
-(async () => {
-  try {
-    // Extract the file name and basePath from the CLI command
-    const outputFileArgIndex = process.argv.indexOf('--outputFile');
-    const outputFileName = outputFileArgIndex === -1 ? 'posts.json' : process.argv[outputFileArgIndex + 1];
-
-    const basePathArgIndex = process.argv.indexOf('--basePath');
-    const basePath = basePathArgIndex === -1 ? undefined : process.argv[basePathArgIndex + 1];
-
-    // Build outputPath using resolve(basePath, outputFileName)
-    let outputPath;
-
-    if (basePath) {
-      outputPath = resolve(basePath, outputFileName);
-    } else {
-      outputPath = resolve(currentDirPath, '../../config', outputFileName);
-    }
-
-    await runBuildPostList({ outputPath });
-  } catch (error) {
-    // Ensure we exit with error code
-    process.exit(1);
-  }
-})();
+// Run only when invoked directly (not when imported)
+if (fileURLToPath(import.meta.url) === process.argv[1]) {
+  (async () => {
+    try {
+      const getFlagValue = (flag: string, def?: string) => {
+        const idx = process.argv.indexOf(flag);
+        if (idx === -1) return def;
+        const val = process.argv[idx + 1];
+        if (!val || val.startsWith('--')) return def;
+        return val;
+      };
+
+      const outputFileName = getFlagValue('--outputFile', 'posts.json')!;
+      const basePath = getFlagValue('--basePath', undefined);
+
+      const outputPath = basePath
+        ? resolve(basePath, outputFileName)
+        : resolve(currentDirPath, '../../config', outputFileName);
+
+      await runBuildPostList({ outputPath, basePath });
+    } catch (error) {
+      // Ensure we exit with error code
+      process.exit(1);
+    }
+  })();
+}

Note: fileURLToPath is already imported in this file. If you prefer a stronger check, compare against new URL(process.argv[1], 'file:').href === import.meta.url. I can provide that variant too.

🧹 Nitpick comments (7)
jest.config.js (1)

16-20: Comment and behavior mismatch: integration tests are not excluded by default

The comment says “Default: all tests except integration”, but the config still matches all tests under tests/, including tests/integration. Also, Jest’s testMatch does not support negation globs like '!/netlify//.test.'—use testPathIgnorePatterns instead.

Apply this diff to make the behavior match the comment and avoid relying on unsupported negation:

-  // Default: all tests except integration
-  testMatch: [
-    '**/tests/**/*.test.*',
-    '!**/netlify/**/*.test.*'
-  ],
+  // Default: all unit tests; integration and netlify tests are excluded here and run via dedicated scripts
+  testMatch: ['**/tests/**/*.test.*'],
+  testPathIgnorePatterns: ['<rootDir>/tests/integration', '<rootDir>/netlify'],

Follow-up:

  • Ensure package.json:test:integration still explicitly targets tests/integration so those tests run when intended.
  • This aligns with the learning that coverage should target scripts and not other suites by default.
npm/runners/build-post-list-runner.ts (2)

11-15: Tighten types for postDirectories

postDirectories is a list of [fsPath, routePrefix] pairs. Use a tuple for each entry to capture intent and improve type safety.

-interface BuildPostListOptions {
-  postDirectories?: string[][];
+interface BuildPostListOptions {
+  postDirectories?: [string, string][];
   basePath?: string;
   outputPath?: string;
 }

41-49: Improve error context with resolved outputPath

When options.outputPath is undefined, the error detail shows “undefined”. Prefer the actual resolved outputPath for better diagnostics.

-    const customError = CustomError.fromError(error, {
+    const customError = CustomError.fromError(error, {
       category: 'script',
       operation: 'runBuildPostList',
-      detail: `Build post list failed with output path: ${options.outputPath}`
+      detail: `Build post list failed with output path: ${options.outputPath ?? outputPath}`
     });
tests/integration/build-post-list.int.test.ts (3)

20-22: Surface runner output for easier debugging

Forward stdio for the second execSync as well; otherwise failures don’t show logs.

-    execSync(`npx tsx npm/runners/build-post-list-runner.ts --outputFile ${outputFileName} --basePath "${tempDir}"`);
+    execSync(`npx tsx npm/runners/build-post-list-runner.ts --outputFile ${outputFileName} --basePath "${tempDir}"`, { stdio: 'inherit' });

Optional: consider execFileSync to avoid shell parsing and improve portability. Example:

// execFileSync('npx', ['tsx', 'npm/runners/build-post-list-runner.ts', '--outputFile', outputFileName, '--basePath', tempDir], { stdio: 'inherit' });

62-71: Make slug assertions resilient to trailing slash

Depending on upstream changes, slugs may include a trailing slash. Relax the expectation to keep the test stable but still strict.

-          slug: '/docs'
+          slug: expect.stringMatching(/^\/docs\/?$/)

72-81: Same for About slug: allow optional trailing slash

Mirror the change for the about section.

-          slug: '/about'
+          slug: expect.stringMatching(/^\/about\/?$/)
package.json (1)

11-11: Ensure coverage excludes integration tests

test:coverage currently runs Jest with default config, which (per current jest.config.js) may include integration tests. To align with the “coverage for scripts only” learning and the new unit/integration split, delegate coverage to the unit suite.

-    "test:coverage": "jest --coverage",
+    "test:coverage": "npm run test:unit -- --coverage",
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 8ddbe47 and ad65594.

📒 Files selected for processing (5)
  • jest.config.js (1 hunks)
  • npm/runners/build-pages-runner.ts (1 hunks)
  • npm/runners/build-post-list-runner.ts (1 hunks)
  • package.json (1 hunks)
  • tests/integration/build-post-list.int.test.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: akshatnema
PR: asyncapi/website#3101
File: tests/build-rss.test.js:25-27
Timestamp: 2024-11-01T09:55:20.531Z
Learning: In `tests/build-rss.test.js`, replacing `jest.resetModules()` with `jest.resetAllMocks()` in the `afterEach()` block causes errors. It is necessary to use `jest.resetModules()` to reset the module registry between tests in this file.
📚 Learning: 2024-11-10T18:16:22.273Z
Learnt from: vishvamsinh28
PR: asyncapi/website#3284
File: scripts/build-post-list.js:49-53
Timestamp: 2024-11-10T18:16:22.273Z
Learning: In `scripts/build-post-list.js`, the `walkDirectories` function depends on sequential execution because it mutates `resultObj`. Parallelizing the loop with `Promise.all` causes tests to fail.

Applied to files:

  • tests/integration/build-post-list.int.test.ts
  • npm/runners/build-post-list-runner.ts
📚 Learning: 2025-01-18T08:44:43.614Z
Learnt from: akshatnema
PR: asyncapi/website#3423
File: tests/index.test.js:2-7
Timestamp: 2025-01-18T08:44:43.614Z
Learning: In the AsyncAPI website project, JavaScript test files must include the .ts extension when importing TypeScript files (e.g., `require('../scripts/build-rss.ts')`). This is enforced by the project's configuration which uses `moduleResolution: "bundler"` in tsconfig.json and TypeScript-aware ESLint plugins. The .ts extensions are required even though the files are imported using CommonJS require statements.

Applied to files:

  • jest.config.js
📚 Learning: 2024-12-30T11:00:42.064Z
Learnt from: JeelRajodiya
PR: asyncapi/website#3423
File: jest.config.cjs:6-7
Timestamp: 2024-12-30T11:00:42.064Z
Learning: The user only wants coverage for scripts, not for .tsx files, because the existing tests are focused on scripts.

Applied to files:

  • jest.config.js
📚 Learning: 2025-01-18T08:44:43.614Z
Learnt from: akshatnema
PR: asyncapi/website#3423
File: tests/index.test.js:2-7
Timestamp: 2025-01-18T08:44:43.614Z
Learning: In the AsyncAPI website project, JavaScript test files must include the .ts extension when importing TypeScript files (e.g., `require('../scripts/build-rss.ts')`). This is a project-specific requirement enforced by the linting rules and build setup, even though it differs from typical Node.js behavior.

Applied to files:

  • jest.config.js
📚 Learning: 2024-11-01T09:35:23.912Z
Learnt from: akshatnema
PR: asyncapi/website#3101
File: scripts/build-rss.js:4-6
Timestamp: 2024-11-01T09:35:23.912Z
Learning: Converting `getAllPosts()` to asynchronous in `scripts/build-rss.js` causes the existing build system to fail.

Applied to files:

  • npm/runners/build-post-list-runner.ts
📚 Learning: 2025-06-19T13:51:27.459Z
Learnt from: sagarkori143
PR: asyncapi/website#4192
File: npm/runners/build-pages-runner.ts:7-14
Timestamp: 2025-06-19T13:51:27.459Z
Learning: In the AsyncAPI website build system, individual runner functions use try-catch blocks that rethrow errors to maintain consistent error boundaries, while the top-level orchestrator in npm/index.ts provides meaningful error logging with task-specific context using logger.error(`Error building ${taskName}:`, error). This separation of concerns allows for clean error handling at different architectural layers.

Applied to files:

  • npm/runners/build-post-list-runner.ts
🔇 Additional comments (4)
npm/runners/build-post-list-runner.ts (1)

28-51: Good separation of concerns and error boundary

runBuildPostList wraps script invocation, adds contextual CustomError, logs, and rethrows—consistent with the project’s runner pattern noted in past learnings. Once the CLI issues are addressed, the structure looks solid.

tests/integration/build-post-list.int.test.ts (1)

102-112: Nice end-to-end checks on slug prefixes

Verifying section-specific path prefixes is a good, low-cost invariants check that will catch routing regressions.

npm/runners/build-pages-runner.ts (1)

25-45: Runner structure and error propagation look good

Consistent with the project’s error-handling practice: log contextual CustomError and rethrow for the top-level to exit with a non-zero code.

package.json (1)

10-15: Scripts split looks good

Sequential unit then integration runs make the intent explicit, and the dedicated runner test entry is helpful for local debugging.

Comment on lines 47 to 54
(async () => {
try {
await runBuildPages();
} catch (error) {
// Ensure we exit with error code
process.exit(1);
}
})();
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid auto-executing on import; add a “run when main” guard

Self-invoking at module load introduces hard-to-debug side effects if this file is ever imported. Prefer a main guard so imports remain pure and the CLI still works.

-(async () => {
-  try {
-    await runBuildPages();
-  } catch (error) {
-    // Ensure we exit with error code
-    process.exit(1);
-  }
-})();
+if (fileURLToPath(import.meta.url) === process.argv[1]) {
+  (async () => {
+    try {
+      await runBuildPages();
+    } catch (error) {
+      // Ensure we exit with error code
+      process.exit(1);
+    }
+  })();
+}

Add this import at the top of the file:

import { fileURLToPath } from 'url';

Optional: If other code needs to call this programmatically, consider exporting the function:

export async function runBuildPages()
🤖 Prompt for AI Agents
In npm/runners/build-pages-runner.ts around lines 47 to 54, the module currently
self-invokes an async IIFE at import time which causes side effects; replace the
IIFE with a "run when main" guard so the module only auto-runs when executed
directly: export the runBuildPages function (if not already exported) and add a
top-file import of fileURLToPath from 'url'; then wrap the invocation in a
conditional that checks the module is the entry script (using
fileURLToPath(import.meta.url) compared to process.argv[1] or an equivalent
main-check) and call runBuildPages() inside that block so importing the file is
side-effect free.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (1)
npm/runners/build-post-list-runner.ts (1)

28-39: Default postDirectories should derive from the resolved basePath

When a custom basePath is supplied, defaults for postDirectories should be computed relative to that basePath, not to currentDirPath. Otherwise, a caller cannot relocate the scan root without also passing custom postDirectories.

Proposed change outside the diff range (adjust inside runBuildPostList):

const basePath = options.basePath || resolve(currentDirPath, '../../pages');
const postDirectories = options.postDirectories || [
  [resolve(basePath, 'blog'), '/blog'],
  [resolve(basePath, 'docs'), '/docs'],
  [resolve(basePath, 'about'), '/about']
];
♻️ Duplicate comments (2)
npm/runners/build-pages-runner.ts (1)

47-54: Avoid auto-executing on import; guard with “run when main”

Self-invoking at module load causes side effects when this module is imported (including by tests). Add a main guard so imports remain pure, and the CLI still works.

Apply this diff:

-(async () => {
-  try {
-    await runBuildPages();
-  } catch (error) {
-    // Ensure we exit with error code
-    process.exit(1);
-  }
-})();
+if (fileURLToPath(import.meta.url) === process.argv[1]) {
+  (async () => {
+    try {
+      await runBuildPages();
+    } catch (error) {
+      // Ensure we exit with error code
+      logger.error('Build pages CLI failed', error);
+      process.exit(1);
+    }
+  })();
+}

Add this import near the top:

import { fileURLToPath } from 'url';
tests/integration/build-post-list.int.test.ts (1)

1-6: Increase Jest timeout for the integration flow

Two tsx invocations commonly exceed the default 5s timeout on CI. Set a higher timeout for stability.

 import { execSync } from 'child_process';
 import fs from 'fs';
 import os from 'os';
 import path from 'path';
 
+// Integration builds can take longer on CI
+jest.setTimeout(60_000);
🧹 Nitpick comments (6)
npm/runners/build-post-list-runner.ts (1)

73-77: Exit-on-error swallows pre-run parsing failures; log before exit

Errors thrown before runBuildPostList (e.g., bad CLI args) are not logged. Log the error to aid debugging.

   } catch (error) {
-    // Ensure we exit with error code
+    // Ensure we exit with error code and visible diagnostics
+    logger.error('Build post list CLI failed', error);
     process.exit(1);
   }
npm/runners/build-pages-runner.ts (1)

25-45: runBuildPages Is Only Used Internally, Exporting Is Non-Breaking but Recommended

Verification shows that runBuildPages is only invoked within its own module (lines 49–50) and has no external imports or references across the codebase—so exporting it will not break existing usages.

• No occurrences of runBuildPages( outside npm/runners/build-pages-runner.ts were found.
• Exporting the function and wiring up CLI flags remains an optional refactor to improve testability.

Suggested changes:

--- a/npm/runners/build-pages-runner.ts
+++ b/npm/runners/build-pages-runner.ts
@@
-export async function runBuildPages(options: BuildPagesOptions = {}): Promise<void> {
+export async function runBuildPages(options: BuildPagesOptions = {}): Promise<void> {
   const config = { ...DEFAULT_OPTIONS, ...options };
   try {
     ensureDirectoryExists(config.targetDir);
@@
-}
+
+}
+
+// --- CLI entrypoint ---
+if (require.main === module) {
+  // Lightweight CLI parsing (you can swap for yargs/commander)
+  const argv = require('minimist')(process.argv.slice(2), {
+    string: ['sourceDir', 'targetDir'],
+    default: { sourceDir: DEFAULT_OPTIONS.sourceDir, targetDir: DEFAULT_OPTIONS.targetDir },
+  });
+
+  runBuildPages({ sourceDir: argv.sourceDir, targetDir: argv.targetDir })
+    .catch(err => {
+      process.exitCode = 1;
+    });
+}

By exporting runBuildPages and exposing --sourceDir/--targetDir, integration tests can import the function directly and pass temporary directories without touching real folders.

tests/integration/build-post-list.int.test.ts (2)

17-22: Use npm scripts or parameterizable runners to avoid hardcoding tsx calls

Direct npx tsx calls work, but:

  • They bypass any project-level wrappers (env, logging).
  • Quoting is brittle across shells.
  • With the current runner, pages are always written to the real pages/ dir, harming isolation.

Either:

  • Add minimal CLI flags to build-pages-runner (e.g., --targetDir "${tempDir}") and use those here, or
  • Expose runBuildPages and invoke it programmatically with a temp target.

Also, mirror stdio on the second exec for consistent diagnostics.

-    // Run the runner as a CLI command with the test output file name and basePath
-    execSync(`npx tsx npm/runners/build-post-list-runner.ts --outputFile ${outputFileName} --basePath "${tempDir}"`);
+    // Run the runner as a CLI command with the test output file name and basePath
+    execSync(
+      `npx tsx npm/runners/build-post-list-runner.ts --outputFile ${outputFileName} --basePath "${tempDir}"`,
+      { stdio: 'inherit' }
+    );

Replying to “Can’t we directly run npm scripts?”: Running npm run build:pages also formats MDX (format:mdx) and may alter repo files. For tests, a CLI that only performs the minimal action (or a programmatic call) is safer and faster. If preferred, add a dedicated build:pages:ci script that runs only the runner and consume that here.


62-71: Assertions assume data from the real pages dir; will break once basePath is honored

The test expects Welcome at /docs and About at /about regardless of the basePath content. After fixing the runner to actually use --basePath for scanning, ensure the temp dir contains the expected markdown/pages fixtures (or assert schema/shape rather than exact entries).

package.json (2)

10-15: Ensure coverage excludes integration tests consistently

npm run test:coverage uses jest.config, which currently still matches integration tests. Either adjust jest.config (preferred; see comment there) or add ignore flags here too to avoid accidentally running integration tests during coverage.

Option A — rely on config (after adding testPathIgnorePatterns in jest.config): no change needed here.

Option B — enforce via script:

-    "test:coverage": "jest --coverage",
+    "test:coverage": "jest --coverage --testPathIgnorePatterns=\"tests/integration|netlify\"",

12-14: Redundant testMatch override in test:unit; safe but can drift from jest.config

Overriding --testMatch and --testPathIgnorePatterns inline is okay but duplicates config. Prefer a single source of truth in jest.config to prevent future drift.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 8ddbe47 and ad65594.

📒 Files selected for processing (5)
  • jest.config.js (1 hunks)
  • npm/runners/build-pages-runner.ts (1 hunks)
  • npm/runners/build-post-list-runner.ts (1 hunks)
  • package.json (1 hunks)
  • tests/integration/build-post-list.int.test.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: akshatnema
PR: asyncapi/website#3101
File: tests/build-rss.test.js:25-27
Timestamp: 2024-11-01T09:55:20.531Z
Learning: In `tests/build-rss.test.js`, replacing `jest.resetModules()` with `jest.resetAllMocks()` in the `afterEach()` block causes errors. It is necessary to use `jest.resetModules()` to reset the module registry between tests in this file.
📚 Learning: 2025-01-18T08:44:43.614Z
Learnt from: akshatnema
PR: asyncapi/website#3423
File: tests/index.test.js:2-7
Timestamp: 2025-01-18T08:44:43.614Z
Learning: In the AsyncAPI website project, JavaScript test files must include the .ts extension when importing TypeScript files (e.g., `require('../scripts/build-rss.ts')`). This is enforced by the project's configuration which uses `moduleResolution: "bundler"` in tsconfig.json and TypeScript-aware ESLint plugins. The .ts extensions are required even though the files are imported using CommonJS require statements.

Applied to files:

  • jest.config.js
📚 Learning: 2024-12-30T11:00:42.064Z
Learnt from: JeelRajodiya
PR: asyncapi/website#3423
File: jest.config.cjs:6-7
Timestamp: 2024-12-30T11:00:42.064Z
Learning: The user only wants coverage for scripts, not for .tsx files, because the existing tests are focused on scripts.

Applied to files:

  • jest.config.js
📚 Learning: 2025-01-18T08:44:43.614Z
Learnt from: akshatnema
PR: asyncapi/website#3423
File: tests/index.test.js:2-7
Timestamp: 2025-01-18T08:44:43.614Z
Learning: In the AsyncAPI website project, JavaScript test files must include the .ts extension when importing TypeScript files (e.g., `require('../scripts/build-rss.ts')`). This is a project-specific requirement enforced by the linting rules and build setup, even though it differs from typical Node.js behavior.

Applied to files:

  • jest.config.js
📚 Learning: 2024-11-01T09:35:23.912Z
Learnt from: akshatnema
PR: asyncapi/website#3101
File: scripts/build-rss.js:4-6
Timestamp: 2024-11-01T09:35:23.912Z
Learning: Converting `getAllPosts()` to asynchronous in `scripts/build-rss.js` causes the existing build system to fail.

Applied to files:

  • npm/runners/build-post-list-runner.ts
📚 Learning: 2024-11-10T18:16:22.273Z
Learnt from: vishvamsinh28
PR: asyncapi/website#3284
File: scripts/build-post-list.js:49-53
Timestamp: 2024-11-10T18:16:22.273Z
Learning: In `scripts/build-post-list.js`, the `walkDirectories` function depends on sequential execution because it mutates `resultObj`. Parallelizing the loop with `Promise.all` causes tests to fail.

Applied to files:

  • npm/runners/build-post-list-runner.ts
  • tests/integration/build-post-list.int.test.ts
📚 Learning: 2025-06-19T13:51:27.459Z
Learnt from: sagarkori143
PR: asyncapi/website#4192
File: npm/runners/build-pages-runner.ts:7-14
Timestamp: 2025-06-19T13:51:27.459Z
Learning: In the AsyncAPI website build system, individual runner functions use try-catch blocks that rethrow errors to maintain consistent error boundaries, while the top-level orchestrator in npm/index.ts provides meaningful error logging with task-specific context using logger.error(`Error building ${taskName}:`, error). This separation of concerns allows for clean error handling at different architectural layers.

Applied to files:

  • npm/runners/build-post-list-runner.ts
🔇 Additional comments (2)
package.json (2)

10-15: Script flow LGTM: unit then integration

Running unit first and integration next keeps feedback quick and isolates failures. Nice.


8-43: ✅ e2e script removal verified safe

No references to the removed test:e2e script were found in CI workflows, documentation, or dev tooling after searching:

  • CI configs (.github/**/*.yml) contain no test:e2e or “e2e” job definitions
  • Documentation files (*.md, *.yml) make no calls to npm run test:e2e
  • No tooling or scripts invoke Cypress via an e2e script

Removal is intentional and safe to merge.

@akshatnema
Copy link
Member

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 14, 2025

✅ Actions performed

Full review triggered.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

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

⚠️ Outside diff range comments (1)
config/all-tags.json (1)

94-325: Remove duplicate entries in the technologies array to maintain data integrity.

Verification confirms 4 technologies have duplicate entries that should be deduplicated:

  • "AsyncAPI Generator" (2 occurrences)
  • "HTML" (2 occurrences)
  • "SmartPaste" (2 occurrences)
  • "VSCode" (2 occurrences)

These duplicates create unnecessary bloat, complicate lookups, and should be consolidated.

♻️ Duplicate comments (1)
jest.config.js (1)

16-20: Comment and behavior diverge: integration tests are still matched by Jest config

The comment says "except integration," but testMatch still includes tests/integration. Without testPathIgnorePatterns, integration tests will run in commands that rely solely on jest.config (e.g., npm run test:coverage).

Apply this diff to align config with intent:

   // Default: all tests except integration
   testMatch: [
     '**/tests/**/*.test.*',
     '!**/netlify/**/*.test.*'
   ],
+  testPathIgnorePatterns: [
+    '<rootDir>/tests/integration/',
+    '<rootDir>/netlify/'
+  ],
🧹 Nitpick comments (15)
config/meetings.json (1)

17-17: Remove trailing whitespace from title.

Line 17 has a trailing space in the title: "AsyncAPI Design WG Meeting ". This should be trimmed for data consistency.

-    "title": "AsyncAPI Design WG Meeting ",
+    "title": "AsyncAPI Design WG Meeting",
tests/check-locales.test.ts (1)

509-557: Consider using specific numeric assertions for better test clarity.

The test correctly verifies the presence of the validationSummary object structure. However, using expect.any(Number) for totalFiles and filesWithIssues makes the test less precise. Based on your mock setup, you can predict the exact values:

  • totalFiles should be 2 (common.json and file2.json)
  • filesWithIssues should be 1 (only common.json has missing keys)

More specific assertions would make test failures easier to diagnose and serve as better documentation of expected behavior.

Example refactor:

       validationSummary: expect.objectContaining({
-        totalFiles: expect.any(Number),
+        totalFiles: 2,
         totalLanguages: 2,
-        filesWithIssues: expect.any(Number)
+        filesWithIssues: 1
       }),
tests/markdown/check-edit-links.test.ts (2)

209-216: Test doesn't verify AbortController signal propagation.

The test aborts the controller and mocks fetch to reject, but it doesn't verify that the signal is actually passed to the fetch call or that the abort is properly integrated. Consider enhancing this test to verify the signal is passed to fetch:

 it('should handle AbortController signal', async () => {
   const controller = new AbortController();
+  let receivedSignal = null;

   controller.abort();
-  mockFetch.mockImplementation(() => Promise.reject(new Error('Aborted')));
+  mockFetch.mockImplementation((url, options) => {
+    receivedSignal = options?.signal;
+    return Promise.reject(new Error('Aborted'));
+  });

   await expect(processBatch(testBatch)).rejects.toThrow();
+  expect(receivedSignal).toBe(controller.signal);
 });

284-306: Consider using afterEach for environment variable cleanup.

The test properly saves and restores the environment variable, but the cleanup happens at the end of the test. If an assertion fails before the cleanup code, the environment variable won't be restored. Consider using afterEach for more robust cleanup:

+describe('checkUrls with environment variable', () => {
+  let originalEnv: string | undefined;
+
+  beforeEach(() => {
+    originalEnv = process.env.DOCS_LINK_CHECK_BATCH_SIZE;
+  });
+
+  afterEach(() => {
+    if (originalEnv) {
+      process.env.DOCS_LINK_CHECK_BATCH_SIZE = originalEnv;
+    } else {
+      delete process.env.DOCS_LINK_CHECK_BATCH_SIZE;
+    }
+  });
+
   it('should use DOCS_LINK_CHECK_BATCH_SIZE environment variable', async () => {
-    const originalEnv = process.env.DOCS_LINK_CHECK_BATCH_SIZE;
-
     process.env.DOCS_LINK_CHECK_BATCH_SIZE = '2';
     mockFetch.mockImplementation(() => Promise.resolve({ status: 200 }));

     const largePathsArray = Array.from({ length: 10 }, (_, i) => ({
       filePath: `test${i}.md`,
       urlPath: `test${i}`,
       editLink: `https://example.com/test${i}`
     }));

     await checkUrls(largePathsArray);

     // Should create 5 batches (10 items / 2 per batch)
     expect(logger.info).toHaveBeenCalledWith('Processing 5 batches concurrently...');
-
-    if (originalEnv) {
-      process.env.DOCS_LINK_CHECK_BATCH_SIZE = originalEnv;
-    } else {
-      delete process.env.DOCS_LINK_CHECK_BATCH_SIZE;
-    }
   });
+});
tests/integration/case-studies-runner.int.test.ts (1)

264-285: Consider simplifying the error handling test pattern.

The current try-catch pattern is functional but convoluted. Consider using a more direct approach:

-    it('wraps errors in CustomError with proper context', async () => {
-      const nonExistentDir = resolve(tempDir, 'non-existent-dir');
-
-      try {
-        await runCaseStudies({
-          caseStudyDirectory: nonExistentDir,
-          outputPath
-        });
-        throw new Error('Expected error to be thrown');
-      } catch (error) {
-        if (error instanceof Error && error.message === 'Expected error to be thrown') {
-          throw error;
-        }
-        expect(error).toBeInstanceOf(CustomError);
-        const customError = error as CustomError;
-
-        expect(customError.context.category).toBe('script');
-        expect(customError.context.operation).toBe('runCaseStudies');
-        expect(customError.context.detail).toBeDefined();
-        expect(customError.context.detail).toContain('Case studies build failed');
-      }
-    });
+    it('wraps errors in CustomError with proper context', async () => {
+      const nonExistentDir = resolve(tempDir, 'non-existent-dir');
+
+      await expect(
+        runCaseStudies({
+          caseStudyDirectory: nonExistentDir,
+          outputPath
+        })
+      ).rejects.toThrow(CustomError);
+
+      // Verify context in a separate call
+      try {
+        await runCaseStudies({
+          caseStudyDirectory: nonExistentDir,
+          outputPath
+        });
+      } catch (error) {
+        const customError = error as CustomError;
+        expect(customError.context.category).toBe('script');
+        expect(customError.context.operation).toBe('runCaseStudies');
+        expect(customError.context.detail).toBeDefined();
+        expect(customError.context.detail).toContain('Case studies build failed');
+      }
+    });
tests/integration/helpers/build-pages-lock.ts (2)

42-109: Consider simplifying the nested polling logic

The waitForPagesBuild function has deeply nested loops (4 levels) with multiple await-in-loop patterns. While the linting suppressions acknowledge this, the complexity could be reduced.

Consider extracting helper functions:

async function checkPagesDirectory(): Promise<boolean> {
  try {
    const pagesDir = resolve(process.cwd(), 'pages');
    const stats = await fs.stat(pagesDir);
    
    if (!stats.isDirectory()) return false;
    
    const topLevelFiles = await fs.readdir(pagesDir);
    return await hasBuiltSubdirectories(pagesDir, topLevelFiles);
  } catch {
    return false;
  }
}

async function hasBuiltSubdirectories(pagesDir: string, topLevelFiles: string[]): Promise<boolean> {
  const requiredDirs = ['blog', 'docs', 'about'];
  const existingDirs = topLevelFiles.filter(f => requiredDirs.includes(f));
  
  for (const subdir of existingDirs) {
    if (await hasConvertedFiles(resolve(pagesDir, subdir))) {
      return true;
    }
  }
  return false;
}

async function hasConvertedFiles(subdirPath: string): Promise<boolean> {
  try {
    const stats = await fs.stat(subdirPath);
    if (!stats.isDirectory()) return false;
    
    const files = await fs.readdir(subdirPath);
    return files.some(file => file.endsWith('.mdx'));
  } catch {
    return false;
  }
}

Then simplify the main loop:

export async function waitForPagesBuild(maxWaitMs = 60000): Promise<boolean> {
  const startTime = Date.now();
  const checkInterval = 1000;

  while (Date.now() - startTime < maxWaitMs) {
    if (await checkPagesDirectory()) {
      return true;
    }
    
    // Wait before next check
    await new Promise(res => setTimeout(res, checkInterval));
  }

  return false;
}

29-35: Broad error suppression may mask real issues

All error handling uses empty catch blocks, which silently suppresses all errors including unexpected ones. While this is acceptable for ENOENT (file not found), other errors like EACCES (permission denied) might indicate real problems.

Consider logging unexpected errors or at least filtering by error code:

} catch (error) {
  // Expected: lock doesn't exist yet
  if (error.code !== 'ENOENT') {
    console.warn('Unexpected error checking lock:', error);
  }
}

Also applies to: 80-82, 86-88, 99-104

npm/runners/build-post-list-runner.ts (1)

58-74: Use parseArgs for more robust CLI argument parsing

The manual argument parsing using indexOf is brittle and doesn't handle edge cases like missing values, duplicate flags, or malformed input.

Apply this diff:

+    import { parseArgs } from 'node:util';
+
     try {
-      // Extract the file name and basePath from the CLI command
-      const outputFileArgIndex = process.argv.indexOf('--outputFile');
-      const outputFileName = outputFileArgIndex === -1 ? 'posts.json' : process.argv[outputFileArgIndex + 1];
-
-      const basePathArgIndex = process.argv.indexOf('--basePath');
-      const basePath = basePathArgIndex === -1 ? undefined : process.argv[basePathArgIndex + 1];
-
-      // Build outputPath using resolve(basePath, outputFileName)
-      let outputPath;
-
-      if (basePath) {
-        outputPath = resolve(basePath, outputFileName);
-      } else {
-        outputPath = resolve(currentDirPath, '../../config', outputFileName);
-      }
+      const { values } = parseArgs({
+        options: {
+          outputFile: { type: 'string' },
+          basePath: { type: 'string' }
+        }
+      });
+      
+      const outputFileName = values.outputFile || 'posts.json';
+      const basePath = values.basePath;
+      
+      const outputPath = basePath
+        ? resolve(basePath, outputFileName)
+        : resolve(currentDirPath, '../../config', outputFileName);

Add the import at the top:

import { parseArgs } from 'node:util';
scripts/adopters/index.ts (1)

15-51: Error handling is solid; consider tightening context typing.

The validation and contextual wrapping around writeJSON look good and provide useful metadata (operation, stage, sourcePath, targetPath, truncated stack). The repeated (error as any).context casts, though, lose type safety. Consider introducing a small ContextualError type or helper (e.g., withContext(error, context)) so callers can rely on a typed context field without any casts.

tests/integration/build-adopters-list-runner.int.test.ts (1)

143-165: Data-quality assertions are strong but may be brittle to future content changes.

Enforcing uniqueness of (companyName|useCase) combinations and resource links at the integration-test level will cause test failures whenever content editors intentionally introduce duplicates (e.g., same use case across teams or shared links). If those invariants are business-critical, this is fine; otherwise, consider softening these checks or moving them to a separate “data lint” suite so normal content updates don’t unnecessarily break CI.

tests/integration/build-tools.int.test.ts (1)

29-41: Preserve and restore original GITHUB_TOKEN instead of unconditionally overwriting/deleting.

The suite sets process.env.GITHUB_TOKEN = 'test-token' in beforeAll and deletes it in afterAll, which can clobber any real token present when tests start. Capture the original value and restore it, deleting only if it was initially undefined, e.g.:

   let tempDir: string;
   let automatedToolsPath: string;
   let manualToolsPath: string;
   let toolsPath: string;
   let tagsPath: string;
+  let originalGitHubToken: string | undefined;

   beforeAll(async () => {
-    // Mock the GITHUB_TOKEN environment variable
-    process.env.GITHUB_TOKEN = 'test-token';
+    // Mock the GITHUB_TOKEN environment variable, preserving original
+    originalGitHubToken = process.env.GITHUB_TOKEN;
+    process.env.GITHUB_TOKEN = 'test-token';
@@
   afterAll(async () => {
@@
-    // Clean up environment variable
-    delete process.env.GITHUB_TOKEN;
+    // Restore original environment variable
+    if (originalGitHubToken === undefined) {
+      delete process.env.GITHUB_TOKEN;
+    } else {
+      process.env.GITHUB_TOKEN = originalGitHubToken;
+    }

This keeps the tests isolated from the caller’s environment.

Also applies to: 66-75

tests/integration/build-newsroom-videos-runner.int.test.ts (1)

15-24: Make YOUTUBE_TOKEN restoration robust when no original token exists.

You correctly snapshot originalEnv.YOUTUBE_TOKEN before overriding, but afterAll only restores it if the original value is truthy. If there was no token initially, the suite leaves YOUTUBE_TOKEN = 'test-token' set after tests. Consider:

   afterAll(() => {
-    // Restore original environment variables
-    if (originalEnv.YOUTUBE_TOKEN) {
-      process.env.YOUTUBE_TOKEN = originalEnv.YOUTUBE_TOKEN;
-    }
+    // Restore original environment variables
+    if (typeof originalEnv.YOUTUBE_TOKEN === 'undefined') {
+      delete process.env.YOUTUBE_TOKEN;
+    } else {
+      process.env.YOUTUBE_TOKEN = originalEnv.YOUTUBE_TOKEN;
+    }
   });

This restores the environment to its exact pre-test state.

Also applies to: 35-40

tests/integration/build-meetings-runner.int.test.ts (1)

195-201: Avoid invoking the function to verify it's async.

Calling runBuildMeetings() without arguments on line 199 actually executes the function, which may trigger side effects (environment variable checks, file operations, API calls) in an uncontrolled test context. Instead, verify the function signature and async nature through type checking or by calling it with proper arguments and asserting it returns a Promise.

Consider this safer approach:

   describe('Export and Type Safety', () => {
     it('should export the runBuildMeetings function', () => {
       expect(typeof runBuildMeetings).toBe('function');
-      // Verify it's a Promise-returning function
-      expect(runBuildMeetings()).toBeInstanceOf(Promise);
+      // Verify it returns a Promise when called with valid options
+      const result = runBuildMeetings({ outputPath });
+      expect(result).toBeInstanceOf(Promise);
+      // Clean up - await the promise to prevent unhandled rejection
+      return result;
     });
   });
tests/integration/build-post-list.int.test.ts (1)

16-58: Consider refactoring for improved readability.

The isPagesValid function has deep nesting (4 levels) with try-catch blocks inside loops, requiring multiple eslint-disable comments. While functionally correct, extracting the inner logic would improve readability.

Consider this refactor:

async function isPagesValid(): Promise<boolean> {
  try {
    const pagesDir = resolve(process.cwd(), 'pages');
    const stats = await fs.stat(pagesDir);
    
    if (!stats.isDirectory()) {
      return false;
    }
    
    const files = await fs.readdir(pagesDir);
    const hasExpectedDirs = ['docs', 'blog', 'about'].some(dir => files.includes(dir));
    
    if (!hasExpectedDirs) {
      return false;
    }
    
    return await hasAnyMdxFiles(pagesDir, ['blog', 'docs', 'about']);
  } catch {
    return false;
  }
}

async function hasAnyMdxFiles(baseDir: string, subdirs: string[]): Promise<boolean> {
  for (const subdir of subdirs) {
    try {
      const subdirPath = resolve(baseDir, subdir);
      const subdirStats = await fs.stat(subdirPath);
      
      if (subdirStats.isDirectory()) {
        const subdirFiles = await fs.readdir(subdirPath);
        if (subdirFiles.some(file => file.endsWith('.mdx'))) {
          return true;
        }
      }
    } catch {
      // Subdirectory doesn't exist, continue
    }
  }
  return false;
}
tests/integration/build-pages-runner.int.test.ts (1)

402-408: Avoid invoking the function to verify it's async.

Calling runBuildPages() without arguments on line 406 actually executes the function, which may trigger file operations and transformations in an uncontrolled test context. This is the same pattern flagged in the build-meetings-runner test.

Use a safer approach:

   describe('Function Export', () => {
     it('should export the runner function', () => {
       expect(typeof runBuildPages).toBe('function');
-      // Verify it's a Promise-returning function
-      expect(runBuildPages()).toBeInstanceOf(Promise);
+      // Verify it returns a Promise when called with valid options
+      const result = runBuildPages({ sourceDir, targetDir });
+      expect(result).toBeInstanceOf(Promise);
+      // Await to prevent unhandled rejection
+      return result;
     });
   });
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8ddbe47 and 534af85.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (36)
  • config/all-tags.json (2 hunks)
  • config/meetings.json (1 hunks)
  • config/newsroom_videos.json (1 hunks)
  • jest.config.js (1 hunks)
  • npm/runners/build-adopters-list-runner.ts (2 hunks)
  • npm/runners/build-dashboard-runner.ts (3 hunks)
  • npm/runners/build-meetings-runner.ts (2 hunks)
  • npm/runners/build-newsroom-videos-runner.ts (2 hunks)
  • npm/runners/build-pages-runner.ts (2 hunks)
  • npm/runners/build-post-list-runner.ts (3 hunks)
  • npm/runners/build-tools-runner.ts (1 hunks)
  • npm/runners/case-studies-runner.ts (1 hunks)
  • package.json (2 hunks)
  • scripts/adopters/index.ts (1 hunks)
  • scripts/index.ts (1 hunks)
  • tests/adopters/index.test.ts (1 hunks)
  • tests/build-meetings.test.ts (2 hunks)
  • tests/build-rss.test.ts (4 hunks)
  • tests/check-locales.test.ts (1 hunks)
  • tests/index.test.ts (1 hunks)
  • tests/integration/build-adopters-list-runner.int.test.ts (1 hunks)
  • tests/integration/build-dashboard.int.test.ts (1 hunks)
  • tests/integration/build-finance-info-list-runner.int.test.ts (1 hunks)
  • tests/integration/build-meetings-runner.int.test.ts (1 hunks)
  • tests/integration/build-newsroom-videos-runner.int.test.ts (1 hunks)
  • tests/integration/build-pages-runner.int.test.ts (1 hunks)
  • tests/integration/build-post-list.int.test.ts (1 hunks)
  • tests/integration/build-tools.int.test.ts (1 hunks)
  • tests/integration/case-studies-runner.int.test.ts (1 hunks)
  • tests/integration/compose-blog-runner.int.test.ts (1 hunks)
  • tests/integration/fixtures/dashboard-fixtures.ts (1 hunks)
  • tests/integration/fixtures/nock-helpers.ts (1 hunks)
  • tests/integration/fixtures/tools-fixtures.ts (1 hunks)
  • tests/integration/helpers/build-pages-lock.ts (1 hunks)
  • tests/integration/helpers/file-utils.ts (1 hunks)
  • tests/markdown/check-edit-links.test.ts (3 hunks)
🧰 Additional context used
🧠 Learnings (27)
📚 Learning: 2024-11-01T09:55:20.531Z
Learnt from: akshatnema
Repo: asyncapi/website PR: 3101
File: tests/build-rss.test.js:25-27
Timestamp: 2024-11-01T09:55:20.531Z
Learning: In `tests/build-rss.test.js`, replacing `jest.resetModules()` with `jest.resetAllMocks()` in the `afterEach()` block causes errors. It is necessary to use `jest.resetModules()` to reset the module registry between tests in this file.

Applied to files:

  • jest.config.js
  • tests/build-rss.test.ts
  • tests/integration/build-meetings-runner.int.test.ts
  • tests/markdown/check-edit-links.test.ts
  • tests/adopters/index.test.ts
  • tests/integration/build-dashboard.int.test.ts
  • tests/integration/build-tools.int.test.ts
  • tests/build-meetings.test.ts
  • tests/integration/build-pages-runner.int.test.ts
  • tests/integration/build-newsroom-videos-runner.int.test.ts
📚 Learning: 2025-01-03T08:14:02.138Z
Learnt from: JeelRajodiya
Repo: asyncapi/website PR: 3423
File: tests/index.test.js:2-7
Timestamp: 2025-01-03T08:14:02.138Z
Learning: The user (JeelRajodiya) has stated a preference to keep the test files in CommonJS rather than migrating them to TypeScript.

Applied to files:

  • jest.config.js
📚 Learning: 2024-12-30T11:00:42.064Z
Learnt from: JeelRajodiya
Repo: asyncapi/website PR: 3423
File: jest.config.cjs:6-7
Timestamp: 2024-12-30T11:00:42.064Z
Learning: The user only wants coverage for scripts, not for .tsx files, because the existing tests are focused on scripts.

Applied to files:

  • jest.config.js
  • tests/integration/build-post-list.int.test.ts
  • package.json
📚 Learning: 2025-01-18T08:44:43.614Z
Learnt from: akshatnema
Repo: asyncapi/website PR: 3423
File: tests/index.test.js:2-7
Timestamp: 2025-01-18T08:44:43.614Z
Learning: In the AsyncAPI website project, JavaScript test files must include the .ts extension when importing TypeScript files (e.g., `require('../scripts/build-rss.ts')`). This is enforced by the project's configuration which uses `moduleResolution: "bundler"` in tsconfig.json and TypeScript-aware ESLint plugins. The .ts extensions are required even though the files are imported using CommonJS require statements.

Applied to files:

  • jest.config.js
  • tests/build-rss.test.ts
  • npm/runners/build-pages-runner.ts
  • tests/integration/case-studies-runner.int.test.ts
  • tests/adopters/index.test.ts
  • tests/integration/compose-blog-runner.int.test.ts
  • tests/build-meetings.test.ts
  • tests/integration/helpers/build-pages-lock.ts
  • tests/integration/helpers/file-utils.ts
  • tests/integration/build-adopters-list-runner.int.test.ts
  • tests/integration/build-pages-runner.int.test.ts
  • tests/integration/build-newsroom-videos-runner.int.test.ts
  • package.json
📚 Learning: 2025-01-18T08:44:43.614Z
Learnt from: akshatnema
Repo: asyncapi/website PR: 3423
File: tests/index.test.js:2-7
Timestamp: 2025-01-18T08:44:43.614Z
Learning: In the AsyncAPI website project, JavaScript test files must include the .ts extension when importing TypeScript files (e.g., `require('../scripts/build-rss.ts')`). This is a project-specific requirement enforced by the linting rules and build setup, even though it differs from typical Node.js behavior.

Applied to files:

  • jest.config.js
  • npm/runners/build-pages-runner.ts
  • tests/integration/case-studies-runner.int.test.ts
  • tests/adopters/index.test.ts
  • tests/build-meetings.test.ts
  • tests/integration/helpers/build-pages-lock.ts
  • tests/integration/build-adopters-list-runner.int.test.ts
  • tests/integration/build-pages-runner.int.test.ts
  • tests/integration/build-newsroom-videos-runner.int.test.ts
📚 Learning: 2025-01-18T08:44:43.614Z
Learnt from: akshatnema
Repo: asyncapi/website PR: 3423
File: tests/index.test.js:2-7
Timestamp: 2025-01-18T08:44:43.614Z
Learning: In JavaScript test files within the AsyncAPI website project, TypeScript file imports must include the .ts extension to avoid lint errors, even though the files being imported are JavaScript files.

Applied to files:

  • jest.config.js
📚 Learning: 2024-11-01T13:32:15.472Z
Learnt from: akshatnema
Repo: asyncapi/website PR: 3101
File: tests/fixtures/rssData.js:1-57
Timestamp: 2024-11-01T13:32:15.472Z
Learning: In the `tests/fixtures/rssData.js` file of the `asyncapi/website` project, tests for edge cases such as empty strings for title or excerpt, very long text content, international characters (UTF-8), or malformed URLs in `slug` or `cover` are not necessary because these cases will not occur.

Applied to files:

  • tests/build-rss.test.ts
  • tests/markdown/check-edit-links.test.ts
  • tests/integration/case-studies-runner.int.test.ts
  • tests/integration/build-dashboard.int.test.ts
  • tests/integration/fixtures/tools-fixtures.ts
  • tests/integration/build-tools.int.test.ts
  • tests/integration/compose-blog-runner.int.test.ts
  • tests/integration/build-finance-info-list-runner.int.test.ts
  • tests/integration/build-adopters-list-runner.int.test.ts
  • tests/integration/build-post-list.int.test.ts
  • tests/integration/build-pages-runner.int.test.ts
  • tests/integration/build-newsroom-videos-runner.int.test.ts
  • tests/integration/fixtures/dashboard-fixtures.ts
📚 Learning: 2024-11-01T09:35:23.912Z
Learnt from: akshatnema
Repo: asyncapi/website PR: 3101
File: scripts/build-rss.js:4-6
Timestamp: 2024-11-01T09:35:23.912Z
Learning: Converting `getAllPosts()` to asynchronous in `scripts/build-rss.js` causes the existing build system to fail.

Applied to files:

  • tests/build-rss.test.ts
  • tests/integration/build-meetings-runner.int.test.ts
  • npm/runners/build-post-list-runner.ts
  • scripts/index.ts
  • tests/integration/build-post-list.int.test.ts
📚 Learning: 2024-11-29T17:36:09.783Z
Learnt from: vishvamsinh28
Repo: asyncapi/website PR: 3378
File: tests/markdown/check-markdown.test.js:133-138
Timestamp: 2024-11-29T17:36:09.783Z
Learning: When testing the 'main' function in 'check-markdown.test.js', it's acceptable to simply ensure it doesn't throw any errors, as the functions it calls are already tested elsewhere.

Applied to files:

  • tests/build-rss.test.ts
  • tests/integration/build-meetings-runner.int.test.ts
  • tests/index.test.ts
  • tests/markdown/check-edit-links.test.ts
  • tests/integration/case-studies-runner.int.test.ts
  • tests/adopters/index.test.ts
  • tests/integration/build-dashboard.int.test.ts
  • tests/integration/build-tools.int.test.ts
  • tests/integration/compose-blog-runner.int.test.ts
  • tests/integration/build-adopters-list-runner.int.test.ts
  • tests/integration/build-post-list.int.test.ts
  • tests/check-locales.test.ts
  • tests/integration/build-pages-runner.int.test.ts
  • tests/integration/build-newsroom-videos-runner.int.test.ts
📚 Learning: 2025-01-19T04:51:41.255Z
Learnt from: anshgoyalevil
Repo: asyncapi/website PR: 3557
File: tests/fixtures/markdown/check-edit-links-data.js:3-11
Timestamp: 2025-01-19T04:51:41.255Z
Learning: In the AsyncAPI website repository, the test data in `tests/fixtures/markdown/check-edit-links-data.js` intentionally includes inconsistent paths (with and without 'docs' prefix) to verify the script's ability to normalize and handle ambiguous path structures.

Applied to files:

  • tests/build-rss.test.ts
  • tests/markdown/check-edit-links.test.ts
  • tests/adopters/index.test.ts
  • tests/integration/build-dashboard.int.test.ts
  • tests/integration/fixtures/tools-fixtures.ts
  • tests/integration/build-tools.int.test.ts
  • tests/integration/compose-blog-runner.int.test.ts
  • tests/integration/build-post-list.int.test.ts
  • tests/integration/build-pages-runner.int.test.ts
  • tests/integration/fixtures/dashboard-fixtures.ts
📚 Learning: 2024-12-02T05:52:49.547Z
Learnt from: akshatnema
Repo: asyncapi/website PR: 3265
File: tests/helper/toolsObjectData.js:1-18
Timestamp: 2024-12-02T05:52:49.547Z
Learning: In `tests/helper/toolsObjectData.js`, using the hard-coded repository ID directly in the URL is acceptable when creating mock data for tests, as we are not asserting anything at `REPO_ID`.

Applied to files:

  • tests/build-rss.test.ts
  • tests/integration/fixtures/tools-fixtures.ts
  • tests/integration/build-tools.int.test.ts
  • tests/integration/fixtures/dashboard-fixtures.ts
📚 Learning: 2025-06-20T14:47:22.389Z
Learnt from: sagarkori143
Repo: asyncapi/website PR: 0
File: :0-0
Timestamp: 2025-06-20T14:47:22.389Z
Learning: Runner files in the npm/runners directory should follow consistent error handling patterns, throwing new Error instances with descriptive messages rather than just rethrowing caught errors.

Applied to files:

  • tests/build-rss.test.ts
  • tests/integration/build-meetings-runner.int.test.ts
  • tests/markdown/check-edit-links.test.ts
  • tests/integration/case-studies-runner.int.test.ts
  • tests/integration/build-tools.int.test.ts
  • tests/integration/build-adopters-list-runner.int.test.ts
  • tests/integration/build-post-list.int.test.ts
  • tests/integration/build-pages-runner.int.test.ts
  • tests/integration/build-newsroom-videos-runner.int.test.ts
  • npm/runners/build-adopters-list-runner.ts
📚 Learning: 2024-10-18T17:24:45.053Z
Learnt from: anshgoyalevil
Repo: asyncapi/website PR: 3301
File: scripts/markdown/check-markdown.js:0-0
Timestamp: 2024-10-18T17:24:45.053Z
Learning: In `scripts/markdown/check-markdown.js`, the script is not run in an asynchronous environment, so refactoring it to use `async/await` is unnecessary.

Applied to files:

  • npm/runners/build-pages-runner.ts
  • tests/markdown/check-edit-links.test.ts
📚 Learning: 2024-11-10T18:16:22.273Z
Learnt from: vishvamsinh28
Repo: asyncapi/website PR: 3284
File: scripts/build-post-list.js:49-53
Timestamp: 2024-11-10T18:16:22.273Z
Learning: In `scripts/build-post-list.js`, the `walkDirectories` function depends on sequential execution because it mutates `resultObj`. Parallelizing the loop with `Promise.all` causes tests to fail.

Applied to files:

  • npm/runners/build-pages-runner.ts
  • tests/integration/build-meetings-runner.int.test.ts
  • scripts/adopters/index.ts
  • tests/index.test.ts
  • tests/markdown/check-edit-links.test.ts
  • tests/integration/case-studies-runner.int.test.ts
  • tests/adopters/index.test.ts
  • tests/integration/compose-blog-runner.int.test.ts
  • tests/integration/build-finance-info-list-runner.int.test.ts
  • tests/build-meetings.test.ts
  • npm/runners/build-post-list-runner.ts
  • scripts/index.ts
  • tests/integration/helpers/build-pages-lock.ts
  • tests/integration/build-adopters-list-runner.int.test.ts
  • tests/integration/build-post-list.int.test.ts
  • tests/integration/build-pages-runner.int.test.ts
  • tests/integration/build-newsroom-videos-runner.int.test.ts
  • npm/runners/build-adopters-list-runner.ts
📚 Learning: 2025-06-20T14:47:22.389Z
Learnt from: sagarkori143
Repo: asyncapi/website PR: 0
File: :0-0
Timestamp: 2025-06-20T14:47:22.389Z
Learning: The AsyncAPI website modularization PR uses Promise.allSettled for parallel execution of build tasks, which provides better performance and fault isolation compared to sequential execution.

Applied to files:

  • tests/integration/build-meetings-runner.int.test.ts
  • npm/runners/build-post-list-runner.ts
  • scripts/index.ts
  • tests/integration/helpers/build-pages-lock.ts
  • tests/integration/build-newsroom-videos-runner.int.test.ts
📚 Learning: 2025-06-19T13:51:27.459Z
Learnt from: sagarkori143
Repo: asyncapi/website PR: 4192
File: npm/runners/build-pages-runner.ts:7-14
Timestamp: 2025-06-19T13:51:27.459Z
Learning: In the AsyncAPI website build system, individual runner functions use try-catch blocks that rethrow errors to maintain consistent error boundaries, while the top-level orchestrator in npm/index.ts provides meaningful error logging with task-specific context using logger.error(`Error building ${taskName}:`, error). This separation of concerns allows for clean error handling at different architectural layers.

Applied to files:

  • tests/integration/build-meetings-runner.int.test.ts
  • tests/integration/build-dashboard.int.test.ts
  • tests/integration/build-tools.int.test.ts
  • npm/runners/build-post-list-runner.ts
  • tests/integration/build-adopters-list-runner.int.test.ts
  • tests/integration/build-pages-runner.int.test.ts
  • tests/integration/build-newsroom-videos-runner.int.test.ts
  • npm/runners/build-dashboard-runner.ts
  • npm/runners/build-adopters-list-runner.ts
📚 Learning: 2025-06-19T13:49:29.796Z
Learnt from: sagarkori143
Repo: asyncapi/website PR: 4192
File: npm/runners/build-newsroom-videos-runner.ts:8-15
Timestamp: 2025-06-19T13:49:29.796Z
Learning: In the AsyncAPI website modularization project, error handling is centralized in the top-level orchestrator function (npm/index.ts) with comprehensive logging and context. Individual runner functions in npm/runners/ are kept simple and let errors propagate naturally to the centralized handler, avoiding redundant try-catch blocks that only rethrow errors.

Applied to files:

  • tests/integration/build-meetings-runner.int.test.ts
  • tests/integration/build-tools.int.test.ts
  • npm/runners/case-studies-runner.ts
📚 Learning: 2025-01-14T15:12:29.840Z
Learnt from: anshgoyalevil
Repo: asyncapi/website PR: 3557
File: scripts/markdown/check-edit-links.js:83-88
Timestamp: 2025-01-14T15:12:29.840Z
Learning: In the AsyncAPI website's edit link generation logic, the `editUrls` configuration (config/edit-page-config.json) includes a fallback entry with an empty value that acts as a catch-all matcher. Therefore, `editOptions.find()` will always return a match, making null checks on the result unnecessary and untestable.

Applied to files:

  • tests/markdown/check-edit-links.test.ts
📚 Learning: 2025-01-08T15:15:00.759Z
Learnt from: anshgoyalevil
Repo: asyncapi/website PR: 3557
File: scripts/markdown/check-editlinks.js:58-59
Timestamp: 2025-01-08T15:15:00.759Z
Learning: In the AsyncAPI codebase, batch processing operations (like in the Dashboard script and check-editlinks.js) follow a sequential pattern using await in loops, which is the preferred approach for maintaining consistency across the codebase.

Applied to files:

  • tests/markdown/check-edit-links.test.ts
📚 Learning: 2025-04-20T16:05:16.482Z
Learnt from: anshgoyalevil
Repo: asyncapi/website PR: 3950
File: scripts/utils/check-locales.ts:122-129
Timestamp: 2025-04-20T16:05:16.482Z
Learning: In the AsyncAPI website project, Next.js throws errors at runtime when locale files are missing, making additional validation for missing files unnecessary in the check-locales script.

Applied to files:

  • tests/markdown/check-edit-links.test.ts
  • tests/integration/build-post-list.int.test.ts
  • tests/check-locales.test.ts
  • tests/integration/build-pages-runner.int.test.ts
📚 Learning: 2025-02-16T12:57:24.575Z
Learnt from: anshgoyalevil
Repo: asyncapi/website PR: 0
File: :0-0
Timestamp: 2025-02-16T12:57:24.575Z
Learning: Tests failing after dependency upgrades indicate potential breaking changes and might require code changes rather than test modifications to support newer versions.

Applied to files:

  • tests/adopters/index.test.ts
  • package.json
📚 Learning: 2024-11-29T19:42:31.175Z
Learnt from: akshatnema
Repo: asyncapi/website PR: 3265
File: scripts/tools/tools-object.js:93-98
Timestamp: 2024-11-29T19:42:31.175Z
Learning: In `scripts/tools/tools-object.js`, when validation fails in the `convertTools` function, errors should be thrown or rejected instead of only logging them, to ensure proper error propagation and handling.

Applied to files:

  • tests/integration/build-tools.int.test.ts
  • tests/check-locales.test.ts
📚 Learning: 2024-10-18T17:28:41.718Z
Learnt from: anshgoyalevil
Repo: asyncapi/website PR: 3301
File: scripts/markdown/check-markdown.js:0-0
Timestamp: 2024-10-18T17:28:41.718Z
Learning: In `scripts/markdown/check-markdown.js`, when processing large markdown files with recursion and loops, synchronous file reads (`fs.readFileSync`) are preferred over asynchronous reads.

Applied to files:

  • tests/build-meetings.test.ts
📚 Learning: 2024-10-19T15:26:43.683Z
Learnt from: anshgoyalevil
Repo: asyncapi/website PR: 3301
File: scripts/markdown/check-markdown.js:127-128
Timestamp: 2024-10-19T15:26:43.683Z
Learning: In `scripts/markdown/check-markdown.js`, synchronous file reading with `fs.readFileSync` is necessary because the files need to be processed synchronously.

Applied to files:

  • tests/build-meetings.test.ts
📚 Learning: 2024-11-10T18:16:35.551Z
Learnt from: vishvamsinh28
Repo: asyncapi/website PR: 3284
File: scripts/build-post-list.js:28-46
Timestamp: 2024-11-10T18:16:35.551Z
Learning: In the `scripts/build-post-list.js` JavaScript file, tests rely on the `result` object being a global variable. Moving it inside the `buildPostList` function causes tests to fail; therefore, keep `result` as a global variable.

Applied to files:

  • tests/integration/build-post-list.int.test.ts
📚 Learning: 2024-10-18T17:37:50.602Z
Learnt from: anshgoyalevil
Repo: asyncapi/website PR: 3301
File: scripts/markdown/check-markdown.js:31-31
Timestamp: 2024-10-18T17:37:50.602Z
Learning: In `scripts/markdown/check-markdown.js`, the `frontmatter` object cannot have a property named `hasOwnProperty`, so using `frontmatter.hasOwnProperty(attr)` is acceptable.

Applied to files:

  • tests/integration/build-post-list.int.test.ts
📚 Learning: 2025-03-23T12:42:49.503Z
Learnt from: anshgoyalevil
Repo: asyncapi/website PR: 3950
File: scripts/utils/check-locales.ts:138-143
Timestamp: 2025-03-23T12:42:49.503Z
Learning: For the locale validation function in check-locales.ts, the team has decided that modifying the outer scope variable 'hasErrors' inside the forEach loop is acceptable despite the ESLint warning about unsafe references in loop functions.

Applied to files:

  • tests/check-locales.test.ts
🔇 Additional comments (62)
config/meetings.json (1)

1-107: Data integrity looks good overall.

The JSON structure is well-formed across all 15 meeting entries. Calendar event IDs, GitHub issue URLs, and ISO 8601 date formatting are consistent. The only minor issue is the trailing space noted above.

One note: Several entries are dated before the PR creation date (2025-08-24), such as meetings on 2025-08-07 and 2025-08-12. If these represent historical meetings intended for integration test fixtures, verify that the test logic handles past-dated entries appropriately to avoid flaky tests based on current date comparisons.

config/all-tags.json (3)

1-30: AI summary describes changes inconsistently with actual code.

The AI summary claims: "Added new public language object in the languages array: { "name": "Go", ... }" However, the "Go" entry (lines 225–229) is in the technologies array, not languages. The languages array ends at line 92.


225-229: Verify the "Go" entry addition and color assignment.

The new "Go" entry uses the same default color scheme (bg-[#61d0f2] / border-[#40ccf7]) as dozens of other entries. This may be a placeholder. Consider:

  • Whether "Go" should have a dedicated, language-specific color (e.g., bg-[#00ADD8] for Go's official blue)
  • Whether this addition is required for the integration tests or represents a separate maintenance task

286-289: Clarify the purpose of the label swap between SmartPaste and JetBrains.

Lines 286–289 and 291–294 are marked as changed and appear to swap the names of these two entries:

  • Line 281–284: SmartPaste (unchanged)
  • Line 286–289: SmartPaste (marked as changed)
  • Line 291–294: JetBrains (marked as changed)

This suggests a label swap, but the intent is unclear. Verify whether:

  • This is a data correction to fix a misplaced label
  • These edits support a specific test fixture or requirement

Also applies to: 291-294

tests/markdown/check-edit-links.test.ts (8)

175-181: LGTM!

Good edge case coverage for null editLink handling. The test properly verifies both the return value and that no network call is made.


191-200: LGTM!

Good verification of resource cleanup. The test properly ensures that timeout cleanup happens in the finally block.


202-207: LGTM!

Good edge case coverage for empty batch handling.


278-282: LGTM!

Good edge case coverage for empty input handling.


308-320: LGTM!

Good edge case coverage for testing batching logic with non-divisible array sizes.


183-189: Error message format is correct.

The implementation at line 61 of scripts/markdown/check-edit-links.ts throws new Error(Error checking ${editLink}: ${error}), which matches the test expectation of .rejects.toThrow('Error checking'). The test correctly validates that the error message begins with "Error checking".


260-261: Error message is correct.

The implementation throws "Failed to check edit links: ${error}" (line 229), and the test expects 'Failed to check edit links'. Jest's .toThrow() performs substring matching, so the expected message correctly matches the error thrown.


112-121: Error message verification confirms both tests are correct. The generatePaths function at line 193 throws errors with the format Error processing directory ${folderPath}: ${err}. Both test expectations properly match this behavior:

  • Line 112-113: Substring "Error processing directory" matches ✓
  • Line 115-121: Substring "Directory read error" matches the re-thrown error ✓
tests/integration/build-finance-info-list-runner.int.test.ts (8)

1-30: LGTM! Well-structured test setup.

The imports are appropriate, and the setup/teardown pattern correctly creates isolated temporary directories for each test with proper cleanup.


32-107: LGTM! Comprehensive file creation tests.

The tests properly verify JSON file generation from YAML sources and directory creation behavior.


109-251: LGTM! Thorough content validation.

The tests comprehensively validate YAML-to-JSON conversion, including nested structures and empty arrays.


253-358: LGTM! Comprehensive year selection tests.

The tests properly verify automatic latest year selection, explicit year usage, and correct descending year sorting.


396-424: LGTM! Custom path configuration tested correctly.

The test properly verifies that custom directory paths are respected by the runner.


426-520: LGTM! Comprehensive error handling coverage.

The tests properly verify all error scenarios including missing data, missing files, and non-numeric directory filtering. The use of .rejects.toThrow(CustomError) correctly tests async errors.


522-617: LGTM! Excellent edge case coverage.

The tests handle special characters, large files (100 entries), and file overwriting scenarios. The YAML generation logic is correct, including proper escaping and formatting.


360-393: Verify test isolation when parallel execution is enabled, or reconfigure Jest to run integration tests sequentially.

The test uses process.chdir() to test default path behavior with proper restoration in the finally block (line 390). However, since jest.config.js does not disable parallel execution (no maxWorkers or runInBand settings), Jest 29.7.0 will run tests concurrently on multi-core systems. This creates a race condition: if multiple tests change process.cwd() in parallel, the global process state can be corrupted even with individual finally blocks restoring values.

Recommended fixes:

  • Configure Jest to run integration tests serially: add maxWorkers: 1 for integration tests in jest.config.js, or mark this test suite with .serial (if available), OR
  • Use isolated worker processes that don't share global process.cwd() state.
npm/runners/case-studies-runner.ts (2)

56-67: LGTM! Clean execution guard pattern.

The guard correctly prevents execution in test environments using both NODE_ENV and VITEST_WORKER_ID checks. The IIFE pattern properly handles top-level async execution, and the error handling aligns with the centralized pattern where detailed logging occurs within runCaseStudies itself.


69-70: LGTM! Export enables testability.

The export properly exposes runCaseStudies for integration testing and external usage, aligning with the modularization pattern across other runner files in this PR.

tests/integration/case-studies-runner.int.test.ts (3)

14-89: LGTM! Well-structured test setup.

The beforeAll hook properly creates an isolated temporary test environment with diverse YAML fixtures covering multi-line strings, arrays, nested objects, and multiple AsyncAPI versions. The afterAll cleanup ensures no test artifacts remain.


329-474: Excellent edge case coverage!

This test section thoroughly validates minimal fields, full optional fields, multiple files, and different YAML extensions. The comprehensive fixture on lines 362-415 is particularly valuable for ensuring the runner handles complex nested structures correctly.


192-196: No issues found—test will pass reliably with current project setup.

Verification confirms the config/casestudies directory exists with two syntactically valid YAML files (adeo.yml, hdi.yml). The runCaseStudies() function correctly defaults to this directory and includes explicit validation that throws a CustomError if the directory is missing, preventing unpredictable failures. The test is not fragile and will execute successfully.

tests/build-rss.test.ts (3)

147-149: LGTM: Consistent multi-line formatting improves readability

The jest.doMock calls have been reformatted to split the options object across multiple lines, improving consistency and readability throughout the test file.

Also applies to: 182-184, 206-208, 220-222, 238-238, 258-260


219-244: LGTM: Comprehensive error handling tests

These new tests properly verify CustomError handling—both re-throwing existing CustomError instances without wrapping and wrapping non-Error exceptions. The tests validate error context properties, ensuring robust error propagation.


246-269: LGTM: Good edge case coverage for posts without cover images

This test ensures that posts without cover images don't generate <enclosure> tags in the RSS feed, which is the correct RSS behavior.

npm/runners/build-tools-runner.ts (1)

64-79: LGTM: Clean public API and direct-execution guard

The exports enable testing and programmatic usage, while the import.meta.url guard ensures the module only auto-runs when executed directly, avoiding side effects on import.

tests/index.test.ts (1)

48-100: LGTM: Thorough coverage of finance directory parsing

These new tests comprehensively verify the finance directory handling logic: filtering non-numeric entries, sorting years correctly, handling decimal numbers, and properly throwing errors when no valid data is found.

config/newsroom_videos.json (1)

3-30: LGTM: Updated newsroom video data

The video entries have been refreshed with current 2025 content. The structure remains consistent, and the data appears valid.

npm/runners/build-pages-runner.ts (1)

5-8: LGTM: Public API exports and safe direct-execution guard

The exported interface and function enable testing and programmatic usage. The import.meta.url guard ensures the CLI only runs when executed directly, addressing the concern about side effects on import.

Also applies to: 47-61

tests/integration/helpers/build-pages-lock.ts (1)

12-24: LGTM: Atomic lock acquisition using exclusive flag

The use of the wx flag ensures atomic lock creation, preventing race conditions when multiple test processes attempt to acquire the lock simultaneously.

npm/runners/build-post-list-runner.ts (1)

11-15: LGTM: Clean public API with proper error handling

The exported interface and function enable testing and external usage. Error handling properly wraps errors in CustomError with context.

Also applies to: 28-50

package.json (2)

10-10: LGTM! Test script consolidation aligns with integration test setup.

The test script changes properly separate unit and integration test execution, with appropriate path targeting and exclusion patterns.

Also applies to: 13-14


179-179: nock dependency verified as current and secure.

The nock version 14.0.10 is the latest available on npm with no known security vulnerabilities. The dependency is appropriately placed in devDependencies for HTTP mocking in tests.

tests/integration/compose-blog-runner.int.test.ts (4)

12-24: LGTM! Robust test setup and cleanup.

The beforeEach and afterEach hooks properly manage temporary directories with unique naming and comprehensive cleanup.


115-266: LGTM! Comprehensive content validation coverage.

The tests thoroughly validate front matter structure, tag formatting, empty value handling, and default metadata generation.


427-505: LGTM! Thorough error handling validation.

The tests properly validate CustomError usage, error contexts, and various failure scenarios including missing fields and file conflicts.


507-714: LGTM! Excellent edge case coverage and API verification.

The tests cover various edge cases including special characters, long content, different post types, and properly verify the public API surface.

npm/runners/build-dashboard-runner.ts (2)

11-13: LGTM! Clean public API interface.

The exported BuildDashboardOptions interface provides a clear contract for the runner's configuration.


25-67: LGTM! Proper test environment handling and CLI integration.

The function export, error handling, and CLI guard properly prevent auto-execution in test environments while maintaining CLI functionality. The past review feedback has been addressed.

Based on learnings

tests/build-meetings.test.ts (2)

1-1: LGTM! Appropriate migration to promise-based cleanup.

The import update enables promise-based cleanup while maintaining synchronous operations where appropriate for the test context.


42-49: LGTM! Robust async cleanup with appropriate error handling.

The async cleanup with try/catch properly handles potential cleanup failures, especially on Windows where file handle delays can occur. The comment provides valuable context.

tests/integration/helpers/file-utils.ts (1)

10-28: LGTM! Clean recursive file listing implementation.

The function properly traverses directories and accumulates file paths. The sequential processing with no-await-in-loop is appropriate for maintaining order and simplicity, though it could be optimized with Promise.all if performance becomes a concern.

npm/runners/build-meetings-runner.ts (2)

11-13: LGTM! Consistent public API exports.

The interface and function exports follow the established pattern across runners, enabling both testing and external usage.

Also applies to: 57-57


43-54: LGTM! Proper test environment guard.

The CLI execution guard correctly prevents auto-execution in test environments, matching the pattern established in other runners.

tests/adopters/index.test.ts (2)

13-13: LGTM! Tests properly updated for new function signature.

The test calls correctly use the new two-argument signature for buildAdoptersList, maintaining test coverage while adapting to API changes.

Also applies to: 20-25


31-37: LGTM! Appropriate input validation test coverage.

The new tests properly verify that required parameters are validated with clear error messages.

npm/runners/build-newsroom-videos-runner.ts (2)

11-13: LGTM! Consistent public API pattern.

The interface and function exports maintain consistency with other runner modules in the codebase.

Also applies to: 57-57


44-54: LGTM! Proper test environment guard in place.

The CLI execution guard correctly prevents auto-execution during test imports, following the established pattern.

scripts/index.ts (1)

36-39: Adopters list invocation correctly updated to new API.

Supplying explicit source and target config paths via resolve(currentDirPath, '../config', ...) matches the new buildAdoptersList(sourcePath, targetPath) contract and keeps path handling consistent with other builders in this script.

tests/integration/build-adopters-list-runner.int.test.ts (1)

13-38: Temp workspace setup and runner invocation look clean.

Using a unique tempDir under os.tmpdir, wiring sourcePath to the real config/adopters.yml, and cleaning up in afterAll gives good isolation while still exercising the real pipeline via runBuildAdoptersList. No changes needed here.

tests/integration/build-tools.int.test.ts (1)

227-262: Good coverage of CustomError context for GitHub API failures.

The should handle GitHub API errors gracefully test validating CustomError, context.category, context.operation, message contents, and context.detail gives solid assurance that API failures propagate with meaningful context, matching the earlier guidance around structured error handling for scripts. Based on learnings.

tests/integration/build-meetings-runner.int.test.ts (1)

236-258: LGTM: Environment restoration is properly guarded.

The try/finally blocks ensure CALENDAR_SERVICE_ACCOUNT and CALENDAR_ID are restored even if the test assertions fail, preventing environment pollution across tests.

tests/integration/fixtures/tools-fixtures.ts (1)

1-399: LGTM: Comprehensive test fixtures.

The mock data is well-structured with diverse scenarios covering GitHub API responses, tool metadata, pagination, manual/automated tools, tags, and error cases. This provides excellent coverage for integration tests.

npm/runners/build-adopters-list-runner.ts (1)

8-59: LGTM: Consistent runner pattern with proper CLI guards.

The implementation follows the established pattern for runner modules:

  • Configurable options with sensible defaults
  • CLI execution guard prevents auto-run in test environments (checking both NODE_ENV and VITEST_WORKER_ID)
  • Public export enables integration testing
  • CustomError wrapping with contextual details

Based on learnings

tests/integration/build-post-list.int.test.ts (1)

81-374: LGTM: Comprehensive integration test coverage.

The test suite thoroughly validates:

  • File creation and structure
  • Section presence (docs, blog, about, docsTree)
  • Required fields and type validation
  • Slug uniqueness and prefixes
  • TOC structure, reading time, excerpts
  • Nested sections, weights, index files
  • Error handling for invalid inputs

The 30-second timeout on line 114 appropriately accommodates the build operations.

tests/integration/fixtures/dashboard-fixtures.ts (1)

1-500: LGTM: Well-structured dashboard test fixtures.

The mock data comprehensively covers dashboard scenarios including hot discussions (issues and PRs), good first issues, pagination with hasNextPage, pull requests with reviews, and error responses. The data structure matches the expected GraphQL response format.

tests/integration/build-pages-runner.int.test.ts (1)

9-713: LGTM: Excellent integration test coverage.

The test suite is exceptionally thorough, covering:

  • File creation and structural preservation
  • .md.mdx renaming
  • Content transformations (HTML comments → JSX, table tag capitalization)
  • Default options and error handling
  • Edge cases (special characters, unicode, deep nesting, large files)
  • Idempotency

The tests validate both the happy path and numerous edge cases, ensuring robust behavior.

tests/integration/build-dashboard.int.test.ts (1)

17-300: LGTM: Comprehensive dashboard integration tests.

The test suite provides thorough coverage:

  • File creation and structure validation
  • CustomError handling with proper context
  • Rate limit warnings and pagination
  • Pull request handling via getDiscussionByID
  • Data integrity (required fields, uniqueness, sorting)
  • Missing GitHub token scenario

The use of helper mocks from nock-helpers.ts keeps the tests clean and maintainable. Proper cleanup in afterEach and afterAll prevents test interference.

tests/integration/fixtures/nock-helpers.ts (1)

1-323: LGTM: Well-organized nock helper utilities.

The helper functions effectively encapsulate nock setup for different integration test scenarios:

  • Dashboard mocks: GraphQL API with pagination, rate limits, and error handling
  • Tools mocks: GitHub Code Search and raw content APIs
  • Newsroom mocks: YouTube API interactions

The request body parsing logic (lines 73-96, 131-154) properly handles Buffer and string types, making the mocks robust. Clear JSDoc comments document each helper's purpose.

Copy link

@akshat-nema akshat-nema left a comment

Choose a reason for hiding this comment

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

Why codecov coverage is still around 40% in it?

sagarkori143 and others added 12 commits November 16, 2025 20:44
Co-authored-by: Akshat Nema <158018845+akshat-nema@users.noreply.github.com>
Co-authored-by: Akshat Nema <158018845+akshat-nema@users.noreply.github.com>
Co-authored-by: Akshat Nema <158018845+akshat-nema@users.noreply.github.com>
Co-authored-by: Akshat Nema <158018845+akshat-nema@users.noreply.github.com>
Co-authored-by: Akshat Nema <158018845+akshat-nema@users.noreply.github.com>
Co-authored-by: Akshat Nema <158018845+akshat-nema@users.noreply.github.com>
@sagarkori143
Copy link
Contributor Author

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 16, 2025

✅ Actions performed

Full review triggered.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 11

Caution

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

⚠️ Outside diff range comments (2)
npm/runners/build-tools-runner.ts (1)

64-79: Tighten the CLI “run when main” check for cross‑platform reliability

The guard if (import.meta.url === \file://${process.argv[1]}`)` relies on constructing a file URL by string concatenation, which can break on Windows paths and edge cases (spaces, encoding). It’s safer to compare OS paths:

-if (import.meta.url === `file://${process.argv[1]}`) {
+if (fileURLToPath(import.meta.url) === process.argv[1]) {
   (async () => {
     try {
       await runBuildTools();
     } catch (error) {
       process.exit(1);
     }
   })();
 }

This reuses the existing fileURLToPath import and keeps the semantics while being more robust.

npm/runners/build-dashboard-runner.ts (1)

11-49: Use the resolved outputPath in error context instead of options.outputPath

runBuildDashboard’s error handling is aligned with the runners’ pattern (wrap in CustomError, add operation/detail, log, rethrow), but the context currently uses options.outputPath, which is often undefined when the default path is used:

const outputPath = options.outputPath || resolve(currentDirPath, '../../dashboard.json');
// ...
detail: `Runner failed with output path: ${options.outputPath}`

Switching the detail to use the resolved outputPath will give accurate diagnostics regardless of whether the caller passed an explicit value:

-            operation: 'runBuildDashboard',
-            detail: `Runner failed with output path: ${options.outputPath}`
+            operation: 'runBuildDashboard',
+            detail: `Runner failed with output path: ${outputPath}`
@@
-            category: 'script',
-            operation: 'runBuildDashboard',
-            detail: `Build dashboard runner failed with output path: ${options.outputPath}`
+            category: 'script',
+            operation: 'runBuildDashboard',
+            detail: `Build dashboard runner failed with output path: ${outputPath}`

Optionally, you may also want to normalize CLI-provided paths through resolve for consistency with the default path, but that’s a nice-to-have.

♻️ Duplicate comments (4)
jest.config.js (1)

16-20: Comment and configuration still diverge: integration tests remain matched

The past review comment correctly identified that the comment claims "except integration" but testMatch still includes tests/integration. The suggested fix to add testPathIgnorePatterns has not been applied.

npm/runners/build-pages-runner.ts (1)

47-58: Use path comparison instead of URL string comparison in main guard

The direct-run guard currently compares import.meta.url to file://${process.argv[1]}, which can be fragile on Windows or with unusual paths/encoding. Replacing it with a path comparison is safer:

-if (import.meta.url === `file://${process.argv[1]}`) {
+if (fileURLToPath(import.meta.url) === process.argv[1]) {
   (async () => {
     try {
       await runBuildPages();
     } catch (error) {
       process.exit(1);
     }
   })();
 }

This keeps import-time side effects off while improving cross-platform behavior.

npm/runners/build-adopters-list-runner.ts (1)

26-43: Use resolved paths in error detail for clearer diagnostics

runBuildAdoptersList correctly wraps failures in a CustomError, but the detail field currently uses options.sourcePath / options.targetPath. When callers omit options and rely on defaults, this will log undefined instead of the actual resolved paths.

You can improve the error context by using the computed values:

-    const sourcePath = options.sourcePath || resolve(currentDirPath, '../../config', 'adopters.yml');
-    const targetPath = options.targetPath || resolve(currentDirPath, '../../config', 'adopters.json');
+    const sourcePath = options.sourcePath || resolve(currentDirPath, '../../config', 'adopters.yml');
+    const targetPath = options.targetPath || resolve(currentDirPath, '../../config', 'adopters.json');
@@
-      detail: `Build adopters list failed - sourcePath: ${options.sourcePath}, targetPath: ${options.targetPath}`
+      detail: `Build adopters list failed - sourcePath: ${sourcePath}, targetPath: ${targetPath}`

This keeps the contract unchanged while making logs and error reports more actionable.

tests/integration/build-post-list.int.test.ts (1)

19-58: Align waitForPages max wait with Jest's beforeAll timeout

The concern is valid: waitForPages defaults to 60 000 ms, while the beforeAll at line 76 has a 30 000 ms timeout. If page builds take between 30–60 seconds, Jest will timeout the hook before waitForPages completes, causing flaky failures.

Additionally, the return value of waitForPages() at line 105 is not checked—the code proceeds regardless of success or timeout, masking failures.

Consider either:

  • Lowering waitForPages's default (or passing a smaller maxWaitMs from beforeAll), or
  • Increasing the hook timeout to at least 60 000 ms

Also validate the boolean result and fail early with a clear error if pages never become valid, rather than letting Jest timeout silently.

🧹 Nitpick comments (25)
tests/integration/case-studies-runner.int.test.ts (1)

495-505: Use custom test directories for better isolation.

The promise is now properly awaited (good!), but calling runCaseStudies() without arguments uses real project directories which could fail unpredictably and isn't isolated. The test should focus on verifying the export and promise behavior using controlled test paths.

Apply this diff to use isolated test directories:

   describe('Function Export', () => {
     it('should export the runner function', async () => {
       expect(typeof runCaseStudies).toBe('function');
-      // Verify it's a Promise-returning function
-      const promise = runCaseStudies();
+    });
+
+    it('should return a Promise', async () => {
+      const testDir = resolve(tempDir, 'export-test');
+      const testOutput = resolve(tempDir, 'export-test-output.json');
+      await fs.mkdir(testDir, { recursive: true });
+      
+      const promise = runCaseStudies({
+        caseStudyDirectory: testDir,
+        outputPath: testOutput
+      });
 
       expect(promise).toBeInstanceOf(Promise);
-      // Await the Promise to handle any potential rejections
       await promise;
     });
   });
tests/build-rss.test.ts (2)

154-188: Consider verifying the error message content.

The test creates detailed mock data with posts missing dates (including specific titles and slugs), and the test name suggests it should verify that these posts are "included in the error message." However, the test only checks that a CustomError is thrown without verifying the error message content.

Consider adding an assertion to verify the error message contains the expected post identifiers:

-    // This should specifically test the error thrown by the missingDatePosts check
-    await expect(rssFeed(type, title, desc, outputPath)).rejects.toThrow(CustomError);
+    // This should specifically test the error thrown by the missingDatePosts check
+    try {
+      await rssFeed(type, title, desc, outputPath);
+    } catch (error) {
+      expect(error).toBeInstanceOf(CustomError);
+      const errorMessage = (error as CustomError).message;
+      expect(errorMessage).toContain('Post 1 without Date');
+      expect(errorMessage).toContain('Post 2 without Date');
+      expect(errorMessage).toContain('/blog/post3-no-date-no-title'); // Verify slug is used when title is null
+    }

237-244: LGTM: Good error handling coverage

The test properly verifies that non-Error exceptions (like strings) are wrapped in CustomError. The mock cleanup is correctly handled.

Optionally, consider adding a comment to clarify the intentional use of a string error:

   it('should wrap non-Error exceptions in CustomError', async () => {
     jest.doMock('../config/posts.json', () => mockRssData, { virtual: true });
+    // Intentionally reject with a non-Error value to test error wrapping
     const mockWriteFile = jest.spyOn(fs.promises, 'writeFile').mockRejectedValue('String error');
tests/markdown/check-edit-links.test.ts (3)

209-216: Consider strengthening the AbortController test.

This test immediately aborts the controller and mocks fetch to reject with 'Aborted', but it doesn't verify that the abort signal is actually passed to fetch or that fetch respects the signal. The test would pass even if processBatch doesn't use the AbortController at all.

To properly validate abort behavior, consider:

  • Verifying that mockFetch is called with the abort signal: expect(mockFetch).toHaveBeenCalledWith(expect.anything(), expect.objectContaining({ signal: expect.any(AbortSignal) }))
  • Or testing a real abort scenario where fetch is in-flight when abort is called

265-273: Consider using jest.spyOn on the imported module instead of dynamic require.

The dynamic require with global-require disable is a code smell. Since generatePaths is already imported at line 10, you could use jest.spyOn on the imported module:

-    // eslint-disable-next-line global-require
-    const mockGeneratePaths = jest.spyOn(require('../../scripts/markdown/check-edit-links'), 'generatePaths');
+    const checkEditLinks = await import('../../scripts/markdown/check-edit-links');
+    const mockGeneratePaths = jest.spyOn(checkEditLinks, 'generatePaths');

However, if module mocking constraints require the current approach, the existing implementation is acceptable.


191-200: Note: Testing implementation detail rather than behavior.

This test verifies that clearTimeout is called, which is an implementation detail rather than observable behavior. While this helps ensure proper cleanup, it can make tests brittle if the implementation changes to use a different cleanup mechanism.

Consider whether this test adds significant value, or if resource cleanup could be validated through other means (e.g., integration tests that detect leaked timers).

npm/runners/build-meetings-runner.ts (1)

43-54: Consider adding a direct-execution guard, not just a test-env guard

Right now the CLI auto-runs whenever NODE_ENV !== 'test' and VITEST_WORKER_ID is unset, even if this module is imported from other runtime code. To avoid side effects on import and stay consistent with other runners, consider also guarding on the module being the entry script (e.g., via a fileURLToPath(import.meta.url) === process.argv[1] check) so only direct CLI execution runs the IIFE.
Based on learnings

npm/runners/build-post-list-runner.ts (1)

11-51: Tighten types and error context for better diagnostics

Two small improvements here:

  • postDirectories is currently typed as string[][], but it’s always [directoryPath, routePrefix]. A tuple type like [string, string][] would better express intent and catch misuses at compile time.
  • In the error detail you log options.outputPath, which is often undefined when relying on the default. Logging the computed outputPath (and optionally basePath) would make runner failures easier to diagnose.

For example:

-    const customError = CustomError.fromError(error, {
-      category: 'script',
-      operation: 'runBuildPostList',
-      detail: `Build post list failed with output path: ${options.outputPath}`
-    });
+    const customError = CustomError.fromError(error, {
+      category: 'script',
+      operation: 'runBuildPostList',
+      detail: `Build post list failed with output path: ${outputPath}`
+    });

Based on learnings

tests/integration/compose-blog-runner.int.test.ts (2)

493-515: Make the CustomError context test fail if no error is thrown

In wraps errors in CustomError with proper context, if runComposeBlog ever stops throwing for this input, the test will pass without executing any assertions. To keep it robust, explicitly assert that an error is thrown:

it('wraps errors in CustomError with proper context', async () => {
  expect.assertions(3);

  const answers = { /* ... */ };

  try {
    await runComposeBlog({
      answers,
      outputPath: join(outputDir, 'error-test.md')
    });
    // Optional: explicitly fail if no error
    // fail('Expected runComposeBlog to throw');
  } catch (error) {
    expect(error).toBeInstanceOf(CustomError);
    if (error instanceof CustomError) {
      expect(error.context.operation).toBe('runComposeBlog');
      expect(error.context.category).toBe('script');
    }
  }
});

This guarantees the test fails if the expected error is not produced.


671-707: Default-path test is correct but touches real project files

The returns default path when outputPath is not provided test accurately verifies the default behavior by calling runComposeBlog without outputPath and checking for markdown/blog/<slug>.md. It mitigates conflicts via a unique title and attempts cleanup.

If this ever becomes noisy (e.g., failures leaving behind files), consider routing the default path via a configurable base directory in runComposeBlog so tests can keep everything under os.tmpdir(). For now, the current approach is acceptable.

tests/integration/helpers/build-pages-lock.ts (1)

37-109: Polling logic for waitForPagesBuild is robust; only minor optional refactors

The timeout-based polling of the pages directory, checking for blog/docs/about and .mdx files, is a reasonable readiness check for these integration tests. Swallowing IO errors and always sleeping between iterations keeps the helper resilient without over-complicating it. If you want, you could factor the ['blog', 'docs', 'about'] list into a shared constant or log which subdir satisfied the condition, but that’s purely optional.

tests/integration/helpers/file-utils.ts (1)

4-28: Recursive file walker is correct; consider normalizing directory separators

The recursive getAllFiles implementation is straightforward and correct for test usage. If you ever need these directory entries to be reused as OS paths (not just for assertions), you might consider using path.sep instead of a hard-coded / when pushing directory names:

-    if (stat.isDirectory()) {
-      fileList.push(`${filePath}/`);
+    if (stat.isDirectory()) {
+      fileList.push(`${filePath}${path.sep}`);

But as a test-only helper, the current approach is acceptable.

scripts/adopters/index.ts (1)

15-50: Robust validation & context wrapping; consider aligning context keys with runner usage

The input validation and contextual wrapping around writeJSON look solid and give good diagnostics. One small polish: the early errors attach context.function = 'buildAdoptersList' while the catch block (and the runner) work with context.operation. Using operation consistently (or copying function into operation before rethrow) would make downstream error consumers simpler and more uniform.

tests/integration/build-meetings-runner.int.test.ts (1)

195-201: Make export/type-safety test async and reuse the mock

As written, runBuildMeetings() is invoked in a synchronous test and the returned Promise is never awaited. If runBuildMeetings rejects (e.g., because mockCalendar isn’t configured for this specific call), Jest may see an unhandled rejection instead of a normal assertion failure, and the test doesn’t explicitly verify successful completion.

You can keep the “returns a Promise” check but make the flow explicit:

-    it('should export the runBuildMeetings function', () => {
-      expect(typeof runBuildMeetings).toBe('function');
-      // Verify it's a Promise-returning function
-      expect(runBuildMeetings()).toBeInstanceOf(Promise);
-    });
+    it('should export the runBuildMeetings function', async () => {
+      expect(typeof runBuildMeetings).toBe('function');
+      mockCalendar.mockResolvedValue({ data: { items: mockEvents } });
+
+      const promise = runBuildMeetings({ outputPath });
+      expect(promise).toBeInstanceOf(Promise);
+      await expect(promise).resolves.toBeUndefined();
+    });

This matches the integration style used elsewhere and ensures the async path is properly exercised.

tests/integration/build-tools.int.test.ts (1)

227-287: Comprehensive error-path coverage and correct Promise assertions

The error-handling scenarios around GitHub failures, empty responses, and file-write issues are well covered here, and it’s good to see the Promise assertions using .resolves.toBeUndefined() / .rejects.toThrow() instead of .resolves.not.toThrow(). The CustomError context checks (category, operation, detail) in the surrounding tests also align nicely with the runner’s contract.

npm/runners/build-adopters-list-runner.ts (1)

46-64: Consider avoiding double logging between runner and CLI wrapper

Both the inner runBuildAdoptersList catch and the CLI IIFE log an error via logger.error for the same failure before rethrowing / exiting. That’s functionally safe, but in CLI usage it can result in duplicated log lines for a single error.

If you want to align more closely with the “runners define error boundaries, top-level orchestrator/CLI does the logging” pattern, you could either:

  • Drop the logger.error call inside runBuildAdoptersList and let the CLI (or npm/index.ts) be responsible for logging, or
  • Keep the runner log and simplify the CLI wrapper to just process.exit(1) after logging once.

Not mandatory, but it would make logs a bit cleaner.

tests/integration/build-finance-info-list-runner.int.test.ts (1)

1-611: Finance info runner integration tests are thorough and well-isolated

The suite exercises creation, year selection, default/custom path handling, error paths (CustomError cases), and several edge cases using per-test temp directories, which is solid. If you ever find this file getting unwieldy, consider small helpers for repeated “write Expenses/ExpensesLink YAML and run” sequences, but that’s optional.

tests/integration/build-pages-runner.int.test.ts (2)

402-407: Avoid unawaited runBuildPages call in “Function Export” test

The export test calls runBuildPages() without awaiting or returning the Promise, which can leave work running in the background and potentially overlap with other tests.

Given other tests already prove the function runs end-to-end, this check can safely be simplified to a pure export assertion:

-  describe('Function Export', () => {
-    it('should export the runner function', () => {
-      expect(typeof runBuildPages).toBe('function');
-      // Verify it's a Promise-returning function
-      expect(runBuildPages()).toBeInstanceOf(Promise);
-    });
-  });
+  describe('Function Export', () => {
+    it('should export the runner function', () => {
+      expect(typeof runBuildPages).toBe('function');
+    });
+  });

This still validates the public API without introducing extra concurrent runs.


14-90: Shared tempDir/targetDir across tests is acceptable but could be isolated further

Using beforeAll to seed a single tempDir/sourceDir/targetDir and repeatedly invoking runBuildPages works here (and you explicitly test idempotency), but it does mean tests share filesystem state and may mask ordering-sensitive issues.

If you ever see flakiness, consider moving targetDir setup/cleanup to beforeEach/afterEach for stronger isolation, while keeping the current structure as a starting point.

tests/integration/fixtures/dashboard-fixtures.ts (1)

1-500: Dashboard fixtures align well with expected GraphQL shapes

The mock structures (issues, PRs, pagination, rateLimit, errors) look consistent with the runner’s needs and give good coverage for dashboard scenarios. If any future tests start comparing timestamps directly, consider switching the new Date(...).toISOString() values to fixed ISO strings to make them fully deterministic, but it isn’t necessary with the current usage. Based on learnings.

tests/integration/build-post-list.int.test.ts (3)

183-198: Consolidate the duplicate toc-structure checks

The tests “toc entries in docs have expected fields” and “docs items with toc have valid structure” effectively assert the same shape (content, slug, lvl, i with expected types) on item.toc.

You could keep just one of these (or merge them) to reduce duplication and keep future maintenance simpler, without losing coverage.

Also applies to: 232-243


271-282: Clarify what is being asserted for directories without _section.mdx

The test name and comment refer to “directories without _section.mdx”, but the filter condition is effectively “all section items whose title does not include ‘Welcome’”. That will also include sections that do have _section.mdx files.

Either tightening the filter (e.g., based on isSection plus some flag or slug heuristic), or relaxing the description (e.g., “section items have a string title”) would make the test intent clearer and avoid future confusion.


351-373: Tighten error-handling tests by asserting error messages

The invalid basePath and writeFilePath tests assert specific error messages, but the postDirectories case only checks that some error is thrown. Given the runners are expected to surface clear, descriptive errors, it would be helpful to also assert on the message (even partially) here.

For example:

-    await expect(
-      runBuildPostList({
-        outputPath: resolve(tempDir, 'empty-dirs-test.json'),
-        basePath: 'pages',
-        postDirectories: []
-      })
-    ).rejects.toThrow();
+    await expect(
+      runBuildPostList({
+        outputPath: resolve(tempDir, 'empty-dirs-test.json'),
+        basePath: 'pages',
+        postDirectories: []
+      })
+    ).rejects.toThrow('postDirectories');

This aligns with the actual error thrown by buildPostList ("postDirectories array is empty") and maintains consistency with the adjacent validation tests.

tests/integration/fixtures/nock-helpers.ts (2)

9-11: Update documentation comments to match the new .int.test.ts filenames

The header comments still reference tests/integration/build-dashboard.test.ts and tests/integration/build-tools.test.ts, but the integration suites are now named with .int.test.ts.

Consider updating these comments to avoid confusion:

-// Tests: tests/integration/build-dashboard.test.ts
+// Tests: tests/integration/build-dashboard.int.test.ts
...
-// Tests: tests/integration/build-tools.test.ts
+// Tests: tests/integration/build-tools.int.test.ts

Also applies to: 205-207


69-121: Extract shared GraphQL body parsing logic to reduce duplication

Both setupDashboardPaginationMocks and setupPullRequestMocks implement identical body parsing logic (lines 77–93 and 135–151). The parsing handles Buffer, string, and object cases identically, differing only in the fallback value.

Consider extracting a helper to centralize this logic:

function parseGraphQLRequestBody(path: string, body: string | Buffer | any, fallback: any) {
  try {
    if (body instanceof Buffer) {
      return JSON.parse(body.toString());
    }
    if (typeof body === 'string') {
      if (body === '/graphql' || body === path) {
        return fallback;
      }
      return JSON.parse(body);
    }
    return body;
  } catch {
    return fallback;
  }
}

Then call it in both callbacks with the appropriate fallback (paginationMocks.firstPage or emptyResponse). This keeps routing logic clear while centralizing the parsing behavior.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8ddbe47 and 73df674.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (38)
  • config/all-tags.json (1 hunks)
  • config/meetings.json (1 hunks)
  • config/newsroom_videos.json (1 hunks)
  • jest.config.js (1 hunks)
  • markdown/blog/default-path-test-1763304991853.md (1 hunks)
  • markdown/blog/default-path-test.md (1 hunks)
  • npm/runners/build-adopters-list-runner.ts (2 hunks)
  • npm/runners/build-dashboard-runner.ts (3 hunks)
  • npm/runners/build-meetings-runner.ts (2 hunks)
  • npm/runners/build-newsroom-videos-runner.ts (2 hunks)
  • npm/runners/build-pages-runner.ts (2 hunks)
  • npm/runners/build-post-list-runner.ts (3 hunks)
  • npm/runners/build-tools-runner.ts (1 hunks)
  • npm/runners/case-studies-runner.ts (1 hunks)
  • package.json (2 hunks)
  • scripts/adopters/index.ts (1 hunks)
  • scripts/index.ts (1 hunks)
  • tests/adopters/index.test.ts (1 hunks)
  • tests/build-meetings.test.ts (2 hunks)
  • tests/build-rss.test.ts (4 hunks)
  • tests/check-locales.test.ts (1 hunks)
  • tests/index.test.ts (1 hunks)
  • tests/integration/build-adopters-list-runner.int.test.ts (1 hunks)
  • tests/integration/build-dashboard.int.test.ts (1 hunks)
  • tests/integration/build-finance-info-list-runner.int.test.ts (1 hunks)
  • tests/integration/build-meetings-runner.int.test.ts (1 hunks)
  • tests/integration/build-newsroom-videos-runner.int.test.ts (1 hunks)
  • tests/integration/build-pages-runner.int.test.ts (1 hunks)
  • tests/integration/build-post-list.int.test.ts (1 hunks)
  • tests/integration/build-tools.int.test.ts (1 hunks)
  • tests/integration/case-studies-runner.int.test.ts (1 hunks)
  • tests/integration/compose-blog-runner.int.test.ts (1 hunks)
  • tests/integration/fixtures/dashboard-fixtures.ts (1 hunks)
  • tests/integration/fixtures/nock-helpers.ts (1 hunks)
  • tests/integration/fixtures/tools-fixtures.ts (1 hunks)
  • tests/integration/helpers/build-pages-lock.ts (1 hunks)
  • tests/integration/helpers/file-utils.ts (1 hunks)
  • tests/markdown/check-edit-links.test.ts (3 hunks)
🧰 Additional context used
🧠 Learnings (31)
📓 Common learnings
Learnt from: sagarkori143
Repo: asyncapi/website PR: 0
File: :0-0
Timestamp: 2025-06-20T14:47:22.389Z
Learning: Runner files in the npm/runners directory should follow consistent error handling patterns, throwing new Error instances with descriptive messages rather than just rethrowing caught errors.
📚 Learning: 2025-01-18T08:44:43.614Z
Learnt from: akshatnema
Repo: asyncapi/website PR: 3423
File: tests/index.test.js:2-7
Timestamp: 2025-01-18T08:44:43.614Z
Learning: In the AsyncAPI website project, JavaScript test files must include the .ts extension when importing TypeScript files (e.g., `require('../scripts/build-rss.ts')`). This is a project-specific requirement enforced by the linting rules and build setup, even though it differs from typical Node.js behavior.

Applied to files:

  • tests/integration/build-adopters-list-runner.int.test.ts
  • tests/build-meetings.test.ts
  • npm/runners/build-pages-runner.ts
  • tests/adopters/index.test.ts
  • tests/integration/build-newsroom-videos-runner.int.test.ts
  • jest.config.js
  • tests/integration/case-studies-runner.int.test.ts
  • tests/integration/build-post-list.int.test.ts
📚 Learning: 2025-01-18T08:44:43.614Z
Learnt from: akshatnema
Repo: asyncapi/website PR: 3423
File: tests/index.test.js:2-7
Timestamp: 2025-01-18T08:44:43.614Z
Learning: In the AsyncAPI website project, JavaScript test files must include the .ts extension when importing TypeScript files (e.g., `require('../scripts/build-rss.ts')`). This is enforced by the project's configuration which uses `moduleResolution: "bundler"` in tsconfig.json and TypeScript-aware ESLint plugins. The .ts extensions are required even though the files are imported using CommonJS require statements.

Applied to files:

  • tests/integration/build-adopters-list-runner.int.test.ts
  • tests/build-meetings.test.ts
  • npm/runners/build-pages-runner.ts
  • tests/adopters/index.test.ts
  • tests/build-rss.test.ts
  • tests/integration/build-newsroom-videos-runner.int.test.ts
  • tests/integration/compose-blog-runner.int.test.ts
  • tests/integration/helpers/build-pages-lock.ts
  • tests/integration/helpers/file-utils.ts
  • jest.config.js
  • tests/integration/case-studies-runner.int.test.ts
  • tests/integration/build-pages-runner.int.test.ts
  • package.json
  • tests/integration/build-post-list.int.test.ts
📚 Learning: 2024-11-10T18:16:22.273Z
Learnt from: vishvamsinh28
Repo: asyncapi/website PR: 3284
File: scripts/build-post-list.js:49-53
Timestamp: 2024-11-10T18:16:22.273Z
Learning: In `scripts/build-post-list.js`, the `walkDirectories` function depends on sequential execution because it mutates `resultObj`. Parallelizing the loop with `Promise.all` causes tests to fail.

Applied to files:

  • tests/integration/build-adopters-list-runner.int.test.ts
  • tests/index.test.ts
  • tests/build-meetings.test.ts
  • npm/runners/build-post-list-runner.ts
  • tests/markdown/check-edit-links.test.ts
  • npm/runners/build-pages-runner.ts
  • scripts/adopters/index.ts
  • tests/adopters/index.test.ts
  • tests/integration/build-finance-info-list-runner.int.test.ts
  • tests/integration/build-newsroom-videos-runner.int.test.ts
  • tests/integration/compose-blog-runner.int.test.ts
  • npm/runners/build-adopters-list-runner.ts
  • tests/integration/helpers/build-pages-lock.ts
  • scripts/index.ts
  • tests/integration/build-tools.int.test.ts
  • tests/integration/case-studies-runner.int.test.ts
  • tests/integration/build-pages-runner.int.test.ts
  • tests/integration/build-meetings-runner.int.test.ts
  • tests/integration/build-post-list.int.test.ts
📚 Learning: 2024-11-29T19:42:31.175Z
Learnt from: akshatnema
Repo: asyncapi/website PR: 3265
File: scripts/tools/tools-object.js:93-98
Timestamp: 2024-11-29T19:42:31.175Z
Learning: In `scripts/tools/tools-object.js`, when validation fails in the `convertTools` function, errors should be thrown or rejected instead of only logging them, to ensure proper error propagation and handling.

Applied to files:

  • tests/integration/build-adopters-list-runner.int.test.ts
  • tests/check-locales.test.ts
  • tests/integration/build-tools.int.test.ts
  • tests/integration/case-studies-runner.int.test.ts
  • tests/integration/build-meetings-runner.int.test.ts
📚 Learning: 2025-06-20T14:47:22.389Z
Learnt from: sagarkori143
Repo: asyncapi/website PR: 0
File: :0-0
Timestamp: 2025-06-20T14:47:22.389Z
Learning: Runner files in the npm/runners directory should follow consistent error handling patterns, throwing new Error instances with descriptive messages rather than just rethrowing caught errors.

Applied to files:

  • tests/integration/build-adopters-list-runner.int.test.ts
  • tests/markdown/check-edit-links.test.ts
  • tests/build-rss.test.ts
  • tests/integration/build-newsroom-videos-runner.int.test.ts
  • npm/runners/build-adopters-list-runner.ts
  • tests/integration/build-tools.int.test.ts
  • tests/integration/case-studies-runner.int.test.ts
  • tests/integration/build-pages-runner.int.test.ts
  • tests/integration/build-meetings-runner.int.test.ts
  • tests/integration/build-post-list.int.test.ts
📚 Learning: 2024-11-01T13:32:15.472Z
Learnt from: akshatnema
Repo: asyncapi/website PR: 3101
File: tests/fixtures/rssData.js:1-57
Timestamp: 2024-11-01T13:32:15.472Z
Learning: In the `tests/fixtures/rssData.js` file of the `asyncapi/website` project, tests for edge cases such as empty strings for title or excerpt, very long text content, international characters (UTF-8), or malformed URLs in `slug` or `cover` are not necessary because these cases will not occur.

Applied to files:

  • tests/integration/build-adopters-list-runner.int.test.ts
  • tests/markdown/check-edit-links.test.ts
  • tests/integration/build-finance-info-list-runner.int.test.ts
  • tests/integration/fixtures/tools-fixtures.ts
  • tests/build-rss.test.ts
  • tests/integration/build-newsroom-videos-runner.int.test.ts
  • tests/integration/compose-blog-runner.int.test.ts
  • tests/integration/fixtures/dashboard-fixtures.ts
  • markdown/blog/default-path-test.md
  • tests/integration/build-tools.int.test.ts
  • tests/integration/case-studies-runner.int.test.ts
  • tests/integration/build-pages-runner.int.test.ts
  • tests/integration/fixtures/nock-helpers.ts
  • tests/integration/build-dashboard.int.test.ts
  • markdown/blog/default-path-test-1763304991853.md
  • tests/integration/build-post-list.int.test.ts
📚 Learning: 2024-11-29T17:36:09.783Z
Learnt from: vishvamsinh28
Repo: asyncapi/website PR: 3378
File: tests/markdown/check-markdown.test.js:133-138
Timestamp: 2024-11-29T17:36:09.783Z
Learning: When testing the 'main' function in 'check-markdown.test.js', it's acceptable to simply ensure it doesn't throw any errors, as the functions it calls are already tested elsewhere.

Applied to files:

  • tests/integration/build-adopters-list-runner.int.test.ts
  • tests/index.test.ts
  • tests/markdown/check-edit-links.test.ts
  • tests/adopters/index.test.ts
  • tests/build-rss.test.ts
  • tests/integration/build-newsroom-videos-runner.int.test.ts
  • tests/check-locales.test.ts
  • tests/integration/compose-blog-runner.int.test.ts
  • tests/integration/build-tools.int.test.ts
  • tests/integration/case-studies-runner.int.test.ts
  • tests/integration/build-pages-runner.int.test.ts
  • tests/integration/build-dashboard.int.test.ts
  • tests/integration/build-meetings-runner.int.test.ts
  • tests/integration/build-post-list.int.test.ts
📚 Learning: 2025-06-19T13:51:27.459Z
Learnt from: sagarkori143
Repo: asyncapi/website PR: 4192
File: npm/runners/build-pages-runner.ts:7-14
Timestamp: 2025-06-19T13:51:27.459Z
Learning: In the AsyncAPI website build system, individual runner functions use try-catch blocks that rethrow errors to maintain consistent error boundaries, while the top-level orchestrator in npm/index.ts provides meaningful error logging with task-specific context using logger.error(`Error building ${taskName}:`, error). This separation of concerns allows for clean error handling at different architectural layers.

Applied to files:

  • tests/integration/build-adopters-list-runner.int.test.ts
  • npm/runners/build-post-list-runner.ts
  • tests/integration/build-newsroom-videos-runner.int.test.ts
  • npm/runners/build-adopters-list-runner.ts
  • tests/integration/build-tools.int.test.ts
  • tests/integration/case-studies-runner.int.test.ts
  • tests/integration/build-pages-runner.int.test.ts
  • npm/runners/build-dashboard-runner.ts
  • tests/integration/build-dashboard.int.test.ts
  • tests/integration/build-meetings-runner.int.test.ts
📚 Learning: 2025-01-18T08:44:43.614Z
Learnt from: akshatnema
Repo: asyncapi/website PR: 3423
File: tests/index.test.js:2-7
Timestamp: 2025-01-18T08:44:43.614Z
Learning: In JavaScript test files within the AsyncAPI website project, TypeScript file imports must include the .ts extension to avoid lint errors, even though the files being imported are JavaScript files.

Applied to files:

  • tests/build-meetings.test.ts
  • jest.config.js
📚 Learning: 2024-11-01T09:55:20.531Z
Learnt from: akshatnema
Repo: asyncapi/website PR: 3101
File: tests/build-rss.test.js:25-27
Timestamp: 2024-11-01T09:55:20.531Z
Learning: In `tests/build-rss.test.js`, replacing `jest.resetModules()` with `jest.resetAllMocks()` in the `afterEach()` block causes errors. It is necessary to use `jest.resetModules()` to reset the module registry between tests in this file.

Applied to files:

  • tests/build-meetings.test.ts
  • tests/markdown/check-edit-links.test.ts
  • tests/adopters/index.test.ts
  • tests/build-rss.test.ts
  • tests/integration/build-newsroom-videos-runner.int.test.ts
  • tests/integration/compose-blog-runner.int.test.ts
  • tests/integration/build-tools.int.test.ts
  • jest.config.js
  • tests/integration/build-pages-runner.int.test.ts
  • tests/integration/fixtures/nock-helpers.ts
  • tests/integration/build-dashboard.int.test.ts
  • tests/integration/build-meetings-runner.int.test.ts
📚 Learning: 2024-10-19T15:26:43.683Z
Learnt from: anshgoyalevil
Repo: asyncapi/website PR: 3301
File: scripts/markdown/check-markdown.js:127-128
Timestamp: 2024-10-19T15:26:43.683Z
Learning: In `scripts/markdown/check-markdown.js`, synchronous file reading with `fs.readFileSync` is necessary because the files need to be processed synchronously.

Applied to files:

  • tests/build-meetings.test.ts
📚 Learning: 2024-10-18T17:28:41.718Z
Learnt from: anshgoyalevil
Repo: asyncapi/website PR: 3301
File: scripts/markdown/check-markdown.js:0-0
Timestamp: 2024-10-18T17:28:41.718Z
Learning: In `scripts/markdown/check-markdown.js`, when processing large markdown files with recursion and loops, synchronous file reads (`fs.readFileSync`) are preferred over asynchronous reads.

Applied to files:

  • tests/build-meetings.test.ts
  • tests/markdown/check-edit-links.test.ts
📚 Learning: 2024-11-01T09:35:23.912Z
Learnt from: akshatnema
Repo: asyncapi/website PR: 3101
File: scripts/build-rss.js:4-6
Timestamp: 2024-11-01T09:35:23.912Z
Learning: Converting `getAllPosts()` to asynchronous in `scripts/build-rss.js` causes the existing build system to fail.

Applied to files:

  • npm/runners/build-post-list-runner.ts
  • tests/build-rss.test.ts
  • scripts/index.ts
  • tests/integration/build-meetings-runner.int.test.ts
  • tests/integration/build-post-list.int.test.ts
📚 Learning: 2024-11-10T18:16:35.551Z
Learnt from: vishvamsinh28
Repo: asyncapi/website PR: 3284
File: scripts/build-post-list.js:28-46
Timestamp: 2024-11-10T18:16:35.551Z
Learning: In the `scripts/build-post-list.js` JavaScript file, tests rely on the `result` object being a global variable. Moving it inside the `buildPostList` function causes tests to fail; therefore, keep `result` as a global variable.

Applied to files:

  • npm/runners/build-post-list-runner.ts
  • tests/integration/compose-blog-runner.int.test.ts
  • tests/integration/build-post-list.int.test.ts
📚 Learning: 2025-06-20T14:47:22.389Z
Learnt from: sagarkori143
Repo: asyncapi/website PR: 0
File: :0-0
Timestamp: 2025-06-20T14:47:22.389Z
Learning: The AsyncAPI website modularization PR uses Promise.allSettled for parallel execution of build tasks, which provides better performance and fault isolation compared to sequential execution.

Applied to files:

  • npm/runners/build-post-list-runner.ts
  • tests/integration/build-newsroom-videos-runner.int.test.ts
  • tests/integration/helpers/build-pages-lock.ts
  • scripts/index.ts
  • tests/integration/build-meetings-runner.int.test.ts
📚 Learning: 2025-06-19T13:49:29.796Z
Learnt from: sagarkori143
Repo: asyncapi/website PR: 4192
File: npm/runners/build-newsroom-videos-runner.ts:8-15
Timestamp: 2025-06-19T13:49:29.796Z
Learning: In the AsyncAPI website modularization project, error handling is centralized in the top-level orchestrator function (npm/index.ts) with comprehensive logging and context. Individual runner functions in npm/runners/ are kept simple and let errors propagate naturally to the centralized handler, avoiding redundant try-catch blocks that only rethrow errors.

Applied to files:

  • npm/runners/case-studies-runner.ts
  • npm/runners/build-adopters-list-runner.ts
  • tests/integration/build-tools.int.test.ts
  • tests/integration/case-studies-runner.int.test.ts
  • tests/integration/build-meetings-runner.int.test.ts
📚 Learning: 2025-01-19T04:51:41.255Z
Learnt from: anshgoyalevil
Repo: asyncapi/website PR: 3557
File: tests/fixtures/markdown/check-edit-links-data.js:3-11
Timestamp: 2025-01-19T04:51:41.255Z
Learning: In the AsyncAPI website repository, the test data in `tests/fixtures/markdown/check-edit-links-data.js` intentionally includes inconsistent paths (with and without 'docs' prefix) to verify the script's ability to normalize and handle ambiguous path structures.

Applied to files:

  • tests/markdown/check-edit-links.test.ts
  • tests/adopters/index.test.ts
  • tests/integration/fixtures/tools-fixtures.ts
  • tests/build-rss.test.ts
  • tests/integration/compose-blog-runner.int.test.ts
  • tests/integration/fixtures/dashboard-fixtures.ts
  • markdown/blog/default-path-test.md
  • tests/integration/build-tools.int.test.ts
  • tests/integration/build-pages-runner.int.test.ts
  • tests/integration/build-dashboard.int.test.ts
  • markdown/blog/default-path-test-1763304991853.md
  • tests/integration/build-post-list.int.test.ts
📚 Learning: 2025-01-14T15:12:29.840Z
Learnt from: anshgoyalevil
Repo: asyncapi/website PR: 3557
File: scripts/markdown/check-edit-links.js:83-88
Timestamp: 2025-01-14T15:12:29.840Z
Learning: In the AsyncAPI website's edit link generation logic, the `editUrls` configuration (config/edit-page-config.json) includes a fallback entry with an empty value that acts as a catch-all matcher. Therefore, `editOptions.find()` will always return a match, making null checks on the result unnecessary and untestable.

Applied to files:

  • tests/markdown/check-edit-links.test.ts
📚 Learning: 2025-01-08T15:15:00.759Z
Learnt from: anshgoyalevil
Repo: asyncapi/website PR: 3557
File: scripts/markdown/check-editlinks.js:58-59
Timestamp: 2025-01-08T15:15:00.759Z
Learning: In the AsyncAPI codebase, batch processing operations (like in the Dashboard script and check-editlinks.js) follow a sequential pattern using await in loops, which is the preferred approach for maintaining consistency across the codebase.

Applied to files:

  • tests/markdown/check-edit-links.test.ts
📚 Learning: 2025-04-20T16:05:16.482Z
Learnt from: anshgoyalevil
Repo: asyncapi/website PR: 3950
File: scripts/utils/check-locales.ts:122-129
Timestamp: 2025-04-20T16:05:16.482Z
Learning: In the AsyncAPI website project, Next.js throws errors at runtime when locale files are missing, making additional validation for missing files unnecessary in the check-locales script.

Applied to files:

  • tests/markdown/check-edit-links.test.ts
  • tests/check-locales.test.ts
  • tests/integration/build-pages-runner.int.test.ts
  • tests/integration/build-post-list.int.test.ts
📚 Learning: 2024-10-18T17:24:45.053Z
Learnt from: anshgoyalevil
Repo: asyncapi/website PR: 3301
File: scripts/markdown/check-markdown.js:0-0
Timestamp: 2024-10-18T17:24:45.053Z
Learning: In `scripts/markdown/check-markdown.js`, the script is not run in an asynchronous environment, so refactoring it to use `async/await` is unnecessary.

Applied to files:

  • tests/markdown/check-edit-links.test.ts
  • npm/runners/build-pages-runner.ts
📚 Learning: 2025-02-16T12:57:24.575Z
Learnt from: anshgoyalevil
Repo: asyncapi/website PR: 0
File: :0-0
Timestamp: 2025-02-16T12:57:24.575Z
Learning: Tests failing after dependency upgrades indicate potential breaking changes and might require code changes rather than test modifications to support newer versions.

Applied to files:

  • tests/adopters/index.test.ts
  • tests/integration/compose-blog-runner.int.test.ts
  • tests/integration/build-tools.int.test.ts
📚 Learning: 2024-12-02T05:52:49.547Z
Learnt from: akshatnema
Repo: asyncapi/website PR: 3265
File: tests/helper/toolsObjectData.js:1-18
Timestamp: 2024-12-02T05:52:49.547Z
Learning: In `tests/helper/toolsObjectData.js`, using the hard-coded repository ID directly in the URL is acceptable when creating mock data for tests, as we are not asserting anything at `REPO_ID`.

Applied to files:

  • tests/integration/fixtures/tools-fixtures.ts
  • tests/build-rss.test.ts
  • tests/integration/fixtures/dashboard-fixtures.ts
  • tests/integration/build-tools.int.test.ts
📚 Learning: 2025-03-23T12:42:49.503Z
Learnt from: anshgoyalevil
Repo: asyncapi/website PR: 3950
File: scripts/utils/check-locales.ts:138-143
Timestamp: 2025-03-23T12:42:49.503Z
Learning: For the locale validation function in check-locales.ts, the team has decided that modifying the outer scope variable 'hasErrors' inside the forEach loop is acceptable despite the ESLint warning about unsafe references in loop functions.

Applied to files:

  • tests/check-locales.test.ts
📚 Learning: 2024-11-01T11:40:51.617Z
Learnt from: akshatnema
Repo: asyncapi/website PR: 3265
File: scripts/tools/tools-object.js:49-51
Timestamp: 2024-11-01T11:40:51.617Z
Learning: In JavaScript code, prefer using a custom LogService with Winston for logging errors instead of `console.error` or ad-hoc logging.

Applied to files:

  • npm/runners/build-adopters-list-runner.ts
📚 Learning: 2025-01-03T08:14:02.138Z
Learnt from: JeelRajodiya
Repo: asyncapi/website PR: 3423
File: tests/index.test.js:2-7
Timestamp: 2025-01-03T08:14:02.138Z
Learning: The user (JeelRajodiya) has stated a preference to keep the test files in CommonJS rather than migrating them to TypeScript.

Applied to files:

  • jest.config.js
📚 Learning: 2024-12-30T11:00:42.064Z
Learnt from: JeelRajodiya
Repo: asyncapi/website PR: 3423
File: jest.config.cjs:6-7
Timestamp: 2024-12-30T11:00:42.064Z
Learning: The user only wants coverage for scripts, not for .tsx files, because the existing tests are focused on scripts.

Applied to files:

  • jest.config.js
  • package.json
  • tests/integration/build-post-list.int.test.ts
📚 Learning: 2025-01-08T15:16:27.655Z
Learnt from: anshgoyalevil
Repo: asyncapi/website PR: 3557
File: .github/workflows/check-edit-links.yml:25-29
Timestamp: 2025-01-08T15:16:27.655Z
Learning: In GitHub workflows running scripts with process.exit statements for error handling (like check-editlinks.js in asyncapi/website), avoid adding error suppression (|| true) at the workflow level as it would mask the intended error reporting mechanism.

Applied to files:

  • npm/runners/build-dashboard-runner.ts
📚 Learning: 2024-11-25T18:41:29.632Z
Learnt from: akshatnema
Repo: asyncapi/website PR: 3378
File: scripts/markdown/check-markdown.js:1-1
Timestamp: 2024-11-25T18:41:29.632Z
Learning: When updating workflows for the AsyncAPI website repository, use `.github/workflows/if-nodejs-pr-testing.yml` to include environment variables and secrets for Node.js PR testing.

Applied to files:

  • npm/runners/build-dashboard-runner.ts
📚 Learning: 2024-10-18T17:37:50.602Z
Learnt from: anshgoyalevil
Repo: asyncapi/website PR: 3301
File: scripts/markdown/check-markdown.js:31-31
Timestamp: 2024-10-18T17:37:50.602Z
Learning: In `scripts/markdown/check-markdown.js`, the `frontmatter` object cannot have a property named `hasOwnProperty`, so using `frontmatter.hasOwnProperty(attr)` is acceptable.

Applied to files:

  • tests/integration/build-post-list.int.test.ts
🪛 markdownlint-cli2 (0.18.1)
markdown/blog/default-path-test.md

21-21: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


27-27: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


33-33: Bare URL used

(MD034, no-bare-urls)


45-45: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


45-45: Bare URL used

(MD034, no-bare-urls)


46-46: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


47-47: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


49-49: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


62-62: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


68-68: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

markdown/blog/default-path-test-1763304991853.md

21-21: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


27-27: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


33-33: Bare URL used

(MD034, no-bare-urls)


45-45: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


45-45: Bare URL used

(MD034, no-bare-urls)


46-46: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


47-47: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


49-49: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


62-62: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


68-68: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gsoc This label should be used for issues or discussions related to ideas for Google Summer of Code

Projects

Status: To Be Triaged

Development

Successfully merging this pull request may close these issues.

3 participants