Skip to content

Sync bindings with upstream blend #2

Sync bindings with upstream blend

Sync bindings with upstream blend #2

Workflow file for this run

name: Sync bindings with upstream blend
# Two ways to run:
# 1. schedule — a daily poll checks npm for a newer STABLE
# @juspay/blend-design-system and, if found, regenerates bindings and opens a PR.
# 2. workflow_dispatch — a maintainer regenerates against a specific version on demand.
# Generation is deterministic (@juspay/rescript-bindgen) — no LLM, no secrets.
# Prerelease versions (-beta, -alpha, -rc) are refused below as a safety net.
on:
schedule:
# Daily at 03:00 UTC. Picks up a new stable blend within ~24h.
- cron: '0 3 * * *'
workflow_dispatch:
inputs:
blend_version:
description: 'Version spec to install (e.g. "latest", "1.2.3", or a pkg.pr.new URL for local testing only)'
required: false
default: 'latest'
type: string
allow_prerelease:
description: 'Allow -beta / -alpha / -rc versions. Required to cut a beta release; the merged PR publishes under the npm `beta` dist-tag (never `latest`).'
required: false
default: false
type: boolean
concurrency:
group: sync-bindings
cancel-in-progress: false
jobs:
sync:
name: Regenerate bindings
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 20
cache: npm
- name: Install dependencies
run: npm ci
# On the daily schedule, compare the latest STABLE blend on npm against the
# version this package currently targets. Skip the rest of the job (no PR)
# unless npm has something newer. Manual runs skip this gate.
- name: Check for a newer stable blend (scheduled runs)
id: poll
if: github.event_name == 'schedule'
run: |
CURRENT=$(node -p "(require('./package.json').devDependencies['@juspay/blend-design-system']||'0').replace(/^[^0-9]*/,'')")
LATEST=$(npm view @juspay/blend-design-system version) # dist-tag 'latest' is stable-only
echo "current=$CURRENT latest=$LATEST"
if [ "$CURRENT" = "$LATEST" ]; then
echo "Already on the latest stable blend ($CURRENT). Nothing to sync."
echo "proceed=false" >> $GITHUB_OUTPUT
else
echo "proceed=true" >> $GITHUB_OUTPUT
echo "spec=$LATEST" >> $GITHUB_OUTPUT
fi
# Resolve which version spec to install: the poll result on schedule,
# else the manual input.
- name: Resolve target spec
id: target
if: github.event_name != 'schedule' || steps.poll.outputs.proceed == 'true'
run: |
if [ "${{ github.event_name }}" = "schedule" ]; then
echo "spec=${{ steps.poll.outputs.spec }}" >> $GITHUB_OUTPUT
else
echo "spec=${{ inputs.blend_version }}" >> $GITHUB_OUTPUT
fi
- name: Install target blend version
if: steps.target.outputs.spec != ''
run: npm install --no-save "@juspay/blend-design-system@${{ steps.target.outputs.spec }}"
- name: Resolve installed blend version
id: blend
if: steps.target.outputs.spec != ''
run: |
V=$(node -e "process.stdout.write(JSON.parse(require('fs').readFileSync('node_modules/@juspay/blend-design-system/package.json','utf8')).version)")
echo "version=$V" >> $GITHUB_OUTPUT
echo "Resolved blend version: $V"
- name: Refuse prerelease versions (unless explicitly allowed)
if: steps.target.outputs.spec != ''
run: |
V="${{ steps.blend.outputs.version }}"
if [[ "$V" =~ -(beta|alpha|rc) ]]; then
if [[ "${{ inputs.allow_prerelease }}" != "true" ]]; then
echo "Refusing to sync against prerelease version $V."
echo "The daily/auto path only accepts stable releases."
echo "To cut a beta release, re-run this workflow with allow_prerelease=true;"
echo "the merged PR publishes under the npm 'beta' dist-tag (never 'latest')."
exit 1
else
echo "::warning::Proceeding against prerelease $V (allow_prerelease=true). On merge this publishes under the 'beta' dist-tag."
fi
fi
# Deterministic generation via @juspay/rescript-bindgen. --set-version makes
# package.json version = blend version (1:1), so the PR already carries it.
- name: Pin blend version in devDependencies
if: steps.target.outputs.spec != '' && inputs.allow_prerelease != true
run: |
V="${{ steps.blend.outputs.version }}"
node -e "const p=require('./package.json'); p.devDependencies['@juspay/blend-design-system']='$V'; require('fs').writeFileSync('./package.json', JSON.stringify(p,null,2)+'\n');"
npm install --package-lock-only
- name: Regenerate all bindings (deterministic)
if: steps.target.outputs.spec != ''
run: npm run generate -- --blend "${{ steps.blend.outputs.version }}" --set-version
- name: Build to confirm green
if: steps.target.outputs.spec != ''
run: npm run build
- name: Open PR with regenerated bindings
if: steps.target.outputs.spec != ''
uses: peter-evans/create-pull-request@v8
with:
token: ${{ secrets.GITHUB_TOKEN }}
branch: sync/blend-${{ steps.blend.outputs.version }}
title: 'chore(sync): regenerate bindings for @juspay/blend-design-system@${{ steps.blend.outputs.version }}'
commit-message: |
chore(sync): regenerate bindings for @juspay/blend-design-system@${{ steps.blend.outputs.version }}
body: |
Regenerates ReScript bindings against `@juspay/blend-design-system@${{ steps.blend.outputs.version }}`
using `@juspay/rescript-bindgen` (deterministic — same blend version always
produces byte-identical output). `package.json` version is set to match (1:1).
**Reviewer checklist**
- [ ] `npm run build` is green (CI will block if not)
- [ ] `src/_REPORT.md` shows 0 broken components; skim any flagged/loose props
- [ ] Diff looks sensible — especially prop/variant renames that could break downstream consumers
- [ ] Version = blend version (set automatically); use a `-N` suffix only for a binding-only re-release of an unchanged blend version
_${{ github.event_name == 'schedule' && 'Opened automatically by the daily poll.' || format('Triggered manually by {0} (spec {1}).', github.actor, inputs.blend_version) }}_
labels: |
automated
sync
add-paths: |
src/**
package.json
package-lock.json