From 1e4e02e6224b5a571dde6a181436c52f1ea8a34f Mon Sep 17 00:00:00 2001 From: Sam El-Borai Date: Wed, 19 Nov 2025 19:09:12 +0100 Subject: [PATCH] fix(ci): prefix stainless branches with fork author (#4187) # What does this PR do? I believe that should avoid CI issues seen in https://github.com/llamastack/llama-stack/pull/4173. Error we see in Stainless logs: ``` (cannot lock ref 'refs/heads/preview/base/fix/issue-3797-metadata-validation': 'refs/heads/preview/base/fix' exists; cannot create 'refs/heads/preview/base/fix/issue-3797-metadata-validation') ``` The issue is that if a branch `fix` exists, `fix/` cannot be created (that's how git refs work unfortunately...). The fix in this PR is to ensure PRs from forks are using the author as a prefix. In addition we will do changes to the Stainless API to return better error messages here, it should have been a 4xx with a meaningful error, not a 500. And we will likely need to delete the `fix` branch. ## Test Plan --- .github/workflows/stainless-builds.yml | 56 ++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/.github/workflows/stainless-builds.yml b/.github/workflows/stainless-builds.yml index 00c5e3df5..a18c70887 100644 --- a/.github/workflows/stainless-builds.yml +++ b/.github/workflows/stainless-builds.yml @@ -59,6 +59,30 @@ jobs: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 2 + # Compute the Stainless branch name, prefixing with fork owner if PR is from a fork. + # For fork PRs like "contributor:fix/issue-123", this creates "preview/contributor/fix/issue-123" + # For same-repo PRs, this creates "preview/fix/issue-123" + - name: Compute branch names + id: branch-names + run: | + HEAD_REPO="${{ github.event.pull_request.head.repo.full_name }}" + BASE_REPO="${{ github.repository }}" + BRANCH_NAME="${{ github.event.pull_request.head.ref }}" + + if [ "$HEAD_REPO" != "$BASE_REPO" ]; then + # Fork PR: prefix with fork owner for isolation + FORK_OWNER="${{ github.event.pull_request.head.repo.owner.login }}" + PREVIEW_BRANCH="preview/${FORK_OWNER}/${BRANCH_NAME}" + BASE_BRANCH="preview/base/${FORK_OWNER}/${BRANCH_NAME}" + else + # Same-repo PR + PREVIEW_BRANCH="preview/${BRANCH_NAME}" + BASE_BRANCH="preview/base/${BRANCH_NAME}" + fi + + echo "preview_branch=${PREVIEW_BRANCH}" >> $GITHUB_OUTPUT + echo "base_branch=${BASE_BRANCH}" >> $GITHUB_OUTPUT + # This action builds preview SDKs from the OpenAPI spec changes and # posts/updates a comment on the PR with build results and links to the preview. - name: Run preview builds @@ -73,6 +97,8 @@ jobs: base_sha: ${{ github.event.pull_request.base.sha }} base_ref: ${{ github.event.pull_request.base.ref }} head_sha: ${{ github.event.pull_request.head.sha }} + branch: ${{ steps.branch-names.outputs.preview_branch }} + base_branch: ${{ steps.branch-names.outputs.base_branch }} merge: if: github.event.action == 'closed' && github.event.pull_request.merged == true @@ -90,12 +116,33 @@ jobs: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 2 + # Compute the Stainless branch name, prefixing with fork owner if PR is from a fork. + # For fork PRs like "contributor:fix/issue-123", this creates "preview/contributor/fix/issue-123" + # For same-repo PRs, this creates "preview/fix/issue-123" + - name: Compute branch names + id: branch-names + run: | + HEAD_REPO="${{ github.event.pull_request.head.repo.full_name }}" + BASE_REPO="${{ github.repository }}" + BRANCH_NAME="${{ github.event.pull_request.head.ref }}" + + if [ "$HEAD_REPO" != "$BASE_REPO" ]; then + # Fork PR: prefix with fork owner for isolation + FORK_OWNER="${{ github.event.pull_request.head.repo.owner.login }}" + MERGE_BRANCH="preview/${FORK_OWNER}/${BRANCH_NAME}" + else + # Same-repo PR + MERGE_BRANCH="preview/${BRANCH_NAME}" + fi + + echo "merge_branch=${MERGE_BRANCH}" >> $GITHUB_OUTPUT + # Note that this only merges in changes that happened on the last build on - # preview/${{ github.head_ref }}. It's possible that there are OAS/config - # changes that haven't been built, if the preview-sdk job didn't finish + # the computed preview branch. It's possible that there are OAS/config + # changes that haven't been built, if the preview job didn't finish # before this step starts. In theory we want to wait for all builds - # against preview/${{ github.head_ref }} to complete, but assuming that - # the preview-sdk job happens before the PR merge, it should be fine. + # against the preview branch to complete, but assuming that + # the preview job happens before the PR merge, it should be fine. - name: Run merge build uses: stainless-api/upload-openapi-spec-action/merge@32823b096b4319c53ee948d702d9052873af485f # 1.6.0 with: @@ -108,3 +155,4 @@ jobs: base_sha: ${{ github.event.pull_request.base.sha }} base_ref: ${{ github.event.pull_request.base.ref }} head_sha: ${{ github.event.pull_request.head.sha }} + merge_branch: ${{ steps.branch-names.outputs.merge_branch }}