Skip to content

Commit 247da69

Browse files
committed
fix: unify all npm publish workflows into a single top-level publish-npm.yml
## Problem npm Trusted Publishing matches the `workflow_ref` OIDC claim, which is always the top-level workflow filename. npm allows only ONE trusted publisher per package. The prior migration (#57099) used `workflow_call` to route all publishes through `publish-npm.yml`, but `workflow_ref` resolves to the *caller* (e.g. `nightly.yml`), not the reusable child — so the Trusted Publisher entry for `publish-npm.yml` never matches. ## Solution Merge all three publish entry points into `publish-npm.yml` itself, triggered by all three event types: - `push.tags: v0.*` → release mode (was publish-release.yml) - `schedule + workflow_dispatch` → nightly mode (was nightly.yml) - `push.branches: main, *-stable` → bumped-packages mode (was publish-bumped-packages.yml) A `determine_mode` job inspects the trigger and sets the mode. Downstream jobs use conditional `if:` expressions to run only the relevant build/publish steps. Since `publish-npm.yml` is now always the top-level workflow, `workflow_ref` always resolves to `publish-npm.yml` ✅. ## Key design points - **No JS changes** — the publish scripts are unchanged. The build and publish still happen in the same job, on the same runner, with the same container. No artifact handoff or pack-only mode needed. - **Reusable workflow_call children are fine** — prebuild-ios-*.yml, generate-changelog.yml, etc. remain as `workflow_call` children. Only the file that calls `npm publish` must be the top-level workflow; child workflows don't affect the OIDC claim. - **Old workflow files kept as stubs** — publish-release.yml, nightly.yml, and publish-bumped-packages.yml are replaced with minimal deprecation notices so that external links/dashboards don't 404. - **`always()` + explicit result checks** — publish_react_native depends on build_android (nightly-only) and prebuild_* jobs. In release mode, build_android is skipped. The `always()` prevents cascading skips, while explicit result checks ensure we don't publish after a failed build. ## npm Trusted Publisher config (manual step) For each of the 24 packages, configure on npmjs.com: Organization: react Repository: react-native Workflow: publish-npm.yml Environment: npm-publish
1 parent 79adce3 commit 247da69

4 files changed

Lines changed: 251 additions & 307 deletions

File tree

.github/workflows/nightly.yml

Lines changed: 12 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,19 @@
1-
name: Nightly
1+
# Nightly builds are now handled by publish-npm.yml, which triggers on
2+
# the same cron schedule and supports workflow_dispatch. This file is
3+
# kept only so that links to "nightly.yml" in docs and dashboards
4+
# don't break — it does nothing on its own.
5+
name: Nightly (deprecated → publish-npm.yml)
26

37
on:
8+
# No triggers — this workflow never runs.
9+
# Nightly builds are handled by publish-npm.yml.
410
workflow_dispatch:
5-
# nightly build @ 2:15 AM UTC
6-
schedule:
7-
- cron: "15 2 * * *"
8-
9-
permissions:
10-
contents: read
1111

1212
jobs:
13-
set_release_type:
13+
redirect:
1414
runs-on: ubuntu-latest
15-
if: github.repository == 'react/react-native'
16-
outputs:
17-
RELEASE_TYPE: ${{ steps.set_release_type.outputs.RELEASE_TYPE }}
18-
env:
19-
EVENT_NAME: ${{ github.event_name }}
20-
REF: ${{ github.ref }}
2115
steps:
22-
- id: set_release_type
23-
run: |
24-
echo "Setting release type to nightly"
25-
echo "RELEASE_TYPE=nightly" >> $GITHUB_OUTPUT
26-
27-
prebuild_apple_dependencies:
28-
if: github.repository == 'react/react-native'
29-
uses: ./.github/workflows/prebuild-ios-dependencies.yml
30-
secrets: inherit
31-
32-
prebuild_react_native_core:
33-
uses: ./.github/workflows/prebuild-ios-core.yml
34-
with:
35-
use-hermes-prebuilt: true
36-
version-type: nightly
37-
secrets: inherit
38-
needs: [prebuild_apple_dependencies]
39-
40-
build_android:
41-
runs-on: ubuntu-latest
42-
if: github.repository == 'react/react-native'
43-
needs: [set_release_type]
44-
container:
45-
image: reactnativecommunity/react-native-android:latest
46-
env:
47-
TERM: "dumb"
48-
# Set the encoding to resolve a known character encoding issue with decompressing tar.gz files in containers
49-
# via Gradle: https://github.com/gradle/gradle/issues/23391#issuecomment-1878979127
50-
LC_ALL: C.UTF8
51-
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
52-
ORG_GRADLE_PROJECT_SIGNING_PWD: ${{ secrets.ORG_GRADLE_PROJECT_SIGNING_PWD }}
53-
ORG_GRADLE_PROJECT_SIGNING_KEY: ${{ secrets.ORG_GRADLE_PROJECT_SIGNING_KEY }}
54-
ORG_GRADLE_PROJECT_SONATYPE_USERNAME: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPE_USERNAME }}
55-
ORG_GRADLE_PROJECT_SONATYPE_PASSWORD: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPE_PASSWORD }}
56-
REACT_NATIVE_DOWNLOADS_DIR: /opt/react-native-downloads
57-
steps:
58-
- name: Checkout
59-
uses: actions/checkout@v6
60-
- name: Build Android
61-
uses: ./.github/actions/build-android
62-
with:
63-
release-type: ${{ needs.set_release_type.outputs.RELEASE_TYPE }}
64-
gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }}
65-
66-
# Delegate the actual npm publish to the shared reusable workflow so
67-
# every `npm publish` in this repo originates from one workflow file —
68-
# required because npm Trusted Publishing only accepts one
69-
# (org, repo, workflow_filename) per package.
70-
build_npm_package:
71-
needs:
72-
[
73-
set_release_type,
74-
build_android,
75-
prebuild_apple_dependencies,
76-
prebuild_react_native_core,
77-
]
78-
# The top-level `permissions: contents: read` is the ceiling for
79-
# GITHUB_TOKEN in every job here, including reusable-workflow calls.
80-
# Re-grant `id-token: write` at the job level so publish-npm.yml's
81-
# `publish-react-native` job can mint the OIDC token that npm
82-
# Trusted Publishing exchanges for a publish token.
83-
permissions:
84-
contents: read
85-
id-token: write
86-
uses: ./.github/workflows/publish-npm.yml
87-
secrets: inherit
88-
with:
89-
mode: react-native
90-
release-type: ${{ needs.set_release_type.outputs.RELEASE_TYPE }}
16+
- run: |
17+
echo "⚠️ This workflow is deprecated."
18+
echo "Nightly builds are now published by publish-npm.yml."
19+
echo "See: https://github.com/react/react-native/actions/workflows/publish-npm.yml"
Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
name: Publish Bumped Packages
1+
# Bumped-package publishing is now handled by publish-npm.yml, which
2+
# triggers on pushes to main and *-stable branches. This file is kept
3+
# only so that links to "publish-bumped-packages.yml" in docs and
4+
# dashboards don't break — it does nothing on its own.
5+
name: Publish Bumped Packages (deprecated → publish-npm.yml)
26

37
on:
4-
push:
5-
branches:
6-
- "main"
7-
- "*-stable"
8+
# No triggers — this workflow never runs.
9+
# Branch pushes are handled by publish-npm.yml.
10+
workflow_dispatch:
811

912
jobs:
10-
# Delegate to the shared reusable workflow so every `npm publish` in
11-
# this repo originates from one workflow file — required because npm
12-
# Trusted Publishing only accepts one (org, repo, workflow_filename)
13-
# per package.
14-
publish_bumped_packages:
15-
if: github.repository == 'react/react-native'
16-
uses: ./.github/workflows/publish-npm.yml
17-
secrets: inherit
18-
with:
19-
mode: monorepo-packages
13+
redirect:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- run: |
17+
echo "⚠️ This workflow is deprecated."
18+
echo "Bumped packages are now published by publish-npm.yml."
19+
echo "See: https://github.com/react/react-native/actions/workflows/publish-npm.yml"

0 commit comments

Comments
 (0)