Skip to content

Trigger prototype client regeneration on API changes - #172

Open
josephschorr wants to merge 3 commits into
mainfrom
clients-prototype-regen
Open

Trigger prototype client regeneration on API changes#172
josephschorr wants to merge 3 commits into
mainfrom
clients-prototype-regen

Conversation

@josephschorr

Copy link
Copy Markdown
Member

Draft — merge last. Part 3 of 3 wiring automatic client regeneration into authzed/spicedb-clients-prototype (see that repo's PRs #58 and #59). Nothing here affects this repo's own builds; it only fires a repository_dispatch outward.

Deliberately a new filemanual-client-update.yaml and release-client-update.yaml are untouched, so the legacy five-client pipeline is unaffected and this prototype wiring is one git rm away if it's ever abandoned.

What it does

Chains off Lint and Release completing successfully, then dispatches to the prototype repo with a BUFTAG pinning the exact upstream revision:

  • api_main_updateBUFTAG is the api git SHA
  • api_release_updateBUFTAG is the release tag

Why chained off Lint rather than triggered on push

Lint is what pushes the module to the BSR. Dispatching straight from on: push races that upload, and the receiving side pins to an exact BSR ref — so losing the race means the ref doesn't exist yet. Chaining on successful completion removes the race and also ensures we never regenerate from a commit whose buf breaking-change check failed.

Two related details that are deliberate and look wrong at a glance:

  • workflow_run.head_sha, not github.sha. Under workflow_run, github.sha resolves to the default-branch head, not the triggering commit.
  • Relevance is checked in the job, not declaratively. on: workflow_run supports no paths: filter, so the proto-relevance check uses the compare API. docs/ is excluded because it holds buf-generated swagger, downstream of the protos.

Security: the trigger must reject fork-originated runs

This is the part worth reviewing closely. lint.yaml runs on pull_request for all branches, so a fork PR produces a completed Lint run — and workflow_run fires for those in the base repo with secrets. Filtering on head_branch !== 'main' does not stop it, because for a fork PR head_branch is the fork's branch name: attacker-chosen, and main by default on a fresh fork.

Without a guard, an external contributor could cause the prototype repo to spin up an 8-core runner and materialize a Claude credential into a job, repeatedly. The job therefore also requires:

github.event.workflow_run.event == 'push'
&& github.event.workflow_run.head_repository.full_name == github.repository

Both intended paths — Lint on a push to main, Release on a tag push — are same-repo push events, so nothing legitimate is lost.

Fails open on an unenumerable commit

GitHub's Get-a-commit API caps files at 300 entries and omits the field entirely for very large commits. Treating that as "no relevant files" would skip the dispatch with a green job and no error anywhere — leaving clients silently stale, the exact failure this design exists to prevent. When the list can't be fully enumerated the workflow dispatches anyway and logs why: a needless regeneration finds no proto diff and opens no PR, while a missed one is invisible.

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown

The latest Buf updates on your PR. Results from workflow Lint / lint (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedAug 26, 2026, 10:54 PM

@josephschorr
josephschorr marked this pull request as ready for review August 26, 2026 22:54

@tstirrat15 tstirrat15 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants