[ci] Update prerelease workflows to allow publishing specific packages (#33525)
It may be useful at times to publish only specific packages as an experimental tag. For example, if we need to cherry pick some fixes for an old release, we can first do so by creating that as an experimental release just for that package to allow for quick testing by downstream projects. Similar to .github/workflows/runtime_releases_from_npm_manual.yml I added three options (`dry`, `only_packages`, `skip_packages`) to `runtime_prereleases.yml` which both the manual and nightly workflows reuse. I also added a discord notification when the manual workflow is run.
lauren committed
Jun 13, 2025 at 14:22 UTC
d60f77a533da830613431ddef83d0eda928697ad
3 files changed
+84
-2
.github/workflows/runtime_prereleases.yml
+39
-2
@@ -17,6 +17,17 @@ on:
17
description: 'Whether to notify the team on Discord when the release fails. Useful if this workflow is called from an automation.'
18
required: false
19
type: boolean
20
+ only_packages:
21
+ description: Packages to publish (space separated)
22
+ type: string
23
+ skip_packages:
24
+ description: Packages to NOT publish (space separated)
25
+ type: string
26
+ dry:
27
+ required: true
28
+ description: Dry run instead of publish?
29
+ type: boolean
30
+ default: true
31
secrets:
32
DISCORD_WEBHOOK_URL:
33
description: 'Discord webhook URL to notify on failure. Only required if enableFailureNotification is true.'
@@ -61,10 +72,36 @@ jobs:
72
if: steps.node_modules.outputs.cache-hit != 'true'
73
- run: yarn --cwd scripts/release install --frozen-lockfile
74
if: steps.node_modules.outputs.cache-hit != 'true'
75
+ - run: cp ./scripts/release/ci-npmrc ~/.npmrc
76
- run: |
77
GH_TOKEN=${{ secrets.GH_TOKEN }} scripts/release/prepare-release-from-ci.js --skipTests -r ${{ inputs.release_channel }} --commit=${{ inputs.commit_sha }}
66
- cp ./scripts/release/ci-npmrc ~/.npmrc
67
- scripts/release/publish.js --ci --tags ${{ inputs.dist_tag }}
78
+ - name: Check prepared files
79
+ run: ls -R build/node_modules
80
+ - if: '${{ inputs.only_packages }}'
81
+ name: 'Publish ${{ inputs.only_packages }}'
82
+ run: |
83
+ scripts/release/publish.js \
84
+ --ci \
85
+ --skipTests \
86
+ --tags=${{ inputs.dist_tag }} \
87
+ --onlyPackages=${{ inputs.only_packages }} ${{ (inputs.dry && '') || '\'}}
88
+ ${{ inputs.dry && '--dry'}}
89
+ - if: '${{ inputs.skip_packages }}'
90
+ name: 'Publish all packages EXCEPT ${{ inputs.skip_packages }}'
91
+ run: |
92
+ scripts/release/publish.js \
93
+ --ci \
94
+ --skipTests \
95
+ --tags=${{ inputs.dist_tag }} \
96
+ --skipPackages=${{ inputs.skip_packages }} ${{ (inputs.dry && '') || '\'}}
97
+ ${{ inputs.dry && '--dry'}}
98
+ - if: '${{ !(inputs.skip_packages && inputs.only_packages) }}'
99
+ name: 'Publish all packages'
100
+ run: |
101
+ scripts/release/publish.js \
102
+ --ci \
103
+ --tags=${{ inputs.dist_tag }} ${{ (inputs.dry && '') || '\'}}
104
+ ${{ inputs.dry && '--dry'}}
105
- name: Notify Discord on failure
106
if: failure() && inputs.enableFailureNotification == true
107
uses: tsickert/discord-webhook@86dc739f3f165f16dadc5666051c367efa1692f4
.github/workflows/runtime_prereleases_manual.yml
+43
@@ -5,6 +5,25 @@ on:
5
inputs:
6
prerelease_commit_sha:
7
required: true
8
+ only_packages:
9
+ description: Packages to publish (space separated)
10
+ type: string
11
+ skip_packages:
12
+ description: Packages to NOT publish (space separated)
13
+ type: string
14
+ dry:
15
+ required: true
16
+ description: Dry run instead of publish?
17
+ type: boolean
18
+ default: true
19
+ experimental_only:
20
+ type: boolean
21
+ description: Only publish to the experimental tag
22
+ default: false
23
+ force_notify:
24
+ description: Force a Discord notification?
25
+ type: boolean
26
+ default: false
27
28
permissions: {}
29
@@ -12,8 +31,26 @@ env:
31
TZ: /usr/share/zoneinfo/America/Los_Angeles
32
33
jobs:
34
+ notify:
35
+ if: ${{ inputs.force_notify || inputs.dry == false || inputs.dry == 'false' }}
36
+ runs-on: ubuntu-latest
37
+ steps:
38
+ - name: Discord Webhook Action
39
+ uses: tsickert/discord-webhook@86dc739f3f165f16dadc5666051c367efa1692f4
40
+ with:
41
+ webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }}
42
+ embed-author-name: ${{ github.event.sender.login }}
43
+ embed-author-url: ${{ github.event.sender.html_url }}
44
+ embed-author-icon-url: ${{ github.event.sender.avatar_url }}
45
+ embed-title: "⚠️ Publishing ${{ inputs.experimental_only && 'EXPERIMENTAL' || 'CANARY & EXPERIMENTAL' }} release ${{ (inputs.dry && ' (dry run)') || '' }}"
46
+ embed-description: |
47
+ ```json
48
+ ${{ toJson(inputs) }}
49
+ ```
50
+ embed-url: https://github.com/facebook/react/actions/runs/${{ github.run_id }}
51
52
publish_prerelease_canary:
53
+ if: ${{ !inputs.experimental_only }}
54
name: Publish to Canary channel
55
uses: facebook/react/.github/workflows/runtime_prereleases.yml@main
56
permissions:
@@ -33,6 +70,9 @@ jobs:
70
# downstream consumers might still expect that tag. We can remove this
71
# after some time has elapsed and the change has been communicated.
72
dist_tag: canary,next
73
+ only_packages: ${{ inputs.only_packages }}
74
+ skip_packages: ${{ inputs.skip_packages }}
75
+ dry: ${{ inputs.dry }}
76
secrets:
77
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
78
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -52,6 +92,9 @@ jobs:
92
commit_sha: ${{ inputs.prerelease_commit_sha }}
93
release_channel: experimental
94
dist_tag: experimental
95
+ only_packages: ${{ inputs.only_packages }}
96
+ skip_packages: ${{ inputs.skip_packages }}
97
+ dry: ${{ inputs.dry }}
98
secrets:
99
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
100
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
.github/workflows/runtime_prereleases_nightly.yml
+2
@@ -22,6 +22,7 @@ jobs:
22
release_channel: stable
23
dist_tag: canary,next
24
enableFailureNotification: true
25
+ dry: false
26
secrets:
27
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
28
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -43,6 +44,7 @@ jobs:
44
release_channel: experimental
45
dist_tag: experimental
46
enableFailureNotification: true
47
+ dry: false
48
secrets:
49
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
50
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}