juspay / juspay/blend-rescript
implement: pkg.pr.new preview mirror (blend PR preview → blend-rescript preview)
- Dominant language
- ReScript
- Stars
- 1
- Forks
- 0
- Avg merge
- 2h 48m
- Merged PRs (30d)
- 4
Description
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:
```yaml
- 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 (#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 #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:
```yaml
# .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@
> ```
> (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@
> ```
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?** #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:
- The `BLEND_RESCRIPT_PAT` secret (provisioned once in #47, reused here).
- The `.d.ts` diff logic (extract into a shared reusable workflow or a script under `scripts/` so both `release-mirror.yml` and `preview-mirror.yml` can call it).
I'd implement #47 first (simpler, lower-frequency trigger, easier to validate) then this one on top.
## Out of scope (tracked separately)
- Stable release mirror: #47.
- Old `@subham_/` scope migration for existing consumers: blocks on #5.
## Estimated effort
- blend-design-system side: 15 min (one workflow step, reuses the PAT from #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.
Contributor guide
Assessment
This issue has not been assessed yet.