Skip to content

Commit 9f674cd

Browse files
coadofacebook-github-bot
authored andcommitted
Add CI workflow for validating C++ API snapshot (#56042)
Summary: Adds CI workflow for validating whether the current C++ API snapshot is equivalent with the generated one. Changelog: [Internal] Reviewed By: cortinico Differential Revision: D95963515
1 parent 3c5bb3a commit 9f674cd

2 files changed

Lines changed: 95 additions & 6 deletions

File tree

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
name: Validate C++ API Snapshots
2+
3+
on:
4+
workflow_dispatch:
5+
pull_request:
6+
paths:
7+
- "packages/react-native/ReactCommon/**"
8+
- "packages/react-native/ReactAndroid/**"
9+
- "packages/react-native/React/**"
10+
- "packages/react-native/ReactApple/**"
11+
- "packages/react-native/Libraries/**"
12+
- "scripts/cxx-api/**"
13+
push:
14+
branches:
15+
- main
16+
- "*-stable"
17+
paths:
18+
- "packages/react-native/ReactCommon/**"
19+
- "packages/react-native/ReactAndroid/**"
20+
- "packages/react-native/React/**"
21+
- "packages/react-native/ReactApple/**"
22+
- "packages/react-native/Libraries/**"
23+
- "scripts/cxx-api/**"
24+
25+
env:
26+
DOXYGEN_VERSION: "1.16.1"
27+
28+
jobs:
29+
validate_cxx_api_snapshots:
30+
runs-on: ubuntu-latest
31+
if: github.repository == 'facebook/react-native'
32+
steps:
33+
- name: Checkout
34+
uses: actions/checkout@v6
35+
- name: Setup node.js
36+
uses: ./.github/actions/setup-node
37+
- name: Run yarn
38+
uses: ./.github/actions/yarn-install
39+
- name: Restore Doxygen cache
40+
id: cache-doxygen
41+
uses: actions/cache@v4
42+
with:
43+
path: /tmp/doxygen-${{ env.DOXYGEN_VERSION }}
44+
key: doxygen-${{ env.DOXYGEN_VERSION }}
45+
- name: Install Doxygen
46+
if: steps.cache-doxygen.outputs.cache-hit != 'true'
47+
shell: bash
48+
run: |
49+
DOXYGEN_URL="https://github.com/doxygen/doxygen/releases/download/Release_${DOXYGEN_VERSION//./_}/doxygen-${DOXYGEN_VERSION}.linux.bin.tar.gz"
50+
MAX_RETRIES=3
51+
for i in $(seq 1 $MAX_RETRIES); do
52+
echo "Attempt $i of $MAX_RETRIES: Installing Doxygen ${DOXYGEN_VERSION}..."
53+
curl -fsSL "$DOXYGEN_URL" -o /tmp/doxygen.tar.gz && \
54+
tar -xzf /tmp/doxygen.tar.gz -C /tmp && \
55+
echo "Doxygen installed successfully." && \
56+
break
57+
echo "Attempt $i failed."
58+
if [ $i -eq $MAX_RETRIES ]; then
59+
echo "All $MAX_RETRIES attempts failed."
60+
exit 1
61+
fi
62+
sleep 5
63+
done
64+
- name: Set DOXYGEN_BIN
65+
shell: bash
66+
run: echo "DOXYGEN_BIN=/tmp/doxygen-${DOXYGEN_VERSION}/bin/doxygen" >> "$GITHUB_ENV"
67+
- name: Set up Python
68+
uses: actions/setup-python@v5
69+
with:
70+
python-version: "3.12"
71+
- name: Install Python dependencies
72+
shell: bash
73+
run: pip install doxmlparser natsort pyyaml
74+
- name: Validate C++ API snapshots
75+
shell: bash
76+
continue-on-error: true
77+
run: yarn cxx-api-validate --output-dir /tmp/cxx-api-snapshots
78+
- name: Upload C++ API snapshots
79+
uses: actions/upload-artifact@v6
80+
with:
81+
name: cxx-api-snapshots
82+
path: /tmp/cxx-api-snapshots/

scripts/cxx-api/parser/__main__.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,14 @@ def run_command(
3535
"""Run a subprocess command with consistent error handling."""
3636
result = subprocess.run(cmd, **kwargs)
3737
if result.returncode != 0:
38-
if verbose:
39-
print(f"{label} finished with error: {result.stderr}")
40-
raise RuntimeError(
41-
f"{label} finished with error (exit code {result.returncode})"
42-
)
38+
error_details = [f"{label} finished with error (exit code {result.returncode})"]
39+
if hasattr(result, "stdout") and result.stdout:
40+
error_details.append(f"stdout:\n{result.stdout}")
41+
if hasattr(result, "stderr") and result.stderr:
42+
error_details.append(f"stderr:\n{result.stderr}")
43+
error_message = "\n".join(error_details)
44+
print(error_message)
45+
raise RuntimeError(error_message)
4346
elif verbose:
4447
print(f"{label} finished successfully")
4548
return result
@@ -191,6 +194,8 @@ def build_snapshots(
191194

192195
if errors:
193196
failed_views = ", ".join(name for name, _ in errors)
197+
for name, e in errors:
198+
print(f"Error generating {name}: {e}")
194199
raise RuntimeError(f"Failed to generate snapshots: {failed_views}")
195200
else:
196201
snapshot = build_snapshot_for_view(
@@ -286,7 +291,9 @@ def main():
286291

287292
with tempfile.TemporaryDirectory() as tmpdir:
288293
snapshot_output_dir = (
289-
tmpdir if args.check else args.output_dir or get_default_snapshot_dir()
294+
args.output_dir or tmpdir
295+
if args.check
296+
else args.output_dir or get_default_snapshot_dir()
290297
)
291298

292299
build_snapshots(

0 commit comments

Comments
 (0)