Skip to content

chore: add a rn-sdk beta release script#2141

Merged
santhoshvai merged 3 commits intofeat/callkit-telecom-integrationfrom
rn-beta-publish-cli
Feb 27, 2026
Merged

chore: add a rn-sdk beta release script#2141
santhoshvai merged 3 commits intofeat/callkit-telecom-integrationfrom
rn-beta-publish-cli

Conversation

@santhoshvai
Copy link
Member

@santhoshvai santhoshvai commented Feb 26, 2026

Summary by CodeRabbit

  • New Features

    • Adds a new calling experience package with native iOS CallKit and Android call UI, incoming/outgoing call handling, notifications, ringtones, background/headless tasks, and a keep-alive foreground service.
    • Exposes a debug audio-state log for troubleshooting.
  • Documentation

    • Ship comprehensive README and usage docs for the new calling package.
  • Chores

    • Add build/release scripts and workspace packaging; update dependencies and sample apps to opt into the new calling package.

@changeset-bot
Copy link

changeset-bot bot commented Feb 26, 2026

⚠️ No Changeset found

Latest commit: 8ba40fc

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 26, 2026

Caution

Review failed

Failed to post review comments

📝 Walkthrough

Walkthrough

Adds a new React Native Calling package (react-native-callingx) with full Android and iOS native implementations, TypeScript bindings, and integration into the SDK; removes/rewires legacy CallKeep/VoIP paths to use Callingx; updates manifests, samples, and build/release scripts including a new RN beta release script.

Changes

