Skip to content

SDK generation on release tag fails: can't open PR with base=tag #822

@alexluong

Description

@alexluong

Summary

The "SDK generate on release tag" workflow fails on every real release because Speakeasy tries to open a PR with base=<tag>, which GitHub rejects — tags are not valid PR bases. The current workaround in PR #788 (env.GITHUB_REF = refs/heads/main) is silently ignored by the GitHub Actions runner, because GITHUB_* default env vars cannot be overridden via env:.

Evidence

Error from generate-go / Generate Target:

Error: failed to create PR: POST https://api.github.com/repos/hookdeck/outpost/pulls:
422 Validation Failed [{Resource:PullRequest Field:base Code:invalid Message:}]

Proof the env override didn't apply — Speakeasy's generated branch name:

Creating branch speakeasy-sdk-regen-refs-tags-v0.16.0-1775848605

If GITHUB_REF had been overridden to refs/heads/main, the branch would be speakeasy-sdk-regen-refs-heads-main-…. It isn't.

Root cause

speakeasy-workflow-executor-v15.yml:185-187 sets:

env:
  GITHUB_REF: ${{ inputs.pr_base_is_main == true && 'refs/heads/main' || github.ref }}
  GITHUB_REF_NAME: ${{ inputs.pr_base_is_main == true && 'main' || github.ref_name }}

Per GitHub docs: "If you try to override the value of a default environment variable named CI or GITHUB_*, the value will be ignored." The runner re-sets GITHUB_REF for every step, so Speakeasy's Docker action still receives refs/tags/<tag> from the container env, passes that as the PR base, and GitHub rejects.

PR #788 merged 2026-03-25 but was never end-to-end tested against a real release tag push.

Why we can't "just dispatch from main"

The earlier approach (#784) dispatched the workflow with ref: main, which naturally gives Speakeasy a valid PR base. #788 reverted that because it broke tag fidelity — SDK was generated from main's tree, not the tag's.

More importantly, running from main precludes releasing non-latest versions:

  • Patch / hotfix releases off an older minor line (e.g. v0.15.3 cut from release/v0.15.x) need the SDK generated from that line, not from main.
  • If main has moved past the release being cut, SDK content would reflect unreleased changes.
  • A backport release would need to target a release branch, not main, as the PR base.

So the fix needs to:

  1. Generate the SDK from the exact tag tree (whatever branch it was cut from).
  2. Allow the PR base to be a parameterizable branch (default main, but e.g. release/v0.15.x for backports).

Options to explore

  1. Script Speakeasy via CLI instead of the packaged action. Checkout tag → speakeasy run → checkout target branch → copy SDK dir → commit → gh pr create --base <target>. Full control over ref and PR base; loses some action niceties (changelog upload, code samples push, PR templating) — some can be reconstructed via CLI equivalents.
  2. Invoke Speakeasy's Docker image directly via docker run -e GITHUB_REF=…. Shell-exported env does reach child docker processes, bypassing GitHub's GITHUB_* protection. Medium complexity; brittle across Speakeasy action upgrades since we'd be replicating the action's docker invocation.
  3. Fork / upstream a base_branch input into Speakeasy's sdk-generation-action. Clean long-term fix; highest upfront cost (fork maintenance or upstream lead time).
  4. Create a transient release branch at the tag SHA (e.g. release/<tag>), dispatch with that ref, and have Speakeasy PR into it — then a follow-up step opens a PR from the release branch into the configured target branch. Avoids modifying Speakeasy but adds branch/PR churn.

Target branch should be a workflow input (e.g. main or release/v0.15.x) so the flow supports backport releases.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinginternalRelates to maintainers experience and tooling

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions