This is an automated email from the ASF dual-hosted git repository. imbajin pushed a commit to branch feat/oink-community-content in repository https://gitbox.apache.org/repos/asf/hugegraph-doc.git
commit a3eae85364905ba8ca7291ddd41ec3e7b85dbec8 Author: dark <[email protected]> AuthorDate: Fri Sep 4 20:13:32 2026 +0800 fix(community): verify artifact search contracts - publish a fixed bilingual query-to-route fixture\n- assert all 24 entries in generated offline indexes\n- accept minified and expanded Community artifact markup\n- refresh the checked-in roster through hardened network checks --- data/community/roster.json | 2 +- scripts/community_roster.py | 13 +++++-- scripts/fixtures/community_search_queries.json | 26 ++++++++++++++ scripts/test_community_roster.py | 48 +++++++++++++++++--------- 4 files changed, 69 insertions(+), 20 deletions(-) diff --git a/data/community/roster.json b/data/community/roster.json index ee6197891..413853d88 100644 --- a/data/community/roster.json +++ b/data/community/roster.json @@ -1,7 +1,7 @@ { "schema_version": 1, "project": "hugegraph", - "retrieved_at": "2026-09-04T11:03:16Z", + "retrieved_at": "2026-09-04T12:12:42Z", "source": { "committee": "https://whimsy.apache.org/public/committee-info.json", "projects": "https://whimsy.apache.org/public/public_ldap_projects.json", diff --git a/scripts/community_roster.py b/scripts/community_roster.py index bd12e9770..57ee72554 100644 --- a/scripts/community_roster.py +++ b/scripts/community_roster.py @@ -430,7 +430,14 @@ def validate_rendered_outputs(destination: pathlib.Path) -> None: if not path.is_file(): raise RosterError(f"rendered output is missing {relative}") rendered = path.read_text(encoding="utf-8") - if any(marker not in rendered for marker in markers): + if relative.endswith(".html"): + has_markers = all( + re.search(rf'data-community-role=(?:"{role}"|{role})(?:\s|>)', rendered) + for role in ("pmc", "committers") + ) + else: + has_markers = all(marker in rendered for marker in markers) + if not has_markers: raise RosterError(f"rendered output {relative} is missing Community markers") positions = [rendered.find(url.replace("&", "&") if relative.endswith(".html") else url) for url in urls] if any(position < 0 for position in positions) or positions != sorted(positions): @@ -487,9 +494,11 @@ def _commit_bundle(candidate: dict, candidate_avatars: dict[str, bytes]) -> None for name, avatar in sorted(candidate_avatars.items()): _validate_avatar_blob(name, avatar) destination = AVATAR_DIR / name - if destination.exists(): + if destination.exists() or destination.is_symlink(): previous = destination.read_bytes() try: + if destination.is_symlink(): + raise RosterError(f"candidate destination is a symlink: {destination}") _validate_avatar_blob(name, previous) continue except RosterError: diff --git a/scripts/fixtures/community_search_queries.json b/scripts/fixtures/community_search_queries.json new file mode 100644 index 000000000..a65cfdcb3 --- /dev/null +++ b/scripts/fixtures/community_search_queries.json @@ -0,0 +1,26 @@ +[ + {"locale": "en", "query": "HugeGraph overview", "expected_ref": "/docs/introduction/"}, + {"locale": "en", "query": "server quickstart", "expected_ref": "/docs/quickstart/hugegraph/hugegraph-server/"}, + {"locale": "en", "query": "distributed storage", "expected_ref": "/docs/quickstart/hugegraph/hugegraph-hstore/"}, + {"locale": "en", "query": "placement driver", "expected_ref": "/docs/quickstart/hugegraph/hugegraph-pd/"}, + {"locale": "en", "query": "graph computing", "expected_ref": "/docs/quickstart/computing/hugegraph-computer/"}, + {"locale": "en", "query": "bulk import", "expected_ref": "/docs/quickstart/toolchain/hugegraph-loader/"}, + {"locale": "en", "query": "graph visualization", "expected_ref": "/docs/quickstart/toolchain/hugegraph-hubble/"}, + {"locale": "en", "query": "Java client", "expected_ref": "/docs/clients/"}, + {"locale": "en", "query": "HugeGraph REST API", "expected_ref": "/docs/clients/restful-api/"}, + {"locale": "en", "query": "server config", "expected_ref": "/docs/config/config-guide/"}, + {"locale": "en", "query": "StandardAuthenticator", "expected_ref": "/docs/config/config-authentication/"}, + {"locale": "en", "query": "release artifacts", "expected_ref": "/docs/download/download/"}, + {"locale": "cn", "query": "HugeGraph 介绍", "expected_ref": "/cn/docs/introduction/"}, + {"locale": "cn", "query": "Server 快速开始", "expected_ref": "/cn/docs/quickstart/hugegraph/hugegraph-server/"}, + {"locale": "cn", "query": "分布式存储", "expected_ref": "/cn/docs/quickstart/hugegraph/hugegraph-hstore/"}, + {"locale": "cn", "query": "元数据管理", "expected_ref": "/cn/docs/quickstart/hugegraph/hugegraph-pd/"}, + {"locale": "cn", "query": "图计算", "expected_ref": "/cn/docs/quickstart/computing/hugegraph-computer/"}, + {"locale": "cn", "query": "批量导入", "expected_ref": "/cn/docs/quickstart/toolchain/hugegraph-loader/"}, + {"locale": "cn", "query": "图可视化", "expected_ref": "/cn/docs/quickstart/toolchain/hugegraph-hubble/"}, + {"locale": "cn", "query": "Java 客户端", "expected_ref": "/cn/docs/clients/"}, + {"locale": "cn", "query": "HugeGraph REST API", "expected_ref": "/cn/docs/clients/restful-api/"}, + {"locale": "cn", "query": "Server 配置", "expected_ref": "/cn/docs/config/config-guide/"}, + {"locale": "cn", "query": "权限配置", "expected_ref": "/cn/docs/config/config-authentication/"}, + {"locale": "cn", "query": "发布包", "expected_ref": "/cn/docs/download/download/"} +] diff --git a/scripts/test_community_roster.py b/scripts/test_community_roster.py index 21fc6ac20..33a9e7315 100644 --- a/scripts/test_community_roster.py +++ b/scripts/test_community_roster.py @@ -459,30 +459,44 @@ class CommunityContentContractTests(unittest.TestCase): for marker in markers: self.assertIn(marker, rendered) + def test_explicit_artifact_validator_accepts_prebuilt_site(self): + roster.validate_rendered_outputs(self.site) + result = subprocess.run( + [ + sys.executable, + "scripts/community_roster.py", + "validate", + "--warn-after-days", + "90", + "--artifact", + str(self.site), + ], + cwd=ROOT, + text=True, + capture_output=True, + ) + self.assertEqual(0, result.returncode, result.stderr) + def test_fixed_metadata_is_present_in_actual_offline_indexes(self): - relative_refs = [ - "docs/introduction/", - "docs/quickstart/hugegraph/hugegraph-server/", - "docs/quickstart/hugegraph/hugegraph-hstore/", - "docs/quickstart/hugegraph/hugegraph-pd/", - "docs/quickstart/computing/hugegraph-computer/", - "docs/quickstart/toolchain/hugegraph-loader/", - "docs/quickstart/toolchain/hugegraph-hubble/", - "docs/clients/", - "docs/clients/restful-api/", - "docs/config/config-guide/", - "docs/config/config-authentication/", - "docs/download/download/", - ] - for language, prefix in (("en", "/"), ("cn", "/cn/")): + fixture = json.loads( + (ROOT / "scripts/fixtures/community_search_queries.json").read_text(encoding="utf-8") + ) + self.assertEqual(24, len(fixture)) + self.assertEqual(24, len({(item["locale"], item["query"]) for item in fixture})) + for language in ("en", "cn"): indexes = list(self.site.glob(f"offline-search-index.{language}.*.json")) self.assertEqual(1, len(indexes)) records = {record["ref"]: record for record in json.loads(indexes[0].read_text())} - for relative in relative_refs: - ref = prefix + relative + for item in (entry for entry in fixture if entry["locale"] == language): + ref = item["expected_ref"] self.assertIn(ref, records) self.assertTrue(records[ref]["keywords"], ref) self.assertGreater(records[ref]["boost"], 1, ref) + normalized_query = item["query"].casefold() + searchable = " ".join( + [records[ref]["title"], *records[ref]["keywords"]] + ).casefold() + self.assertIn(normalized_query, searchable, ref) if __name__ == "__main__":
