Skip to content

CI: Build the website on PRs and preview it from forks - #2178

Open
vzaidman wants to merge 1 commit into
react:mainfrom
vzaidman:vzaidman/website-preview
Open

vzaidman wants to merge 1 commit into
react:mainfrom
vzaidman:vzaidman/website-preview

Conversation

@vzaidman

@vzaidman vzaidman commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Summary

The website build checks links between doc pages (onBrokenLinks, onBrokenAnchors), but it only ran as part of the deploy, when a commit landed on main. A PR that broke a link was green and then broke the deploy.

Adds preview-website.yml, which runs yarn build in website/ on PRs that touch docs/** or website/. In forks, it also runs on pushed branches and publishes each one as a preview at https://<owner>.github.io/<repo>/<branch>/, once the fork owner enables workflows and GitHub Pages from the gh-pages branch. "Export to GitHub" pushes to the author's fork by default, so exported diffs get previews too.

WEBSITE_BASE_URL overrides the website's baseUrl. The help page links use Link, so they follow it.

Adds a website-install composite action, like yarn-install, that sets up Node with the yarn cache for website/yarn.lock and installs the website's dependencies. preview-website.yml and deploy-website.yml use it, so deploy-website.yml no longer restores the yarn cache by hand. preview-website.yml also runs when the action changes.

Adds link-website-preview.yml, which waits until the preview of a PR from a fork serves the PR head, and fails the PR if it doesn't within 15 minutes. If the PR description doesn't link the preview, it adds a "## Website preview" section to its bottom, with the link and a warning that the fork owner hosts the preview, and comments that it did. It fails if the description links the preview without that exact section. It runs on pull_request_target, to get a token that can edit the PR, and never checks out PR code.

Changelog: [Internal]

Test plan

  • On a fork with the workflow on its main, in TEST ONLY: link-website-preview vzaidman/metro#10:
    • The check failed while the description linked the preview without the exact section.
    • When that link was removed, the workflow added the "## Website preview" section to the bottom of the description and posted a github-actions comment. See both on the PR.
    • A later description edit that kept the section stayed green, with no new comment.
    • pull_request_target runs the workflow from main, so it doesn't run on this PR.
  • yarn format-check passes, and the action and workflows parse as YAML.
  • FB_INTERNAL=1 WEBSITE_BASE_URL=/metro/export-D128585771/ yarn build in website/ succeeds, and the home and help page links start with that base. Without WEBSITE_BASE_URL, they start with /docs/ as before.
  • On a fork, pushed branches were built, published to gh-pages under <branch>/, and served by GitHub Pages at the preview URL, with .sha matching the pushed commit.
  • The link-website-preview.yml script, run locally with a local server and mocked API, fails when .sha is missing or from another commit. When .sha matches the PR head, it appends the section and comments if the description doesn't link the preview, passes if it includes the exact section, also with CRLF line endings, and fails if it links the preview without it.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Nov 5, 2026
@vzaidman
vzaidman force-pushed the vzaidman/website-preview branch 5 times, most recently from 6cfddc6 to 5cd964b Compare November 6, 2026 13:03
@vzaidman
vzaidman force-pushed the vzaidman/website-preview branch 9 times, most recently from 805320c to 910795d Compare November 6, 2026 20:06
@vzaidman
vzaidman marked this pull request as ready for review November 6, 2026 20:08
The website build checks links between doc pages (`onBrokenLinks`, `onBrokenAnchors`), but it only ran as part of the deploy, when a commit landed on `main`. A PR that broke a link was green and then broke the deploy.

Adds `preview-website.yml`, which runs `yarn build` in `website/` on PRs that touch `docs/**` or `website/`. In forks, it also runs on pushed branches and publishes each one as a preview at `https://<owner>.github.io/<repo>/<branch>/`, once the fork owner enables workflows and GitHub Pages from the `gh-pages` branch. "Export to GitHub" pushes to the author's fork by default, so exported diffs get previews too.

`WEBSITE_BASE_URL` overrides the website's `baseUrl`. The help page links use `Link`, so they follow it.

Adds a `website-install` composite action, like `yarn-install`, that sets up Node with the yarn cache for `website/yarn.lock` and installs the website's dependencies. `preview-website.yml` and `deploy-website.yml` use it, so `deploy-website.yml` no longer restores the yarn cache by hand. `preview-website.yml` also runs when the action changes.

Adds `link-website-preview.yml`, which waits until the preview of a PR from a fork serves the PR head, and fails the PR if it doesn't within 15 minutes. If the PR description doesn't link the preview, it adds a "## Website preview" section to its bottom, with the link and a warning that the fork owner hosts the preview, and comments that it did. It fails if the description links the preview without that exact section. It runs on `pull_request_target`, to get a token that can edit the PR, and never checks out PR code.

Changelog: [Internal]
@vzaidman
vzaidman requested review from huntie and robhogan November 6, 2026 20:08
@vzaidman
vzaidman force-pushed the vzaidman/website-preview branch from 910795d to 56ac0de Compare November 6, 2026 20:10
@vzaidman
vzaidman requested review from robhogan and removed request for robhogan November 6, 2026 20:10
@github-actions

github-actions Bot commented Nov 6, 2026

Copy link
Copy Markdown

Metro review: Changes suggested

Risk: low · Commit: 56ac0de · 3 commands run

This PR builds the website on PRs that touch docs, publishes per-branch previews from forks to gh-pages, and adds a pull_request_target workflow that links the preview from fork PR descriptions. The website and help-page changes are sound, and the pull_request_target script never checks out PR code or interpolates untrusted fields into the script. Two things should change. First, the shared gh-pages concurrency group drops intermediate branch pushes, so some previews are never published. Second, the link workflow puts a failing check on any fork PR whose owner hasn't set up Pages, which covers most external docs contributions.

Findings

  • should fix · One gh-pages concurrency group cancels pending pushes, so some branches never get a preview — .github/workflows/preview-website.yml:208 · ec3078ad

    All push runs share the group preview-website-gh-pages with cancel-in-progress: false. GitHub Actions keeps at most one pending run per concurrency group. When a new run is queued while one is in progress, any run already pending in that group is cancelled and the new one takes its place.

    Failure case: "Export to GitHub" of a stack of three diffs pushes branches A, B and C to the fork within seconds. A starts building, which takes minutes for install plus the Docusaurus build. B queues as pending, then C replaces it, so B's run is cancelled. B's preview is never published. In react/metro, link-website-preview.yml then waits 15 minutes on B's PR and fails with "Website preview not deployed", and the fork owner has to push B again. Any two pushes to different branches during one build show the same loss.

    Fix: don't serialize the whole job on one group:

    • Use a per-ref group (github.ref) so each branch builds independently, cancelling only stale runs of the same branch.
    • Make the push step tolerate concurrent writers with a retry loop: git fetch origin gh-pages && git -C gh-pages rebase FETCH_HEAD && git -C gh-pages push. This never conflicts, because each run writes only its own <branch>/ directory, plus .nojekyll, which every run creates identically.

    Alternatively, move only the push into a separate job that keeps the shared group but can't lose builds. That still drops pending runs, though, so the retry loop is the robust option.

  • should fix · Fork PRs whose owner hasn't set up Actions and Pages get a failing check after 15 minutes — .github/workflows/link-website-preview.yml:143 · 40f38b88

    The job runs on every fork PR that touches docs/** or website/**. If https://<owner>.github.io/<repo>/<branch>/.sha doesn't serve the head SHA within 90 × 10 s, it sets process.exitCode = Failure.

    Actions are disabled by default on new forks, and Pages isn't configured. So an external contributor who fixes a typo in docs/ gets a red "Website preview" check about 15 minutes later. The error asks them to set up their fork's Actions and Pages before the PR looks green. Every synchronize or edited event costs another 15 runner-minutes on react/metro. The workflow is aimed at exported diffs, whose authors control the fork, but it applies to every fork PR.

    Suggested fix: when the preview isn't live, write the setup instructions to the job summary and emit core.notice or core.warning instead of failing. Keep the hard failure for the "links the preview without the exact section" case, which is the safety check. Alternatively, limit the job to PRs whose authors have write access (author_association of MEMBER/OWNER/COLLABORATOR). This also needs a maintainer decision on whether a missing fork preview should block a PR.

Verified
  • ✅ yarn prettier --check on the 4 workflow/action files and the 2 website files (head checkout) — All matched files use Prettier code style.
  • ✅ package_manager: yarn --cwd website install --frozen-lockfile (scratch copy of head, baseUrl hardcoded to /metro/feature/x-y/)
  • ⚠️ package_manager: yarn --cwd website build (scratch copy of head) — docusaurus-plugin-internaldocs-fb needs a git (or hg) repo. The scratch copy isn't one, and initializing it required approval that this session couldn't get, so the build with a custom baseUrl wasn't checked.

Not run: I didn't build the website with a non-root WEBSITE_BASE_URL: the scratch copy needed git init, which was blocked. Instead I checked by grep that the navbar and footer use to:, the homepage uses useBaseUrl and relative image paths, and the only absolute doc link (/help in Troubleshooting.md) is an MDX link, so it follows baseUrl. I didn't run either workflow on GitHub or a fork, so the concurrency finding comes from GitHub's documented semantics, not a run. No benchmarks: the change is CI and website only. Windows doesn't apply.

Automated review by Claude. Advisory only: it never approves or blocks, and a maintainer makes the call.

@huntie huntie left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Immediate gut feedback is please make this a separate comment (can still have the h2). Editing the PR description is invasive, plus this aligns with the RN website automation already.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants