Skip to content

ci: automated release workflow (semantic-release + OIDC trusted publishing)#46

Open
oliverlaz wants to merge 6 commits into
masterfrom
ci/automated-release-workflow
Open

ci: automated release workflow (semantic-release + OIDC trusted publishing)#46
oliverlaz wants to merge 6 commits into
masterfrom
ci/automated-release-workflow

Conversation

@oliverlaz

@oliverlaz oliverlaz commented Jun 11, 2026

Copy link
Copy Markdown
Member

What

Adds an automated, workflow_dispatch-triggered release for @stream-io/react-native-webrtc, modeled on stream-chat-js's release.yml. Uses semantic-release for version computation, changelog, git tag, and GitHub Release, and publishes to npm via tokenless Trusted Publishing (OIDC) with automatic provenance.

Replaces the manual flow (tools/release.sh + hand-run npm publish).

Files

File Purpose
.github/workflows/release.yml Dispatch release job: dry_run input, id-token: write (OIDC), branch safety guard, npx semantic-release
.github/actions/setup-node/action.yml Composite action — Node from .nvmrc (v24) + npm ci
.releaserc.json semantic-release branches + plugin pipeline (commit-analyzer → release-notes → changelog → npm → git → github)
package.json semantic-release script + 4 devDependencies
package-lock.json synced so npm ci succeeds

Release modes

Mode How
Stable (default) dispatch from masterlatest dist-tag
Beta dispatch from beta branch → beta dist-tag (e.g. 145.1.0-beta.1)
Specific branch <major>.x maintenance branches (e.g. 137.x), selectable in the dispatch UI
Dry run dry_run: truesemantic-release --dry-run (no publish/tag/push)

⚠️ Before the first real release

  1. Configure the npm Trusted Publisher for @stream-io/react-native-webrtc on npmjs.com (Settings → Trusted Publisher → GitHub Actions → this repo + release.yml). Tokenless OIDC publish fails without it.
  2. Baseline tag — repo's stable tags are v137.x but the package is on the 145.x line. Create/push a v145.0.0 tag (or do the first 145 release the old way) so semantic-release continues from the right line.
  3. Conventional Commits going forward drive the version bumps (feat:/fix:/BREAKING CHANGE:).

⚠️ Review notes on the workflow as committed

  • GITHUB_TOKEN not passed to the Release step. semantic-release's @semantic-release/github (and the git push) read GITHUB_TOKEN/GH_TOKEN from the env, which Actions does not auto-populate. As written, the GitHub Release/commit step will likely fail with "no GitHub token specified". Recommend adding to the Release step:
        - name: Release
          env:
            GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          run: npx semantic-release ...
    (If master is branch-protected, use a bot PAT instead so the release commit can be pushed.)
  • npm version — tokenless OIDC needs npm ≥ 11.5.1. Node v24 runners ship a recent npm, but if publish fails on an old npm, add a npm install -g npm@latest step before release.

Lockfile note

