Skip to content

implement: pkg.pr.new preview mirror (blend PR preview → blend-rescript preview) #48

@jagguji

Description

@jagguji

Implements the "pkg.pr.new preview mirror" half of the design in #46 (comment thread has the full flow diagram and the Case 1 / Case 2 split with the .d.ts diff mechanism).

Goal

When @juspay/blend-design-system publishes a pkg.pr.new preview for an open PR, this repo automatically publishes a matching pkg.pr.new preview of @juspay/rescript-blend pinned to that blend preview. ReScript consumers wanting to test an unmerged blend PR install one URL — blend comes along transitively.

Contract

Alice opens blend PR #1400
blend preview published:
  https://pkg.pr.new/@juspay/blend-design-system@a1b2
  ↓ (automatic)
blend-rescript preview published:
  https://pkg.pr.new/juspay/blend-rescript@e5f6
  (package.json pins blend-design-system to the @a1b2 tarball URL)
  ↓
Alice's PR gets a bot comment with the single install command

The Case 1 / Case 2 optimization

Not every blend PR needs the LLM regen loop. The .d.ts diff is the signal.

Case 1 — no .d.ts change Case 2 — .d.ts changed
Trigger examples bug fix, perf, internal refactor, tests new component, prop added/renamed, new variant
Regen bindings? No (skip LLM) Yes
Pin blend to preview URL in package.json? Yes Yes
Publish blend-rescript preview? Yes Yes
Cost per blend PR ~1 min CI, no LLM several min + LLM quota

Case 1 still publishes a preview because under the "consumers never install blend directly" rule, the consumer can only reach the blend preview through a matching blend-rescript preview.

Changes required

In juspay/blend-design-system

  1. Append a notify step to ci.yml — at the end of the existing preview job that publishes via pkg.pr.new, after a successful publish:

    - name: Notify blend-rescript of preview
      if: success()
      run: |
        curl -X POST \
          -H "Authorization: token ${{ secrets.BLEND_RESCRIPT_PAT }}" \
          -H "Accept: application/vnd.github+json" \
          https://api.github.com/repos/juspay/blend-rescript/dispatches \
          -d '{"event_type":"blend-preview-published","client_payload":{"blend_sha":"'"${GITHUB_SHA}"'","pr_number":'"${{ github.event.pull_request.number }}"'}}'
  2. Reuse the BLEND_RESCRIPT_PAT secret provisioned in the stable-mirror ticket (implement: release mirror (manual workflow with two flags) #47). Same permissions, same secret.

In juspay/blend-rescript

  1. Re-install the pkg.pr.new GitHub App on juspay/blend-rescript. (Was removed in ci: remove pkg.pr.new per-PR preview publishing #44 because the preview workflow had no users; this ticket is the user.)

  2. Re-add the pkg.pr.new publish workflow, but narrowed to only run on preview branches — we do NOT want previews on every merge to main:

    # .github/workflows/pkg-pr-new.yml
    name: Publish preview to pkg.pr.new
    on:
      push:
        branches: ['preview/blend-*']
    jobs:
      preview:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
          - uses: actions/setup-node@v4
            with:
              node-version: 20
              cache: npm
          - run: npm ci
          - run: npm run build
          - run: npx pkg-pr-new publish
  3. Add .github/workflows/preview-mirror.yml triggered by repository_dispatch: blend-preview-published. Steps:

    1. Check out main.

    2. Create a new branch: preview/blend-${blend_sha}.

    3. Set package.json @juspay/blend-design-system to the pkg.pr.new tarball URL:

      npm pkg set dependencies.@juspay/blend-design-system=https://pkg.pr.new/@juspay/blend-design-system@${blend_sha}
      
    4. npm install to refresh the lockfile with the pinned preview.

    5. .d.ts diff (same as the stable-mirror workflow):

      • Copy node_modules/@juspay/blend-design-system/dist/components to /tmp/new.
      • Fetch the currently-pinned blend from the baseline (main's package.json), install in a scratch dir, copy to /tmp/baseline.
      • diff -r --brief --include='*.d.ts' /tmp/baseline /tmp/new.
    6. Case 1 (empty diff): commit only the pin bump. Log "no regen needed".

    7. Case 2 (non-empty diff): run npm run generate -- --all, gate on npx rescript format -c and npm run build. Commit pin bump + regenerated src/*.res.

    8. Push branch preview/blend-${blend_sha} to origin.

    9. The push triggers pkg-pr-new.yml above → publishes preview URL.

    10. Fetch the preview URL from the job output and post a comment on the blend PR:

      🟢 Case 1 — No binding regen needed. Install:

      npm install https://pkg.pr.new/juspay/blend-rescript@<our-sha>
      

      (Blend is pinned transitively.)

      or for Case 2:

      🟡 Case 2 — Bindings regenerated for this PR. Install:

      npm install https://pkg.pr.new/juspay/blend-rescript@<our-sha>
      
  4. Add a nightly cleanup workflow .github/workflows/preview-cleanup.yml that deletes preview/blend-* branches older than 14 days. Keeps the repo from accumulating hundreds of dead preview branches.

Decisions to lock before building

  • Post the install comment on the blend PR or the blend-rescript preview branch? I'd go blend PR — that's where the dev who opened it is watching. Needs pull-requests: write on BLEND_RESCRIPT_PAT or a separate bot token with access to comment on juspay/blend-design-system PRs.
  • What happens if the Case 2 LLM regen fails? Unlike the stable-mirror case, here a silent failure is arguably OK — the consumer can fall back to writing their binding locally (the current escape hatch). Proposal: the workflow fails, posts a comment on the blend PR saying "❌ Preview regen failed, your PR can't be tested from ReScript without manual bindings. Contact #blend-rescript." That visibility is better than a broken preview URL.
  • Run on every blend PR, or only those with a label? proposal: downstream binding preview flow for unreleased blend-design-system changes #46 initial draft had a label-based opt-in for cost control; the Case 1 short-circuit makes that unnecessary because the diff is fast and the LLM only fires on actual surface changes. Recommend running on every blend PR.
  • Cleanup cadence. 14 days feels right for preview branches, but blend PRs that sit open longer would lose their previews. Alternative: tie branch lifetime to the underlying blend PR's state (open → keep preview, closed → delete). More work, more correct.

Relationship to #47 (stable-mirror)

This ticket shares two pieces of infra with #47:

I'd implement #47 first (simpler, lower-frequency trigger, easier to validate) then this one on top.

Out of scope (tracked separately)

Estimated effort

  • blend-design-system side: 15 min (one workflow step, reuses the PAT from implement: release mirror (manual workflow with two flags) #47).
  • blend-rescript side: ~2 days — the mirror workflow, the narrowed pkg.pr.new workflow, the nightly cleanup, the bot comment on blend PRs, and testing against a real open blend PR end-to-end.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions