* fix(ci): resolve all CI failures — unversioned integrations, test retries - Move integration docs to separate unversioned docs plugin (docs-integrations/) so new integrations don't need to be duplicated across versioned_docs - Remove integration pages from versioned_docs (v0.3, v0.4) — sidebar entries now use links instead of doc refs - Add missing title/description SEO frontmatter to autogen.md - Add retry logic (2 attempts) to test-doc-examples.sh for transient LLM timeouts - Add pytest-rerunfailures to test-api with --reruns 2 for flaky Gemini-dependent integration tests * ci: retrigger * fix: graph entity inheritance, SyncTaskBackend error propagation, fact_type test regressions - Fix observation entity inheritance in get_graph_data: the unit_entities query only fetched entities for visible observation IDs, not their source memory IDs, so the inheritance loop always found an empty entity_map - Remove error swallowing in SyncTaskBackend._execute_task so test failures surface instead of being silently logged - Wrap remaining consolidation submission call sites with try/except since consolidation is non-critical for those operations - Fix test_sync_backend test to expect errors to propagate - Remove fact_type=["world"] filter from test_document_upsert_behavior and test_mentioned_at_from_context_string (same PR #848 regression) - Remove flaky marker from consolidation test (now deterministic)
70 lines
2.6 KiB
JavaScript
70 lines
2.6 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Validates that every integration docs page has `title` and `description`
|
|
* in its frontmatter for SEO purposes.
|
|
*
|
|
* Only checks docs/sdks/integrations/ (the current/unreleased version).
|
|
* Versioned docs are frozen snapshots and checked separately on release.
|
|
*
|
|
* Run: node scripts/check-integration-seo.mjs
|
|
*/
|
|
|
|
import { readFileSync, readdirSync } from 'node:fs';
|
|
import { join, relative } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { dirname } from 'node:path';
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const integrationsDir = join(__dirname, '..', 'docs-integrations');
|
|
|
|
const IGNORED_FILES = ['_template.md', '_category_.json'];
|
|
|
|
function parseFrontmatter(content) {
|
|
if (!content.startsWith('---')) return {};
|
|
const end = content.indexOf('\n---', 3);
|
|
if (end === -1) return {};
|
|
const fm = content.slice(4, end);
|
|
const fields = {};
|
|
for (const line of fm.split('\n')) {
|
|
const match = line.match(/^(\w[\w-]*):\s*(.+)$/);
|
|
if (match) fields[match[1]] = match[2].trim();
|
|
}
|
|
return fields;
|
|
}
|
|
|
|
// ─── Main ────────────────────────────────────────────────────────────────────
|
|
|
|
const files = readdirSync(integrationsDir).filter(
|
|
f => (f.endsWith('.md') || f.endsWith('.mdx')) && !IGNORED_FILES.includes(f)
|
|
);
|
|
|
|
const violations = [];
|
|
|
|
for (const filename of files) {
|
|
const filepath = join(integrationsDir, filename);
|
|
const content = readFileSync(filepath, 'utf8');
|
|
const fm = parseFrontmatter(content);
|
|
const missing = [];
|
|
if (!fm.title) missing.push('title');
|
|
if (!fm.description) missing.push('description');
|
|
if (missing.length > 0) {
|
|
violations.push({ filename, missing });
|
|
}
|
|
}
|
|
|
|
if (violations.length > 0) {
|
|
console.error('[integration-seo] ❌ The following integration pages are missing required frontmatter:\n');
|
|
for (const { filename, missing } of violations) {
|
|
console.error(` docs-integrations/${filename} — missing: ${missing.join(', ')}`);
|
|
}
|
|
console.error('\nAll integration pages must have both `title` and `description` in their frontmatter.');
|
|
console.error('Example:\n');
|
|
console.error(' ---');
|
|
console.error(' sidebar_position: 1');
|
|
console.error(' title: "MyFramework Persistent Memory with Hindsight | Integration"');
|
|
console.error(' description: "Add long-term memory to MyFramework agents with Hindsight. ..."');
|
|
console.error(' ---');
|
|
process.exit(1);
|
|
} else {
|
|
console.log(`[integration-seo] ✅ All ${files.length} integration pages have title and description.`);
|
|
}
|