Bug Description
In PR mode, FindExistingPR() in internal/git/git.go uses strings.HasPrefix to match PR titles. When the workflow runs on the main branch, the search pattern has no branch qualifier suffix, causing it to greedily match PRs created from other branches.
Steps to Reproduce
- Configure
sdk_generation.yaml with mode: pr
- Run the workflow on a feature branch (e.g.,
release-sdks-on-api-release) — this creates a PR with title:
"chore: 🐝 Update SDKs - Generate and Publish OpenAPI specs [release-sdks-on-api-release]"
- Run the workflow on
main — it searches for a PR with title prefix:
"chore: 🐝 Update SDKs - Generate and Publish OpenAPI specs"
strings.HasPrefix matches the branch-specific PR from step 2, because the branch PR title starts with the main search pattern
- The action tries to reuse the branch from step 2, finds commits on it, and fails with:
Error: external changes detected on branch speakeasy-sdk-regen-release-sdks-on-api-release-XXXXXXXXXX.
The action cannot proceed because non-automated commits were pushed to this branch.
Root Cause
internal/git/git.go line 218:
if strings.HasPrefix(p.GetTitle(), prTitle) || strings.HasPrefix(p.GetTitle(), legacyPrTitle) {
When running from main:
prTitle = "chore: 🐝 Update SDKs - <workflow_name>" (no [branch] suffix)
- A PR with title
"chore: 🐝 Update SDKs - <workflow_name> [my-branch]" matches via HasPrefix
The existing base-branch guard at line 226 only activates when !isMainBranch, so it doesn't help here.
Suggested Fix
After the HasPrefix match, check whether the remainder of the title starts with [. When running from main (no branch qualifier expected), skip PRs that have a branch qualifier suffix:
matchedPrefix := prTitle
if !strings.HasPrefix(title, prTitle) {
matchedPrefix = legacyPrTitle
}
remainder := strings.TrimPrefix(title, matchedPrefix)
if isMainBranch && environment.GetFeatureBranch() == "" && strings.HasPrefix(strings.TrimSpace(remainder), "[") {
logging.Info("Skipping PR with branch qualifier that doesn't match current context: %s", title)
continue
}
Additional Note
There's a secondary issue that contributes to the failure: the findNonCICommits() function doesn't recognize commits made by the action when enable_sdk_changelog is enabled. The changelog feature replaces the commit message (which normally starts with "ci: ") with a markdown report from GetCommitMarkdownSection(), causing those action-created commits to be classified as "non-CI" / "external" on subsequent runs.
Bug Description
In PR mode,
FindExistingPR()ininternal/git/git.gousesstrings.HasPrefixto match PR titles. When the workflow runs on the main branch, the search pattern has no branch qualifier suffix, causing it to greedily match PRs created from other branches.Steps to Reproduce
sdk_generation.yamlwithmode: prrelease-sdks-on-api-release) — this creates a PR with title:"chore: 🐝 Update SDKs - Generate and Publish OpenAPI specs [release-sdks-on-api-release]"main— it searches for a PR with title prefix:"chore: 🐝 Update SDKs - Generate and Publish OpenAPI specs"strings.HasPrefixmatches the branch-specific PR from step 2, because the branch PR title starts with the main search patternRoot Cause
internal/git/git.goline 218:When running from main:
prTitle="chore: 🐝 Update SDKs - <workflow_name>"(no[branch]suffix)"chore: 🐝 Update SDKs - <workflow_name> [my-branch]"matches viaHasPrefixThe existing base-branch guard at line 226 only activates when
!isMainBranch, so it doesn't help here.Suggested Fix
After the
HasPrefixmatch, check whether the remainder of the title starts with[. When running from main (no branch qualifier expected), skip PRs that have a branch qualifier suffix:Additional Note
There's a secondary issue that contributes to the failure: the
findNonCICommits()function doesn't recognize commits made by the action whenenable_sdk_changelogis enabled. The changelog feature replaces the commit message (which normally starts with"ci: ") with a markdown report fromGetCommitMarkdownSection(), causing those action-created commits to be classified as "non-CI" / "external" on subsequent runs.