diff --git a/.github/actions/diff-js-api-breaking-changes/action.yml b/.github/actions/diff-js-api-breaking-changes/action.yml
new file mode 100644
index 00000000000000..c58d63e5e8edff
--- /dev/null
+++ b/.github/actions/diff-js-api-breaking-changes/action.yml
@@ -0,0 +1,23 @@
+name: diff-js-api-breaking-changes
+description: Check for breaking changes in the public React Native JS API=
+runs:
+ using: composite
+ steps:
+ - name: Fetch snapshot from PR head
+ shell: bash
+ env:
+ SCRATCH_DIR: ${{ runner.temp }}/diff-js-api-breaking-changes
+ run: |
+ mkdir $SCRATCH_DIR
+ git fetch --depth=1 origin ${{ github.event.pull_request.head.sha }}
+ git show ${{ github.event.pull_request.head.sha }}:packages/react-native/ReactNativeApi.d.ts > $SCRATCH_DIR/ReactNativeApi-after.d.ts \
+ || echo "" > $SCRATCH_DIR/ReactNativeApi.d.ts
+ - name: Run breaking change detection
+ shell: bash
+ env:
+ SCRATCH_DIR: ${{ runner.temp }}/diff-js-api-breaking-changes
+ run: |
+ node ./scripts/diff-api-snapshot \
+ ${{ github.workspace }}/packages/react-native/ReactNativeApi.d.ts \
+ $SCRATCH_DIR/ReactNativeApi-after.d.ts \
+ > $SCRATCH_DIR/output.json
diff --git a/.github/workflows/danger-pr.yml b/.github/workflows/danger-pr.yml
index 39a0e1c4922a15..06daf7ee8378c8 100644
--- a/.github/workflows/danger-pr.yml
+++ b/.github/workflows/danger-pr.yml
@@ -15,13 +15,15 @@ permissions:
jobs:
danger:
runs-on: ubuntu-latest
- if: github.repository == 'facebook/react-native'
+ if: github.repository == 'coado/react-native'
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
- name: Run yarn install
uses: ./.github/actions/yarn-install
+ - name: Run diff-js-api-breaking-changes
+ uses: ./.github/actions/diff-js-api-breaking-changes
- name: Danger
run: yarn danger ci --use-github-checks --failOnErrors
working-directory: private/react-native-bots
diff --git a/packages/react-native/ReactNativeApi.d.ts b/packages/react-native/ReactNativeApi.d.ts
new file mode 100644
index 00000000000000..86fe96261c7a23
--- /dev/null
+++ b/packages/react-native/ReactNativeApi.d.ts
@@ -0,0 +1,4 @@
+
+export interface ReactNativeApi {
+ foo: string,
+}
diff --git a/private/react-native-bots/dangerfile.js b/private/react-native-bots/dangerfile.js
index ddec0bdbc60d13..1bff20819a9709 100644
--- a/private/react-native-bots/dangerfile.js
+++ b/private/react-native-bots/dangerfile.js
@@ -11,6 +11,8 @@
'use strict';
const {danger, fail, warn} = require('danger');
+const fs = require('fs');
+const path = require('path');
const body = danger.github.pr.body?.toLowerCase() ?? '';
@@ -28,6 +30,25 @@ const isFromPhabricator = body_contains('differential revision:');
// Provides advice if a summary section is missing, or body is too short
const includesSummary = body_contains('## summary', 'summary:');
+const snapshot_output = JSON.parse(
+ fs.readFileSync(
+ path.join(
+ process.env.RUNNER_TEMP,
+ 'diff-js-api-breaking-changes/output.json',
+ ),
+ 'utf8',
+ ),
+);
+if (snapshot_output && snapshot_output.result !== 'NON_BREAKING') {
+ const title = ':exclamation: JavaScript API change detected';
+ const idea =
+ 'This PR commits an update to ReactNativeApi.d.ts, indicating a change to React Native's public JavaScript API. ' +
+ 'Please include a clear changelog message. ' +
+ 'This change will be subject to extra review.\n\n' +
+ `This change was flagged as: ${snapshot_output.result}
`;
+ warn(`${title} - ${idea}`);
+}
+
const hasNoUsefulBody =
!danger.github.pr.body || danger.github.pr.body.length < 50;
const hasTooShortAHumanSummary =