package-lock.json grows by ~408 transitive packages (semantic-release's tree). Only 2 existing deps change — incidental patch bumps (cross-spawn 7.0.3→7.0.6, graceful-fs 4.2.9→4.2.10). The large deleted-line count is reshuffling of lockfileVersion-2's legacy nested dependencies block, not real dependency changes.

Test

Merge, then run the workflow from the Actions tab with dry_run: true on master to confirm the computed version + release notes without publishing.

Summary by CodeRabbit

  • New Features

    • Added an automated release workflow with semantic-release and dry-run support.
    • CI workflows updated to use the new local Node setup across platforms and updated checkout action versions.
  • Chores

    • Added release-related dev dependencies and scripts.
    • Removed stale-issue automation configuration.
  • Documentation

    • README updated with new package name, badges, and streamlined example/project sections.

Adds a workflow_dispatch-triggered release job that uses semantic-release
to publish the package to npm via tokenless Trusted Publishing (OIDC),
with automatic provenance. Supports stable (master), beta (prerelease
branch), and <major>.x maintenance releases, plus a dry-run mode.

- .github/workflows/release.yml: dispatch release job (OIDC, dry-run)
- .github/actions/setup-node: composite npm + Node-from-.nvmrc setup
- .releaserc.json: semantic-release branches and plugin pipeline
- package.json: semantic-release script + devDependencies (lockfile synced)
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds semantic-release config and a manual Release workflow that uses a new reusable Node setup composite action; updates package.json for semantic-release, switches CI workflows to the local setup action, and updates README badges and install instructions.

Changes

Release Automation and CI updates

Layer / File(s) Summary
Reusable Node setup action
.github/actions/setup-node/action.yml
Composite GitHub Action configures Node.js via actions/setup-node@v6, resolves version from .nvmrc, enables npm caching, and runs npm ci.
Semantic-release configuration
.releaserc.json
Adds semantic-release config with release branches (including beta), conventional commit analysis, custom patch rules for refactor and deps, changelog generation, npm publishing, and automated git commits for CHANGELOG and package files.
Package scripts and devDependencies
package.json
Adds format and semantic-release scripts and adds @semantic-release/changelog, @semantic-release/git, and semantic-release to devDependencies.
Release workflow
.github/workflows/release.yml
Manual Release workflow with dry_run input, OIDC and contents permissions, branch-gating, full checkout, uses local setup-node action, and runs npx semantic-release (conditionally --dry-run).
CI workflows switched to local setup action
.github/workflows/android_ci.yml, .github/workflows/ci.yml, .github/workflows/ios_ci.yml
Upgrades actions/checkout to v6, updates actions/setup-java to v5 in Android CI, and replaces inline actions/setup-node usage with the local ./.github/actions/setup-node action; removes an iOS cache restore-keys block.
README adjustments
README.md
Updates top badges and Getting Started install snippets to reference @stream-io/react-native-webrtc and removes Community and PIP sections in a later docs area.

Sequence Diagram

sequenceDiagram
  participant User
  participant GitHub as GitHub Actions
  participant Checkout as actions/checkout@v6
  participant SetupNodeAction as ./.github/actions/setup-node
  participant SemanticRelease as semantic-release
  participant GitRepo as Git repository
  participant NPM as npm registry

  User->>GitHub: Trigger workflow_dispatch (dry_run?)
  GitHub->>Checkout: Checkout full history & tags
  GitHub->>SetupNodeAction: Run setup-node composite action
  SetupNodeAction->>SetupNodeAction: Set Node from .nvmrc and npm ci
  GitHub->>SemanticRelease: Run npx semantic-release (--dry-run optional)
  SemanticRelease->>GitRepo: Update CHANGELOG and package manifests
  SemanticRelease->>NPM: Publish package
  SemanticRelease->>GitRepo: Create GitHub release
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A small hop, a tiny script in play,
I set Node up and clear the way,
Releases roll with changelog bright,
NPM sings into the night,
Happy rabbit stamps the tag—hooray!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'ci: automated release workflow (semantic-release + OIDC trusted publishing)' accurately and specifically describes the main change: introducing an automated release workflow using semantic-release and OIDC-based npm Trusted Publishing.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/automated-release-workflow

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.

semantic-release reads GITHUB_TOKEN/GH_TOKEN from the environment to create
the GitHub Release and push the changelog/version commit; Actions does not
populate it automatically.
- android_ci / ci / ios_ci: use ./.github/actions/setup-node (Node from
  .nvmrc) instead of inline setup-node@v4 pinned to 22.x; bump
  actions/checkout to v6 and actions/setup-java to v5
- remove .github/stale.yml

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (2)
.github/workflows/release.yml (1)

21-24: 💤 Low value

Consider pinning actions/checkout to a commit SHA.

Line 22 uses actions/checkout@v6 (tag-based reference). The static analysis tool flags this as unpinned, suggesting commit SHA pinning for supply-chain security (e.g., actions/checkout@<sha256>). While major-version tags are common practice, SHA pinning provides stronger immutability guarantees.

🔐 Pinning example (fetch current SHA)
#!/bin/bash
# Get the current SHA for actions/checkout@v6
gh api repos/actions/checkout/git/ref/tags/v6 --jq '.object.sha' 2>/dev/null || \
gh api repos/actions/checkout/commits/v6 --jq '.sha' 2>/dev/null || \
echo "Run: gh api repos/actions/checkout/git/matching-refs/tags/v6"

Note: The persist-credentials warning is a false positive here—semantic-release requires credentials to push the release commit.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 21 - 24, The workflow uses the
tag-based action reference "actions/checkout@v6" under the step named
"Checkout"; switch this to a pinned commit SHA for supply-chain security by
replacing the tag reference with the corresponding full commit SHA for
actions/checkout v6 (obtain the SHA via the GitHub API or gh CLI) so the step
uses an immutable reference instead of `@v6`.

Source: Linters/SAST tools

package.json (1)

3-3: ⚖️ Poor tradeoff

Baseline tag setup required before first semantic-release run.

The current version 145.0.0-alpha.8 indicates the package is mid-development. Semantic-release needs a baseline tag (e.g., v145.0.0) pushed to the repository before the first workflow run to correctly detect the current version and generate the next release. Without it, semantic-release may fail or produce an incorrect version bump.

Pre-release checklist:

  1. Decide on the baseline version (e.g., 145.0.0)
  2. Create and push the tag: git tag v145.0.0 && git push origin v145.0.0
  3. Update package.json version to match if needed
  4. Run workflow in dry-run mode first to verify

This aligns with the PR objectives' "Create/push a baseline tag" requirement.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` at line 3, The repo is missing a baseline git tag for
semantic-release given the package.json "version" field set to
"145.0.0-alpha.8"; create and push a baseline tag that matches the stable
version (e.g., git tag v145.0.0 && git push origin v145.0.0), ensure the
package.json "version" value aligns with that baseline if required, and run the
semantic-release workflow in dry-run mode first to verify detection and bumping
behavior before enabling full releases.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/release.yml:
- Around line 14-19: The branch guard in the package_release job is too
permissive because the conditional uses endsWith(github.ref_name, '.x'); update
the check to only allow numeric maintenance branches that match semantic-release
(e.g., patterns like 1.x or 1.0.x) by replacing the simple endsWith check with a
precise regex test against github.ref_name (or add a validation step in the job
that rejects non-numeric .x branches), and ensure this aligns with the branch
rules defined in .releaserc.json so only branches matching the numeric
maintenance pattern are permitted to run the release.

In @.releaserc.json:
- Around line 12-15: The releaseRules entry for scope "deps" currently overrides
type-based versioning (so commits like feat(deps): ... would be downgraded to
patch); update the releaseRules array to either narrow the rule by adding an
explicit "type" constraint (for example add "type":"chore" alongside
"scope":"deps" and "release":"patch") or remove/replace the scope-only rule and
add a comment/documentation explaining the intended behavior; target the
"releaseRules" array and the rule object with "scope":"deps" when making this
change.

---

Nitpick comments:
In @.github/workflows/release.yml:
- Around line 21-24: The workflow uses the tag-based action reference
"actions/checkout@v6" under the step named "Checkout"; switch this to a pinned
commit SHA for supply-chain security by replacing the tag reference with the
corresponding full commit SHA for actions/checkout v6 (obtain the SHA via the
GitHub API or gh CLI) so the step uses an immutable reference instead of `@v6`.

In `@package.json`:
- Line 3: The repo is missing a baseline git tag for semantic-release given the
package.json "version" field set to "145.0.0-alpha.8"; create and push a
baseline tag that matches the stable version (e.g., git tag v145.0.0 && git push
origin v145.0.0), ensure the package.json "version" value aligns with that
baseline if required, and run the semantic-release workflow in dry-run mode
first to verify detection and bumping behavior before enabling full releases.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b1400ce8-d1ab-4b05-bc80-9d98d186570a

📥 Commits

Reviewing files that changed from the base of the PR and between 6e0e888 and 98b99a2.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • .github/actions/setup-node/action.yml
  • .github/workflows/release.yml
  • .releaserc.json
  • package.json

Comment on lines +14 to +19
jobs:
package_release:
name: Release from "${{ github.ref_name }}" branch
runs-on: ubuntu-latest
# GH does not allow limiting branches in workflow_dispatch settings, so guard here.
if: ${{ inputs.dry_run || github.ref_name == 'master' || github.ref_name == 'beta' || startsWith(github.ref_name, 'release') || endsWith(github.ref_name, '.x') }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Branch guard is more permissive than semantic-release configuration.

Line 19 uses endsWith(github.ref_name, '.x'), which would allow branches like test.x or foo.x. However, .releaserc.json Line 3 expects numeric maintenance branches (1.x, 2.x, 1.0.x). This mismatch could allow releases from unintended branches.

🔒 Proposed fix to align with semantic-release branch patterns
-    if: ${{ inputs.dry_run || github.ref_name == 'master' || github.ref_name == 'beta' || startsWith(github.ref_name, 'release') || endsWith(github.ref_name, '.x') }}
+    if: ${{ inputs.dry_run || github.ref_name == 'master' || github.ref_name == 'beta' || startsWith(github.ref_name, 'release/') || contains(github.ref_name, '.x') && contains(github.ref_name, fromJSON('[0-9]')) }}

Or use a more precise regex check by adding a validation step before the release.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 14 - 19, The branch guard in the
package_release job is too permissive because the conditional uses
endsWith(github.ref_name, '.x'); update the check to only allow numeric
maintenance branches that match semantic-release (e.g., patterns like 1.x or
1.0.x) by replacing the simple endsWith check with a precise regex test against
github.ref_name (or add a validation step in the job that rejects non-numeric .x
branches), and ensure this aligns with the branch rules defined in
.releaserc.json so only branches matching the numeric maintenance pattern are
permitted to run the release.

Comment thread .releaserc.json
Comment on lines +12 to +15
"releaseRules": [
{ "type": "refactor", "release": "patch" },
{ "scope": "deps", "release": "patch" }
]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

The deps scope rule may override type-based versioning.

Line 14 matches any commit with scope deps regardless of type. This means feat(deps): add feature would trigger a patch release instead of minor, potentially violating semver expectations. Consider adding a type constraint or documenting this intentional override.

📝 Alternative configuration if type-based versioning should be preserved
         "releaseRules": [
           { "type": "refactor", "release": "patch" },
-          { "scope": "deps", "release": "patch" }
+          { "type": "chore", "scope": "deps", "release": "patch" }
         ]

Or document the current behavior if intentional.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"releaseRules": [
{ "type": "refactor", "release": "patch" },
{ "scope": "deps", "release": "patch" }
]
"releaseRules": [
{ "type": "refactor", "release": "patch" },
{ "type": "chore", "scope": "deps", "release": "patch" }
]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.releaserc.json around lines 12 - 15, The releaseRules entry for scope
"deps" currently overrides type-based versioning (so commits like feat(deps):
... would be downgraded to patch); update the releaseRules array to either
narrow the rule by adding an explicit "type" constraint (for example add
"type":"chore" alongside "scope":"deps" and "release":"patch") or remove/replace
the scope-only rule and add a comment/documentation explaining the intended
behavior; target the "releaseRules" array and the rule object with
"scope":"deps" when making this change.

The shared ./.github/actions/setup-node action already runs `npm ci`, so the
extra root-level `npm install` in ci/android_ci/ios_ci was a no-op. The
example-app installs (examples/GumTestApp/) are kept.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@README.md`:
- Line 37: Update the phrase "Real Time Communication" in README.md to the
hyphenated compound adjective "Real‑Time Communication" wherever it modifies
"Communication" (e.g., the sentence containing "provides a number of packages
which are more than useful when developing Real Time Communication
applications"); replace the unhyphenated occurrence with "Real-Time
Communication" to correct grammar.
- Line 32: The README contains the incorrect phrase "much more broader"; update
that sentence to use a correct comparative such as "much broader" or "a more
comprehensive example with backend included" to remove the double comparative.
Locate the sentence in README.md and replace "much more broader example with
backend included" with one of the suggested alternatives so the grammar is
corrected.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 04f66d05-f064-464b-82da-48fa33f241df

📥 Commits

Reviewing files that changed from the base of the PR and between 98b99a2 and 60e2b62.

📒 Files selected for processing (6)
  • .github/stale.yml
  • .github/workflows/android_ci.yml
  • .github/workflows/ci.yml
  • .github/workflows/ios_ci.yml
  • .github/workflows/release.yml
  • README.md
💤 Files with no reviewable changes (1)
  • .github/stale.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/release.yml

Comment thread README.md
## Picture-in-Picture (PIP)

This package does not include a built-in PIP implementation. PIP support is available via [`@stream-io/video-react-native-sdk`](https://github.com/GetStream/stream-video-js).
Don't worry, there are plans to include a much more broader example with backend included.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix grammatical error: "much more broader" is incorrect.

The phrase "much more broader" uses a double comparative, which is grammatically incorrect. It should be either "much broader" or "a more comprehensive".

📝 Proposed fix
-Don't worry, there are plans to include a much more broader example with backend included.
+Don't worry, there are plans to include a much broader example with backend included.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Don't worry, there are plans to include a much more broader example with backend included.
Don't worry, there are plans to include a much broader example with backend included.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` at line 32, The README contains the incorrect phrase "much more
broader"; update that sentence to use a correct comparative such as "much
broader" or "a more comprehensive example with backend included" to remove the
double comparative. Locate the sentence in README.md and replace "much more
broader example with backend included" with one of the suggested alternatives so
the grammar is corrected.

Comment thread README.md

Looking for extra functionality coverage?
The [react-native-webrtc](https://github.com/react-native-webrtc) organization provides a number of packages which are more than useful when developing Real Time Communication applications.
The [react-native-webrtc](https://github.com/react-native-webrtc) organization provides a number of packages which are more than useful when developing Real Time Communication applications.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add hyphen to compound adjective "Real Time Communication".

When "Real Time" modifies "Communication" as a compound adjective, it should be hyphenated as "Real-Time Communication" for correct English grammar.

📝 Proposed fix
-The [react-native-webrtc](https://github.com/react-native-webrtc) organization provides a number of packages which are more than useful when developing Real Time Communication applications.
+The [react-native-webrtc](https://github.com/react-native-webrtc) organization provides a number of packages which are more than useful when developing Real-Time Communication applications.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
The [react-native-webrtc](https://github.com/react-native-webrtc) organization provides a number of packages which are more than useful when developing Real Time Communication applications.
The [react-native-webrtc](https://github.com/react-native-webrtc) organization provides a number of packages which are more than useful when developing Real-Time Communication applications.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~37-~37: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...ch are more than useful when developing Real Time Communication applications.

(EN_COMPOUND_ADJECTIVE_INTERNAL)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` at line 37, Update the phrase "Real Time Communication" in
README.md to the hyphenated compound adjective "Real‑Time Communication"
wherever it modifies "Communication" (e.g., the sentence containing "provides a
number of packages which are more than useful when developing Real Time
Communication applications"); replace the unhyphenated occurrence with
"Real-Time Communication" to correct grammar.

Source: Linters/SAST tools

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.

2 participants