This is an automated email from the ASF dual-hosted git repository.
chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git
The following commit(s) were added to refs/heads/main by this push:
new 6374282cf docs: fix broken docs links and add fory-site check ci
(#3299)
6374282cf is described below
commit 6374282cf33ebd8a9ba4e3dbb8f806d4d1a77438
Author: Shawn Yang <[email protected]>
AuthorDate: Fri Feb 6 16:02:14 2026 +0800
docs: fix broken docs links and add fory-site check ci (#3299)
## Why?
The docs sync to `apache/fory-site` was not validated in CI, so
site-breaking docs changes could merge unnoticed. This PR adds
validation and fixes docs markup that can break the site pipeline.
## What does this PR do?
- Updates `.github/workflows/sync.yml` to:
- run sync only on `push` to `apache/fory` `main`
- trigger on docs-related path changes
- add `pull_request` and `workflow_dispatch` triggers
- Adds a new `validate_site_build` job that checks out `fory` +
`fory-site`, syncs mapped docs, and runs site lint/build.
- Adds `ci/validate_fory_site_sync.py` to:
- parse `.github/sync.yml` mappings for `apache/fory-site@main`
- sync mapped files/directories safely
- prune versioned/i18n content for faster validation
- patch Docusaurus config for a single `current` version build
- run `npm install`, `npm run lint --if-present`, and `npm run build`
- Fixes benchmark docs image tags in C++/Java/Rust docs by switching to
self-closing `<img ... />` markup for site compatibility.
## Related issues
N/A
## Does this PR introduce any user-facing change?
No runtime/API/protocol change. CI workflow and documentation-only
updates.
- [ ] Does this PR introduce any public API change?
- [ ] Does this PR introduce any binary protocol compatibility change?
## Benchmark
N/A (docs/CI only)
---
.github/workflows/ci.yml | 28 ++++++
ci/validate_fory_site_sync.py | 199 +++++++++++++++++++++++++++++++++++++++++
docs/benchmarks/cpp/README.md | 2 +-
docs/benchmarks/java/README.md | 80 ++++++++---------
docs/benchmarks/rust/README.md | 14 +--
5 files changed, 275 insertions(+), 48 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 5b35a053d..d6e4962be 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -737,3 +737,31 @@ jobs:
node-version: 20.x
- name: Check code style
run: python ./ci/run_ci.py format
+
+ validate_fory_site_build:
+ name: Validate Fory Site Build
+ runs-on: ubuntu-latest
+ if: github.repository == 'apache/fory' && (github.event_name !=
'pull_request' || !github.event.pull_request.draft)
+ steps:
+ - name: Checkout fory
+ uses: actions/checkout@v5
+ with:
+ path: fory
+
+ - name: Checkout fory-site
+ uses: actions/checkout@v5
+ with:
+ repository: apache/fory-site
+ ref: main
+ path: fory-site
+
+ - name: Set up Node.js 20.x
+ uses: actions/setup-node@v4
+ with:
+ node-version: 20.x
+ cache: npm
+ cache-dependency-path: fory-site/package-lock.json
+
+ - name: Sync files and validate site build
+ run: |
+ python3 fory/ci/validate_fory_site_sync.py fory fory-site
diff --git a/ci/validate_fory_site_sync.py b/ci/validate_fory_site_sync.py
new file mode 100644
index 000000000..cce69c041
--- /dev/null
+++ b/ci/validate_fory_site_sync.py
@@ -0,0 +1,199 @@
+#!/usr/bin/env python3
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import argparse
+import pathlib
+import re
+import shutil
+import subprocess
+import sys
+from typing import List, Tuple
+
+TARGET_REPO = "apache/fory-site@main"
+
+
+def parse_sync_mappings(sync_file: pathlib.Path) -> List[Tuple[str, str]]:
+ mappings: List[Tuple[str, str]] = []
+ source = None
+ current_target = None
+ for raw in sync_file.read_text(encoding="utf-8").splitlines():
+ no_comment = raw.split("#", 1)[0].rstrip()
+ if not no_comment.strip():
+ continue
+
+ top_level = re.match(r"^([^\s][^:]*):\s*$", no_comment)
+ if top_level:
+ current_target = top_level.group(1).strip()
+ source = None
+ continue
+
+ if current_target != TARGET_REPO:
+ continue
+
+ stripped = no_comment.strip()
+ source_match = re.match(r"^-\s*source:\s*(.+)$", stripped)
+ if source_match:
+ source = source_match.group(1).strip().strip("'\"")
+ continue
+
+ dest_match = re.match(r"^dest:\s*(.+)$", stripped)
+ if dest_match and source:
+ dest = dest_match.group(1).strip().strip("'\"")
+ mappings.append((source, dest))
+ source = None
+
+ if not mappings:
+ raise RuntimeError(f"no sync mappings found for {TARGET_REPO} in
{sync_file}")
+ return mappings
+
+
+def to_workspace_path(root: pathlib.Path, relative_path: str) -> pathlib.Path:
+ posix_path = pathlib.PurePosixPath(relative_path)
+ if posix_path.is_absolute() or ".." in posix_path.parts:
+ raise ValueError(f"invalid sync path: {relative_path}")
+ return root.joinpath(*posix_path.parts)
+
+
+def sync_files(
+ fory_root: pathlib.Path, site_root: pathlib.Path, sync_file: pathlib.Path
+) -> None:
+ for source, dest in parse_sync_mappings(sync_file):
+ src_path = to_workspace_path(fory_root, source)
+ dst_path = to_workspace_path(site_root, dest)
+ if not src_path.exists():
+ raise FileNotFoundError(f"source path does not exist: {src_path}")
+ if src_path.is_dir():
+ if dst_path.exists():
+ shutil.rmtree(dst_path)
+ shutil.copytree(src_path, dst_path)
+ else:
+ dst_path.parent.mkdir(parents=True, exist_ok=True)
+ shutil.copy2(src_path, dst_path)
+ print(f"synced {source} -> {dest}")
+
+
+def rewrite_versions_block(text: str) -> str:
+ marker = "versions:"
+ idx = text.find(marker)
+ if idx == -1:
+ return text
+
+ brace_start = text.find("{", idx)
+ if brace_start == -1:
+ return text
+
+ depth = 0
+ end = -1
+ i = brace_start
+ while i < len(text):
+ ch = text[i]
+ if ch == "{":
+ depth += 1
+ elif ch == "}":
+ depth -= 1
+ if depth == 0:
+ end = i
+ break
+ i += 1
+
+ if end == -1:
+ return text
+
+ j = end + 1
+ while j < len(text) and text[j].isspace():
+ j += 1
+ if j < len(text) and text[j] == ",":
+ j += 1
+
+ replacement = (
+ "versions: {\n"
+ " current: {\n"
+ " label: 'dev',\n"
+ " },\n"
+ " },"
+ )
+ return text[:idx] + replacement + text[j:]
+
+
+def patch_docusaurus_config(path: pathlib.Path) -> None:
+ if not path.exists():
+ return
+ text = path.read_text(encoding="utf-8")
+ text = re.sub(r"locales:\s*\[[^\]]*\]", "locales: ['en-US']", text,
count=1)
+ text = re.sub(r"lastVersion:\s*'[^']*'", "lastVersion: 'current'", text)
+ text = rewrite_versions_block(text)
+ path.write_text(text, encoding="utf-8")
+
+
+def prune_for_fast_build(site_root: pathlib.Path) -> None:
+ for directory in ("i18n", "versioned_docs", "versioned_sidebars"):
+ shutil.rmtree(site_root / directory, ignore_errors=True)
+
+ versions_json = site_root / "versions.json"
+ if versions_json.exists():
+ versions_json.write_text("[]\n", encoding="utf-8")
+
+ patch_docusaurus_config(site_root / "docusaurus.config.ts")
+ patch_docusaurus_config(site_root / "docusaurus.config.js")
+
+
+def run_site_commands(site_root: pathlib.Path) -> None:
+ for command in (
+ ("npm", "install"),
+ ("npm", "run", "lint", "--if-present"),
+ ("npm", "run", "build"),
+ ):
+ subprocess.run(command, cwd=site_root, check=True)
+
+
+def parse_args() -> argparse.Namespace:
+ parser = argparse.ArgumentParser(
+ description="Sync docs to fory-site and validate build."
+ )
+ parser.add_argument("fory_root", nargs="?", default="fory")
+ parser.add_argument("fory_site_root", nargs="?", default="fory-site")
+ return parser.parse_args()
+
+
+def main() -> int:
+ args = parse_args()
+ fory_root = pathlib.Path(args.fory_root)
+ site_root = pathlib.Path(args.fory_site_root)
+ sync_file = fory_root / ".github" / "sync.yml"
+
+ if not sync_file.is_file():
+ raise FileNotFoundError(f"sync mapping file not found: {sync_file}")
+ if not site_root.is_dir():
+ raise FileNotFoundError(f"fory-site directory not found: {site_root}")
+
+ sync_files(fory_root, site_root, sync_file)
+ prune_for_fast_build(site_root)
+ run_site_commands(site_root)
+ return 0
+
+
+if __name__ == "__main__":
+ try:
+ sys.exit(main())
+ except subprocess.CalledProcessError as exc:
+ print(
+ f"command failed with exit code {exc.returncode}: {'
'.join(exc.cmd)}",
+ file=sys.stderr,
+ )
+ sys.exit(exc.returncode)
diff --git a/docs/benchmarks/cpp/README.md b/docs/benchmarks/cpp/README.md
index a3684c5df..f64a16a71 100644
--- a/docs/benchmarks/cpp/README.md
+++ b/docs/benchmarks/cpp/README.md
@@ -27,7 +27,7 @@ python benchmark_report.py --json-file
build/benchmark_results.json --output-dir
## Benchmark Plots
<p align="center">
-<img src="throughput.png" width="90%">
+<img src="throughput.png" width="90%" />
</p>
## Benchmark Results
diff --git a/docs/benchmarks/java/README.md b/docs/benchmarks/java/README.md
index 1d2019aa8..7f987dbbb 100644
--- a/docs/benchmarks/java/README.md
+++ b/docs/benchmarks/java/README.md
@@ -70,10 +70,10 @@ The deserialization peer must have same class definition
with the serialization
No class forward/backward compatibility are supported in this mode.
<p align="center">
-<img width="24%" alt=""
src="serialization/bench_serialize_STRUCT_to_array_tps.png">
-<img width="24%" alt=""
src="serialization/bench_serialize_STRUCT2_to_array_tps.png">
-<img width="24%" alt=""
src="serialization/bench_serialize_MEDIA_CONTENT_to_array_tps.png">
-<img width="24%" alt=""
src="serialization/bench_serialize_SAMPLE_to_array_tps.png">
+<img width="24%" alt=""
src="serialization/bench_serialize_STRUCT_to_array_tps.png" />
+<img width="24%" alt=""
src="serialization/bench_serialize_STRUCT2_to_array_tps.png" />
+<img width="24%" alt=""
src="serialization/bench_serialize_MEDIA_CONTENT_to_array_tps.png" />
+<img width="24%" alt=""
src="serialization/bench_serialize_SAMPLE_to_array_tps.png" />
</p>
#### Java schema compatible serialization
@@ -82,10 +82,10 @@ The deserialization peer can have different class
definition with the serializat
Class forward/backward compatibility are supported in this mode.
<p align="center">
-<img width="24%" alt=""
src="serialization/bench_serialize_compatible_STRUCT_to_array_tps.png">
-<img width="24%" alt=""
src="serialization/bench_serialize_compatible_STRUCT2_to_array_tps.png">
-<img width="24%" alt=""
src="compatible/bench_serialize_compatible_MEDIA_CONTENT_to_array_tps.png">
-<img width="24%" alt=""
src="serialization/bench_serialize_compatible_SAMPLE_to_array_tps.png">
+<img width="24%" alt=""
src="serialization/bench_serialize_compatible_STRUCT_to_array_tps.png" />
+<img width="24%" alt=""
src="serialization/bench_serialize_compatible_STRUCT2_to_array_tps.png" />
+<img width="24%" alt=""
src="compatible/bench_serialize_compatible_MEDIA_CONTENT_to_array_tps.png" />
+<img width="24%" alt=""
src="serialization/bench_serialize_compatible_SAMPLE_to_array_tps.png" />
</p>
#### Java schema consistent deserialization
@@ -94,10 +94,10 @@ The deserialization peer must have same class definition
with the serialization
No class forward/backward compatibility are supported in this mode.
<p align="center">
-<img width="24%" alt=""
src="deserialization/bench_deserialize_STRUCT_from_array_tps.png">
-<img width="24%" alt=""
src="deserialization/bench_deserialize_STRUCT2_from_array_tps.png">
-<img width="24%" alt=""
src="deserialization/bench_deserialize_MEDIA_CONTENT_from_array_tps.png">
-<img width="24%" alt=""
src="deserialization/bench_deserialize_SAMPLE_from_array_tps.png">
+<img width="24%" alt=""
src="deserialization/bench_deserialize_STRUCT_from_array_tps.png" />
+<img width="24%" alt=""
src="deserialization/bench_deserialize_STRUCT2_from_array_tps.png" />
+<img width="24%" alt=""
src="deserialization/bench_deserialize_MEDIA_CONTENT_from_array_tps.png" />
+<img width="24%" alt=""
src="deserialization/bench_deserialize_SAMPLE_from_array_tps.png" />
</p>
#### Java schema compatible deserialization
@@ -106,10 +106,10 @@ The deserialization peer can have different class
definition with the serializat
Class forward/backward compatibility are supported in this mode.
<p align="center">
-<img width="24%" alt=""
src="deserialization/bench_deserialize_compatible_STRUCT_from_array_tps.png">
-<img width="24%" alt=""
src="deserialization/bench_deserialize_compatible_STRUCT2_from_array_tps.png">
-<img width="24%" alt=""
src="compatible/bench_deserialize_compatible_MEDIA_CONTENT_from_array_tps.png">
-<img width="24%" alt=""
src="deserialization/bench_deserialize_compatible_SAMPLE_from_array_tps.png">
+<img width="24%" alt=""
src="deserialization/bench_deserialize_compatible_STRUCT_from_array_tps.png" />
+<img width="24%" alt=""
src="deserialization/bench_deserialize_compatible_STRUCT2_from_array_tps.png" />
+<img width="24%" alt=""
src="compatible/bench_deserialize_compatible_MEDIA_CONTENT_from_array_tps.png"
/>
+<img width="24%" alt=""
src="deserialization/bench_deserialize_compatible_SAMPLE_from_array_tps.png" />
</p>
### Off-heap serialization
@@ -122,10 +122,10 @@ The deserialization peer must have same class definition
with the serialization
No class forward/backward compatibility are supported in this mode.
<p align="center">
-<img width="24%" alt=""
src="serialization/bench_serialize_STRUCT_to_directBuffer_tps.png">
-<img width="24%" alt=""
src="serialization/bench_serialize_STRUCT2_to_directBuffer_tps.png">
-<img width="24%" alt=""
src="serialization/bench_serialize_MEDIA_CONTENT_to_directBuffer_tps.png">
-<img width="24%" alt=""
src="serialization/bench_serialize_compatible_SAMPLE_to_directBuffer_tps.png">
+<img width="24%" alt=""
src="serialization/bench_serialize_STRUCT_to_directBuffer_tps.png" />
+<img width="24%" alt=""
src="serialization/bench_serialize_STRUCT2_to_directBuffer_tps.png" />
+<img width="24%" alt=""
src="serialization/bench_serialize_MEDIA_CONTENT_to_directBuffer_tps.png" />
+<img width="24%" alt=""
src="serialization/bench_serialize_compatible_SAMPLE_to_directBuffer_tps.png" />
</p>
#### Java schema compatible serialization
@@ -134,10 +134,10 @@ The deserialization peer can have different class
definition with the serializat
Class forward/backward compatibility are supported in this mode.
<p align="center">
-<img width="24%" alt=""
src="compatible/bench_serialize_compatible_STRUCT_to_directBuffer_tps.png">
-<img width="24%" alt=""
src="serialization/bench_serialize_compatible_STRUCT2_to_directBuffer_tps.png">
-<img width="24%" alt=""
src="serialization/bench_serialize_compatible_MEDIA_CONTENT_to_directBuffer_tps.png">
-<img width="24%" alt=""
src="serialization/bench_serialize_SAMPLE_to_directBuffer_tps.png">
+<img width="24%" alt=""
src="compatible/bench_serialize_compatible_STRUCT_to_directBuffer_tps.png" />
+<img width="24%" alt=""
src="serialization/bench_serialize_compatible_STRUCT2_to_directBuffer_tps.png"
/>
+<img width="24%" alt=""
src="serialization/bench_serialize_compatible_MEDIA_CONTENT_to_directBuffer_tps.png"
/>
+<img width="24%" alt=""
src="serialization/bench_serialize_SAMPLE_to_directBuffer_tps.png" />
</p>
#### Java schema consistent deserialization
@@ -146,10 +146,10 @@ The deserialization peer must have same class definition
with the serialization
No class forward/backward compatibility are supported in this mode.
<p align="center">
-<img width="24%" alt=""
src="deserialization/bench_deserialize_STRUCT_from_directBuffer_tps.png">
-<img width="24%" alt=""
src="deserialization/bench_deserialize_STRUCT2_from_directBuffer_tps.png">
-<img width="24%" alt=""
src="deserialization/bench_deserialize_MEDIA_CONTENT_from_directBuffer_tps.png">
-<img width="24%" alt=""
src="deserialization/bench_deserialize_SAMPLE_from_directBuffer_tps.png">
+<img width="24%" alt=""
src="deserialization/bench_deserialize_STRUCT_from_directBuffer_tps.png" />
+<img width="24%" alt=""
src="deserialization/bench_deserialize_STRUCT2_from_directBuffer_tps.png" />
+<img width="24%" alt=""
src="deserialization/bench_deserialize_MEDIA_CONTENT_from_directBuffer_tps.png"
/>
+<img width="24%" alt=""
src="deserialization/bench_deserialize_SAMPLE_from_directBuffer_tps.png" />
</p>
#### Java schema compatible deserialization
@@ -158,10 +158,10 @@ The deserialization peer can have different class
definition with the serializat
Class forward/backward compatibility are supported in this mode.
<p align="center">
-<img width="24%" alt=""
src="compatible/bench_deserialize_compatible_STRUCT_from_directBuffer_tps.png">
-<img width="24%" alt=""
src="deserialization/bench_deserialize_compatible_STRUCT2_from_directBuffer_tps.png">
-<img width="24%" alt=""
src="deserialization/bench_deserialize_compatible_MEDIA_CONTENT_from_directBuffer_tps.png">
-<img width="24%" alt=""
src="deserialization/bench_deserialize_compatible_SAMPLE_from_directBuffer_tps.png">
+<img width="24%" alt=""
src="compatible/bench_deserialize_compatible_STRUCT_from_directBuffer_tps.png"
/>
+<img width="24%" alt=""
src="deserialization/bench_deserialize_compatible_STRUCT2_from_directBuffer_tps.png"
/>
+<img width="24%" alt=""
src="deserialization/bench_deserialize_compatible_MEDIA_CONTENT_from_directBuffer_tps.png"
/>
+<img width="24%" alt=""
src="deserialization/bench_deserialize_compatible_SAMPLE_from_directBuffer_tps.png"
/>
</p>
### Zero-copy serialization
@@ -173,19 +173,19 @@ But if you serialize data between processes on same node
and use shared-memory,
#### Java zero-copy serialize to heap buffer
<p align="center">
-<img width="24%" alt=""
src="zerocopy/zero_copy_bench_serialize_BUFFER_to_array_tps.png">
-<img width="24%" alt=""
src="zerocopy/zero_copy_bench_serialize_BUFFER_to_directBuffer_tps.png">
-<img width="24%" alt=""
src="zerocopy/zero_copy_bench_serialize_PRIMITIVE_ARRAY_to_array_tps.png">
-<img width="24%" alt=""
src="zerocopy/zero_copy_bench_serialize_PRIMITIVE_ARRAY_to_directBuffer_tps.png">
+<img width="24%" alt=""
src="zerocopy/zero_copy_bench_serialize_BUFFER_to_array_tps.png" />
+<img width="24%" alt=""
src="zerocopy/zero_copy_bench_serialize_BUFFER_to_directBuffer_tps.png" />
+<img width="24%" alt=""
src="zerocopy/zero_copy_bench_serialize_PRIMITIVE_ARRAY_to_array_tps.png" />
+<img width="24%" alt=""
src="zerocopy/zero_copy_bench_serialize_PRIMITIVE_ARRAY_to_directBuffer_tps.png"
/>
</p>
#### Java zero-copy serialize to direct buffer
<p align="center">
-<img width="24%" alt=""
src="zerocopy/zero_copy_bench_deserialize_BUFFER_from_array_tps.png">
-<img width="24%" alt=""
src="zerocopy/zero_copy_bench_deserialize_BUFFER_from_directBuffer_tps.png">
-<img width="24%" alt=""
src="zerocopy/zero_copy_bench_deserialize_PRIMITIVE_ARRAY_from_array_tps.png">
-<img width="24%" alt=""
src="zerocopy/zero_copy_bench_deserialize_PRIMITIVE_ARRAY_from_directBuffer_tps.png">
+<img width="24%" alt=""
src="zerocopy/zero_copy_bench_deserialize_BUFFER_from_array_tps.png" />
+<img width="24%" alt=""
src="zerocopy/zero_copy_bench_deserialize_BUFFER_from_directBuffer_tps.png" />
+<img width="24%" alt=""
src="zerocopy/zero_copy_bench_deserialize_PRIMITIVE_ARRAY_from_array_tps.png" />
+<img width="24%" alt=""
src="zerocopy/zero_copy_bench_deserialize_PRIMITIVE_ARRAY_from_directBuffer_tps.png"
/>
</p>
## Benchmark Data
diff --git a/docs/benchmarks/rust/README.md b/docs/benchmarks/rust/README.md
index 9ea07ebd9..834516501 100644
--- a/docs/benchmarks/rust/README.md
+++ b/docs/benchmarks/rust/README.md
@@ -26,43 +26,43 @@ python benchmark_report.py --log-file cargo_bench.log
--output-dir=report_output
**company**
<p align="center">
-<img src="company.png" width="90%">
+<img src="company.png" width="90%" />
</p>
**ecommerce_data**
<p align="center">
-<img src="ecommerce_data.png" width="90%">
+<img src="ecommerce_data.png" width="90%" />
</p>
**person**
<p align="center">
-<img src="person.png" width="90%">
+<img src="person.png" width="90%" />
</p>
**simple_list**
<p align="center">
-<img src="simple_list.png" width="90%">
+<img src="simple_list.png" width="90%" />
</p>
**simple_map**
<p align="center">
-<img src="simple_map.png" width="90%">
+<img src="simple_map.png" width="90%" />
</p>
**simple_struct**
<p align="center">
-<img src="simple_struct.png" width="90%">
+<img src="simple_struct.png" width="90%" />
</p>
**system_data**
<p align="center">
-<img src="system_data.png" width="90%">
+<img src="system_data.png" width="90%" />
</p>
### Serialize Results
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]