Cohort / File(s) Summary
Root scripts & manifests
package.json, scripts/release-rn-sdk-beta.mjs
Added release orchestration script and npm scripts for RN SDK beta and publishing @stream-io/react-native-callingx.
New package: react-native-callingx (core)
packages/react-native-callingx/package.json, project.json, babel.config.js, react-native.config.js, tsconfig*.json, .editorconfig, .gitattributes, .gitignore, .nvmrc, .watchmanconfig, README.md, LICENSE
New package scaffold, build config, metadata, docs, license, and project configuration for the Callingx RN module.
Callingx TypeScript API & utilities
packages/react-native-callingx/src/* (CallingxModule.ts, EventManager.ts, spec/*, types.ts, utils/*, index.ts, headlessTask.ts, etc.)
New public TS API, types, event manager, headless task helpers, and utilities exposing Callingx functionality to JS.
Android native: Callingx implementation
packages/react-native-callingx/android/... (build.gradle, gradle.properties, AndroidManifest.xml, src/main/java/... including CallService, CallingxModuleImpl, HeadlessTaskManager, Notification* classes, repo implementations, models, resources, package class)
New Android native module: service, notification management, call repository (Telecom + Legacy), headless tasks, intents, resources, and package/module wiring.
iOS native: Callingx implementation
packages/react-native-callingx/ios/... (Callingx.mm, CallingxImpl.swift, CallingxCall.swift, UUIDStorage.swift, VoipNotificationsManager.swift, AudioSessionManager.swift, Settings.swift, CallingxPublic.h)
New iOS native CallKit/VoIP integration, event bridging, audio session management, UUID storage, and public API surface for Callingx.
Client integration changes
packages/client/src/* (Call.ts, events/call.ts, devices/SpeakerManager.ts, types.ts)
Instrumented call lifecycle to call into globalThis.streamRNVideoSDK?.callingX (startCall/endCall), updated call manager signatures to accept ringing flag, and added Callingx-related types.
React Native SDK: callingx integration & push refactor
packages/react-native-sdk/src/utils/push/*, src/hooks/push/*, src/utils/internal/callingx/*, registerSDKGlobals.ts, CallManager.ts, index.ts, other push and keep-alive modules`
Replaced CallKeep/voip push runtime integrations with callingx-based flows: lazy loader, event setup, push handling, ongoing-call/keep-alive changes, headless task registration, and removal of legacy callkeep/voip helper modules.
React Native SDK: native/platform updates
packages/react-native-sdk/* (Android/iOS manifests, native modules, keepalive service, audio utils)
Added keep-alive foreground service and headless service components, audio state logging APIs, and updated native bridges to expose audio state log.
Dependency & package updates
packages/react-native-sdk/package.json, packages/noise-cancellation-react-native/package.json, packages/video-filters-react-native/package.json, sample apps' package.json files
Added @stream-io/react-native-callingx as optional peer/workspace dependency; bumped @stream-io/react-native-webrtc to 137.1.2; removed react-native-callkeep and react-native-voip-push-notification where applicable.
Sample apps & metro
sample-apps/**/package.json, metro.config.js, app manifests, AppDelegate.swift, and various sample source files
Wired sample apps to use react-native-callingx, updated Metro watchFolders, removed CallKeep/VoIP plugins/usages, and adjusted sample push/config code.
Tests & expo-config-plugin
packages/react-native-sdk/expo-config-plugin/src/*, __tests__/*
Updated plugin config shape (replaced nested ringingPushNotifications with top-level ringing: boolean) and removed manifest/service injection logic for CallKeep/Notifee paths; test adjustments accordingly.

Sequence Diagram

sequenceDiagram
    participant Push as Push Provider
    participant SDK as Stream Video SDK (JS)
    participant Callingx as Callingx Native Module
    participant OS as Platform (CallKit/Telecom/Notification)
    participant App as App UI / Client

    Push->>SDK: deliver incoming push (call_cid, payload)
    SDK->>Callingx: callingx.displayIncomingCall(callId, ...)
    Callingx->>OS: report incoming call (CallKit/Telecom) / post notification
    OS->>Callingx: user action (answer / reject)
    Callingx->>SDK: emit event (answerCall / endCall / audioSession)
    SDK->>App: notify app state (onNewEvent)
    App->>SDK: app-level call handling (start/stop)
    SDK->>Callingx: callingx.startCall / callingx.endCall(call, reason)
    Callingx->>OS: update call state / end call
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Poem

🐰 I hopped through code with eager nose,
New calling roots and native rows,
Threads, events, and headless beats — a song;
Calls start, calls end, the flows belong.
I hide a carrot in the changelog 🥕

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request lacks any description content, making it impossible to assess whether implementation notes, overview, or ticket references are provided per the template requirements. Add a comprehensive pull request description following the template, including an overview of changes, implementation notes, and any relevant ticket or documentation references.
Docstring Coverage ⚠️ Warning Docstring coverage is 17.55% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'chore: add a rn-sdk beta release script' is clear and directly related to the primary changes, which include adding new build and release scripts to package.json and introducing a new beta release script file.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch rn-beta-publish-cli

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
scripts/release-rn-sdk-beta.mjs (1)

391-400: Consider reusing monorepo build entrypoints in release flow.

runBuild() directly invokes per-workspace builds; using shared root scripts for RN deps/SDK reduces drift and keeps release automation aligned with existing dependency-order guarantees.

Based on learnings: Use monorepo build commands (yarn build:react-native:deps, yarn build:react-native:sdk) to ensure proper dependency ordering when working with workspace packages.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/release-rn-sdk-beta.mjs` around lines 391 - 400, runBuild currently
calls workspace-specific build scripts directly; instead, detect when
packageName corresponds to the React Native dependency or SDK workspaces and
call the monorepo-level build entrypoints to preserve dependency ordering:
inside runBuild (referencing function runBuild, parameter packageName, and the
run(...) invocation) add a conditional that maps the RN workspaces to root
commands and runs 'yarn build:react-native:deps' for the RN deps workspace and
'yarn build:react-native:sdk' for the RN SDK workspace (preserving dryRun
behavior and logging), otherwise fall back to the existing 'yarn workspace
<package> run build' path.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/release-rn-sdk-beta.mjs`:
- Around line 422-435: The verifyPublishedVersion function should retry the npm
view call with exponential backoff instead of failing immediately; wrap the
run('npm', ['view', `${packageName}@${version}`, 'version']) call in a retry
loop (e.g., 3-5 attempts) that waits increasing intervals (e.g., 1s, 2s, 4s)
between attempts and throws the existing Error only after all attempts fail,
preserve the dryRun early return and keep the same error message when ultimately
unsuccessful.
- Around line 31-37: The parser currently blindly consumes argv[i+1] for flags
'--base-ref' and '--tag' which can incorrectly pick up another flag (e.g.,
'--tag --dry-run'); update the handling in the loop that uses variables arg,
argv, i and options to validate argv[i+1] exists and does not start with '-'
before assigning to options.baseRef or options.tag, and if invalid emit a clear
error or exit (instead of consuming the flag) so callers get an actionable
message.

---

Nitpick comments:
In `@scripts/release-rn-sdk-beta.mjs`:
- Around line 391-400: runBuild currently calls workspace-specific build scripts
directly; instead, detect when packageName corresponds to the React Native
dependency or SDK workspaces and call the monorepo-level build entrypoints to
preserve dependency ordering: inside runBuild (referencing function runBuild,
parameter packageName, and the run(...) invocation) add a conditional that maps
the RN workspaces to root commands and runs 'yarn build:react-native:deps' for
the RN deps workspace and 'yarn build:react-native:sdk' for the RN SDK workspace
(preserving dryRun behavior and logging), otherwise fall back to the existing
'yarn workspace <package> run build' path.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2111607 and 3a54ab7.

📒 Files selected for processing (2)
  • package.json
  • scripts/release-rn-sdk-beta.mjs

Comment on lines +31 to +37
if (arg === '--base-ref') {
options.baseRef = argv[i + 1];
i += 1;
} else if (arg === '--tag') {
options.tag = argv[i + 1];
i += 1;
} else if (arg === '--dry-run') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Validate option values before consuming --base-ref and --tag.

If the next token is another flag (for example --tag --dry-run), it gets consumed as a value and fails later with a less actionable error.

🛠️ Proposed fix
+function readRequiredArgValue(argv, index, flag) {
+  const value = argv[index + 1];
+  if (!value || value.startsWith('-')) {
+    printHelpAndExit(1, `${flag} requires a value.`);
+  }
+  return value;
+}
+
 function parseArgs(argv) {
   const options = {
@@
   for (let i = 0; i < argv.length; i += 1) {
     const arg = argv[i];
     if (arg === '--base-ref') {
-      options.baseRef = argv[i + 1];
+      options.baseRef = readRequiredArgValue(argv, i, '--base-ref');
       i += 1;
     } else if (arg === '--tag') {
-      options.tag = argv[i + 1];
+      options.tag = readRequiredArgValue(argv, i, '--tag');
       i += 1;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/release-rn-sdk-beta.mjs` around lines 31 - 37, The parser currently
blindly consumes argv[i+1] for flags '--base-ref' and '--tag' which can
incorrectly pick up another flag (e.g., '--tag --dry-run'); update the handling
in the loop that uses variables arg, argv, i and options to validate argv[i+1]
exists and does not start with '-' before assigning to options.baseRef or
options.tag, and if invalid emit a clear error or exit (instead of consuming the
flag) so callers get an actionable message.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
scripts/release-rn-sdk-beta.mjs (3)

633-636: Hardcoded path for version.ts.

The path packages/react-native-sdk/src/version.ts is hardcoded. While this is stable and aligns with project conventions, consider deriving it from rnInfo.location for consistency:

♻️ Derive path from workspace info
       backupFile(
-        resolve(process.cwd(), 'packages/react-native-sdk/src/version.ts'),
+        resolve(process.cwd(), rnInfo.location, 'src/version.ts'),
         backups,
       );

Based on learnings: "Store generated version information in src/version.ts (auto-generated via yarn copy-version script)".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/release-rn-sdk-beta.mjs` around lines 633 - 636, Replace the
hardcoded path passed to backupFile with a path derived from rnInfo.location;
instead of resolve(process.cwd(), 'packages/react-native-sdk/src/version.ts'),
construct the version file path using path.join(rnInfo.location, 'src',
'version.ts') (or resolve(rnInfo.location, 'src', 'version.ts')) and pass that
to backupFile so it consistently uses the workspace info (keep using the same
backups variable).

463-466: Consider a more idiomatic sleep implementation.

Using Atomics.wait for synchronous sleep is functional but uncommon. An alternative using setTimeout with promisification would be more readable:

♻️ Alternative using timers/promises
+import { setTimeout as sleep } from 'node:timers/promises';
+
 // Block synchronously for simple retry backoff.
-function sleep(ms) {
-  Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
-}
+// Note: This requires making verifyPublishedVersion async
+// async function sleep(ms) { ... } or use timers/promises

If keeping synchronous execution is important, the current implementation works fine. Alternatively, child_process.spawnSync('sleep', [String(ms/1000)]) on Unix systems.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/release-rn-sdk-beta.mjs` around lines 463 - 466, Replace the
synchronous Atomics.wait sleep implementation in function sleep with an
idiomatic async/promise-based approach: change the function signature to return
a Promise and use setTimeout (or util.promisify(setTimeout)) to resolve after
ms, update callers of sleep to await it (or adapt call sites) so behavior
remains the same but code becomes more readable and non-blocking; keep the
Atomics.wait version only if synchronous blocking is explicitly required.

646-651: Consider handling process interruption signals.

If the user interrupts the script (Ctrl+C) mid-execution, the finally block may not fully execute, leaving modified package.json files. Consider adding signal handlers to ensure cleanup:

♻️ Add signal handlers for graceful cleanup
// Add near the top of main() or before try block
process.on('SIGINT', () => {
  console.log('\nInterrupted. Restoring backups...');
  if (!options.keepChanges && backups.size > 0) {
    restoreBackups(backups);
  }
  process.exit(130);
});

This ensures manifests are restored even on manual interruption.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/release-rn-sdk-beta.mjs` around lines 646 - 651, Add OS signal
handlers so restoreBackups(backups) runs on interruption: register handlers for
SIGINT and SIGTERM (near the top of main() or before the try block where backups
and options are created) that check if !options.keepChanges && backups.size > 0
then call restoreBackups(backups) and exit with appropriate code; ensure the
handlers are idempotent (no double-restore) and removed or ignored after the
normal finally/cleanup completes so normal flow and process.exit paths remain
unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@scripts/release-rn-sdk-beta.mjs`:
- Around line 633-636: Replace the hardcoded path passed to backupFile with a
path derived from rnInfo.location; instead of resolve(process.cwd(),
'packages/react-native-sdk/src/version.ts'), construct the version file path
using path.join(rnInfo.location, 'src', 'version.ts') (or
resolve(rnInfo.location, 'src', 'version.ts')) and pass that to backupFile so it
consistently uses the workspace info (keep using the same backups variable).
- Around line 463-466: Replace the synchronous Atomics.wait sleep implementation
in function sleep with an idiomatic async/promise-based approach: change the
function signature to return a Promise and use setTimeout (or
util.promisify(setTimeout)) to resolve after ms, update callers of sleep to
await it (or adapt call sites) so behavior remains the same but code becomes
more readable and non-blocking; keep the Atomics.wait version only if
synchronous blocking is explicitly required.
- Around line 646-651: Add OS signal handlers so restoreBackups(backups) runs on
interruption: register handlers for SIGINT and SIGTERM (near the top of main()
or before the try block where backups and options are created) that check if
!options.keepChanges && backups.size > 0 then call restoreBackups(backups) and
exit with appropriate code; ensure the handlers are idempotent (no
double-restore) and removed or ignored after the normal finally/cleanup
completes so normal flow and process.exit paths remain unchanged.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3a54ab7 and 23802f1.

📒 Files selected for processing (1)
  • scripts/release-rn-sdk-beta.mjs

@santhoshvai santhoshvai changed the base branch from main to feat/callkit-telecom-integration February 27, 2026 11:34
@santhoshvai santhoshvai merged commit f2f41da into feat/callkit-telecom-integration Feb 27, 2026
19 checks passed
@santhoshvai santhoshvai deleted the rn-beta-publish-cli branch February 27, 2026 11:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant