mirror of
https://github.com/meta-llama/llama-stack.git
synced 2025-12-22 19:16:17 +00:00
# What does this PR do?
Enable stainless-builds workflow to test preview SDKs by calling
integration-tests workflow with python_url parameter. Add stainless
matrix config for faster CI runs on SDK changes.
- Make integration-tests.yml reusable with workflow_call inputs
- Thread python_url through test setup actions to install preview SDK
- Add matrix_key parameter to generate_ci_matrix.py for custom matrices
- Update stainless-builds.yml to call integration tests with preview URL
This allows us to test a client on the PR introducing the new changes
before merging. Contributors can even write new tests using the
generated client which should pass on the PR, indicating that they will
pass on main upon merge
## Test Plan
see triggered action using the workflows on this branch:
5810594042
which installs the stainless SDK from the given url.
---------
Signed-off-by: Charlie Doern <cdoern@redhat.com>
220 lines
9.5 KiB
YAML
220 lines
9.5 KiB
YAML
name: Stainless SDK Builds
|
|
run-name: Build Stainless SDK from OpenAPI spec changes
|
|
|
|
# This workflow uses pull_request_target, which allows it to run on pull requests
|
|
# from forks with access to secrets. This is safe because the workflow definition
|
|
# comes from the base branch (trusted), and the action only reads OpenAPI spec
|
|
# files without executing any code from the PR.
|
|
|
|
on:
|
|
pull_request_target:
|
|
types:
|
|
- opened
|
|
- synchronize
|
|
- reopened
|
|
- closed
|
|
paths:
|
|
- "client-sdks/stainless/**"
|
|
- ".github/workflows/stainless-builds.yml" # this workflow
|
|
workflow_dispatch:
|
|
inputs:
|
|
pr_number:
|
|
description: 'PR number to run Stainless build for'
|
|
required: true
|
|
type: number
|
|
sdk_install_url:
|
|
description: 'Python SDK install URL (optional, for testing specific builds)'
|
|
required: false
|
|
type: string
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || inputs.pr_number || github.run_id }}
|
|
cancel-in-progress: true
|
|
|
|
env:
|
|
# Stainless organization name.
|
|
STAINLESS_ORG: llamastack
|
|
|
|
# Stainless project name.
|
|
STAINLESS_PROJECT: llama-stack-client
|
|
|
|
# Path to your OpenAPI spec.
|
|
OAS_PATH: ./client-sdks/stainless/openapi.yml
|
|
|
|
# Path to your Stainless config. Optional; only provide this if you prefer
|
|
# to maintain the ground truth Stainless config in your own repo.
|
|
CONFIG_PATH: ./client-sdks/stainless/config.yml
|
|
|
|
# When to fail the job based on build conclusion.
|
|
# Options: "never" | "note" | "warning" | "error" | "fatal".
|
|
FAIL_ON: error
|
|
|
|
# In your repo secrets, configure:
|
|
# - STAINLESS_API_KEY: a Stainless API key, which you can generate on the
|
|
# Stainless organization dashboard
|
|
|
|
jobs:
|
|
compute-branch:
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
preview_branch: ${{ steps.compute.outputs.preview_branch }}
|
|
base_branch: ${{ steps.compute.outputs.base_branch }}
|
|
merge_branch: ${{ steps.compute.outputs.merge_branch }}
|
|
pr_head_repo: ${{ steps.compute.outputs.pr_head_repo }}
|
|
pr_head_ref: ${{ steps.compute.outputs.pr_head_ref }}
|
|
pr_head_sha: ${{ steps.compute.outputs.pr_head_sha }}
|
|
pr_base_sha: ${{ steps.compute.outputs.pr_base_sha }}
|
|
pr_base_ref: ${{ steps.compute.outputs.pr_base_ref }}
|
|
pr_title: ${{ steps.compute.outputs.pr_title }}
|
|
steps:
|
|
- name: Fetch PR details for workflow_dispatch
|
|
if: github.event_name == 'workflow_dispatch'
|
|
id: fetch-pr
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
run: |
|
|
PR_DATA=$(gh pr view ${{ inputs.pr_number }} --repo ${{ github.repository }} --json headRefName,headRepository,headRefOid,baseRefName,baseRefOid,headRepositoryOwner,title)
|
|
echo "pr_data=$PR_DATA" >> $GITHUB_OUTPUT
|
|
|
|
- name: Compute branch names
|
|
id: compute
|
|
run: |
|
|
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
|
# Extract from fetched PR data
|
|
PR_DATA='${{ steps.fetch-pr.outputs.pr_data }}'
|
|
FORK_OWNER=$(echo "$PR_DATA" | jq -r '.headRepositoryOwner.login')
|
|
REPO_NAME=$(echo "$PR_DATA" | jq -r '.headRepository.name')
|
|
HEAD_REPO="${FORK_OWNER}/${REPO_NAME}"
|
|
BRANCH_NAME=$(echo "$PR_DATA" | jq -r '.headRefName')
|
|
HEAD_SHA=$(echo "$PR_DATA" | jq -r '.headRefOid')
|
|
BASE_SHA=$(echo "$PR_DATA" | jq -r '.baseRefOid')
|
|
BASE_REF=$(echo "$PR_DATA" | jq -r '.baseRefName')
|
|
PR_TITLE=$(echo "$PR_DATA" | jq -r '.title')
|
|
else
|
|
# Use pull_request_target event data
|
|
HEAD_REPO="${{ github.event.pull_request.head.repo.full_name }}"
|
|
BRANCH_NAME="${{ github.event.pull_request.head.ref }}"
|
|
FORK_OWNER="${{ github.event.pull_request.head.repo.owner.login }}"
|
|
HEAD_SHA="${{ github.event.pull_request.head.sha }}"
|
|
BASE_SHA="${{ github.event.pull_request.base.sha }}"
|
|
BASE_REF="${{ github.event.pull_request.base.ref }}"
|
|
PR_TITLE="${{ github.event.pull_request.title }}"
|
|
fi
|
|
|
|
BASE_REPO="${{ github.repository }}"
|
|
|
|
if [ "$HEAD_REPO" != "$BASE_REPO" ]; then
|
|
# Fork PR: prefix with fork owner for isolation
|
|
if [ -z "$FORK_OWNER" ]; then
|
|
echo "Error: Fork PR detected but fork owner is empty" >&2
|
|
exit 1
|
|
fi
|
|
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
|
|
echo "merge_branch=${PREVIEW_BRANCH}" >> $GITHUB_OUTPUT
|
|
echo "pr_head_repo=${HEAD_REPO}" >> $GITHUB_OUTPUT
|
|
echo "pr_head_ref=${BRANCH_NAME}" >> $GITHUB_OUTPUT
|
|
echo "pr_head_sha=${HEAD_SHA}" >> $GITHUB_OUTPUT
|
|
echo "pr_base_sha=${BASE_SHA}" >> $GITHUB_OUTPUT
|
|
echo "pr_base_ref=${BASE_REF}" >> $GITHUB_OUTPUT
|
|
echo "pr_title=${PR_TITLE}" >> $GITHUB_OUTPUT
|
|
|
|
preview:
|
|
needs: compute-branch
|
|
# Skip preview if workflow_dispatch provides sdk_install_url, or if PR is being closed
|
|
if: |
|
|
(github.event_name == 'workflow_dispatch' && inputs.sdk_install_url == '') ||
|
|
(github.event_name == 'pull_request_target' && github.event.action != 'closed')
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
pull-requests: write
|
|
outputs:
|
|
sdk_install_url: ${{ fromJSON(steps.run-preview.outputs.outcomes || '{}').python.install_url || '' }}
|
|
steps:
|
|
# Checkout the PR's code to access the OpenAPI spec and config files.
|
|
# This is necessary to read the spec/config from the PR (including from forks).
|
|
- name: Checkout repository
|
|
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
|
with:
|
|
repository: ${{ needs.compute-branch.outputs.pr_head_repo }}
|
|
ref: ${{ needs.compute-branch.outputs.pr_head_sha }}
|
|
fetch-depth: 2
|
|
|
|
- name: Run preview builds
|
|
id: run-preview
|
|
uses: stainless-api/upload-openapi-spec-action/preview@979824f1ea5f44334940f0768d04642b6cdaa0d1 # 1.8.1
|
|
env:
|
|
PR_NUMBER: ${{ inputs.pr_number || github.event.pull_request.number }}
|
|
with:
|
|
stainless_api_key: ${{ secrets.STAINLESS_API_KEY }}
|
|
org: ${{ env.STAINLESS_ORG }}
|
|
project: ${{ env.STAINLESS_PROJECT }}
|
|
oas_path: ${{ env.OAS_PATH }}
|
|
config_path: ${{ env.CONFIG_PATH }}
|
|
fail_on: ${{ env.FAIL_ON }}
|
|
base_sha: ${{ needs.compute-branch.outputs.pr_base_sha }}
|
|
base_ref: ${{ needs.compute-branch.outputs.pr_base_ref }}
|
|
head_sha: ${{ needs.compute-branch.outputs.pr_head_sha }}
|
|
branch: ${{ needs.compute-branch.outputs.preview_branch }}
|
|
base_branch: ${{ needs.compute-branch.outputs.base_branch }}
|
|
commit_message: ${{ needs.compute-branch.outputs.pr_title }}
|
|
make_comment: true
|
|
|
|
run-integration-tests:
|
|
needs: [compute-branch, preview]
|
|
if: |
|
|
always() &&
|
|
(needs.preview.result == 'success' || needs.preview.result == 'skipped') &&
|
|
(github.event_name == 'workflow_dispatch' || github.event.action != 'closed')
|
|
uses: ./.github/workflows/integration-tests.yml
|
|
with:
|
|
# Use provided sdk_install_url from workflow_dispatch, or from preview build
|
|
sdk_install_url: ${{ inputs.sdk_install_url || needs.preview.outputs.sdk_install_url }}
|
|
matrix_key: 'stainless'
|
|
test-all-client-versions: false
|
|
|
|
merge:
|
|
needs: compute-branch
|
|
if: github.event_name == 'pull_request_target' && github.event.action == 'closed' && github.event.pull_request.merged == true
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
pull-requests: write
|
|
steps:
|
|
# Checkout the PR's code to access the OpenAPI spec and config files.
|
|
# This is necessary to read the spec/config from the PR (including from forks).
|
|
- name: Checkout repository
|
|
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
|
with:
|
|
repository: ${{ needs.compute-branch.outputs.pr_head_repo }}
|
|
ref: ${{ needs.compute-branch.outputs.pr_head_sha }}
|
|
fetch-depth: 2
|
|
|
|
# Note that this only merges in changes that happened on the last build on
|
|
# 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 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@979824f1ea5f44334940f0768d04642b6cdaa0d1 # 1.8.1
|
|
with:
|
|
stainless_api_key: ${{ secrets.STAINLESS_API_KEY }}
|
|
org: ${{ env.STAINLESS_ORG }}
|
|
project: ${{ env.STAINLESS_PROJECT }}
|
|
oas_path: ${{ env.OAS_PATH }}
|
|
config_path: ${{ env.CONFIG_PATH }}
|
|
fail_on: ${{ env.FAIL_ON }}
|
|
base_sha: ${{ needs.compute-branch.outputs.pr_base_sha }}
|
|
base_ref: ${{ needs.compute-branch.outputs.pr_base_ref }}
|
|
head_sha: ${{ needs.compute-branch.outputs.pr_head_sha }}
|
|
merge_branch: ${{ needs.compute-branch.outputs.merge_branch }}
|