Sync bindings with upstream blend #2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |