Repository: facebook/react
Pull request: [ci] Add prerelease workflows to GH actions

Stack from [ghstack](https://github.com/ezyang/ghstack) (oldest at bottom):
* #30496
* __->__ #30495

Migrates the last 2 remaining circleci jobs to GH actions. The behavior
of these workflows have been kept the same.

Overview:
- Reusable workflow `runtime_prereleases.yml` added
- Nightly workflow on cron triggers the reusable workflow with the
  current HEAD sha
- Manual workflow which can be triggered from the github UI with a
  `prerelease_commit_sha` which triggers the reusable workflow

Changed files:
filename: .github/workflows/runtime_prereleases.yml
patch: @@ -0,0 +1,49 @@
+name: (Runtime) Publish Prereleases
+
+on:
+  workflow_dispatch:
+    inputs:
+      commit_sha:
+        required: true
+        default: ''
+        type: string
+      release_channel:
+        required: true
+        type: choice
+        options:
+          - stable
+          - experimental
+      dist_tag:
+        required: true
+        type: string
+
+env:
+  TZ: /usr/share/zoneinfo/America/Los_Angeles
+
+jobs:
+  publish_prerelease:
+    name: Publish prelease (${{ inputs.release_channel }}) ${{ inputs.commit_sha }} @${{ inputs.dist_tag }}
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+      - uses: actions/setup-node@v4
+        with:
+          node-version: 18.20.1
+          cache: yarn
+          cache-dependency-path: yarn.lock
+      - name: Restore cached node_modules
+        uses: actions/cache@v4
+        id: node_modules
+        with:
+          path: "**/node_modules"
+          key: ${{ runner.arch }}-${{ runner.os }}-modules-${{ hashFiles('yarn.lock', 'scripts/release/yarn.lock') }}
+      - run: yarn install --frozen-lockfile
+      - run: yarn install --frozen-lockfile
+        working-directory: scripts/release
+      - run: |
+          scripts/release/prepare-release-from-ci.js --skipTests -r ${{ inputs.release_channel }} --commit=${{ inputs.commit_sha }}
+          cp ./scripts/release/ci-npmrc ~/.npmrc
+          scripts/release/publish.js --ci --tags ${{ inputs.dist_tag }}
+        env:
+          GH_TOKEN: ${{ github.token }}
+          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

filename: .github/workflows/runtime_prereleases_manual.yml
patch: @@ -0,0 +1,43 @@
+name: (Runtime) Publish Prereleases Manual
+
+on:
+  workflow_dispatch:
+    inputs:
+      prerelease_commit_sha:
+        required: true
+
+env:
+  TZ: /usr/share/zoneinfo/America/Los_Angeles
+
+jobs:
+
+  publish_prerelease_canary:
+    name: Publish to Canary channel
+    uses: facebook/react/.github/workflows/runtime_prereleases.yml@main
+    with:
+      commit_sha: ${{ inputs.prerelease_commit_sha }}
+      release_channel: stable
+      # The tags to use when publishing canaries. The main one we should
+      # always include is "canary" but we can use multiple (e.g. alpha,
+      # beta, rc). To declare multiple, use a comma-separated string, like
+      # this:
+      #   dist_tag: "canary,alpha,beta,rc"
+      #
+      # TODO: We currently tag canaries with "next" in addition to "canary"
+      # because this used to be called the "next" channel and some
+      # downstream consumers might still expect that tag. We can remove this
+      # after some time has elapsed and the change has been communicated.
+      dist_tag: canary,next,rc
+
+  publish_prerelease_experimental:
+    name: Publish to Experimental channel
+    uses: facebook/react/.github/workflows/runtime_prereleases.yml@main
+    # NOTE: Intentionally running these jobs sequentially because npm
+    # will sometimes fail if you try to concurrently publish two
+    # different versions of the same package, even if they use different
+    # dist tags.
+    needs: publish_prerelease_canary
+    with:
+      commit_sha: ${{ inputs.prerelease_commit_sha }}
+      release_channel: experimental
+      dist_tag: experimental

filename: .github/workflows/runtime_prereleases_nightly.yml
patch: @@ -0,0 +1,35 @@
+name: (Runtime) Publish Prereleases Nightly
+
+on:
+  schedule:
+    # At 10 minutes past 16:00 on Mon, Tue, Wed, Thu, and Fri
+    - cron: 10 16 * * 1,2,3,4,5
+  workflow_dispatch:
+    inputs:
+      prerelease_commit_sha:
+        required: false
+
+env:
+  TZ: /usr/share/zoneinfo/America/Los_Angeles
+
+jobs:
+  publish_prerelease_canary:
+    name: Publish to Canary channel
+    uses: facebook/react/.github/workflows/runtime_prereleases.yml@main
+    with:
+      commit_sha: ${{ github.sha }}
+      release_channel: stable
+      dist_tag: canary,next,rc
+
+  publish_prerelease_experimental:
+    name: Publish to Experimental channel
+    uses: facebook/react/.github/workflows/runtime_prereleases.yml@main
+    # NOTE: Intentionally running these jobs sequentially because npm
+    # will sometimes fail if you try to concurrently publish two
+    # different versions of the same package, even if they use different
+    # dist tags.
+    needs: publish_prerelease_canary
+    with:
+      commit_sha: ${{ github.sha }}
+      release_channel: experimental
+      dist_tag: experimental