Compare commits

...
Author SHA1 Message Date
Christine ChenandGitHub 30bc131b97 feat: auto-merge Speakeasy SDK generation PRs (#332) 2026-06-18 11:05:15 -04:00
Christine Chen 1b0118c365 fix: address review feedback on auto-merge workflow
Pipe gh pr list output through jq instead of passing --arg to gh --jq,
and add a repo-level concurrency group to prevent cross-PR merge races.
2026-06-17 16:54:40 -04:00
Christine Chen cda73e5ebf feat: auto-merge Speakeasy SDK generation PRs
Add a workflow that merges Speakeasy codegen PRs when the bot applies a
semver label, closing superseded regen PRs first. This unblocks
sdk_publish.yaml after mode:pr generation without manual intervention.
2026-06-17 16:28:01 -04:00
b0eda78d3f chore: update OpenAPI spec from monorepo (#330)
Co-authored-by: OpenRouter SDK Bot <sdk-bot@openrouter.ai>
2026-06-17 12:53:02 -07:00
Christine ChenandGitHub bf682bdb62 fix: use PR mode for spec-change SDK generation (#329) 2026-06-17 15:07:36 -04:00
Christine Chen b322622117 fix: use PR mode for spec-change SDK generation
Switch sdk_generation_for_spec_change.yaml from direct to pr mode so
Speakeasy opens a PR instead of pushing to main. This avoids branch
protection failures and routes publishing through sdk_publish.yaml.
2026-06-17 10:37:08 -04:00
3 changed files with 140 additions and 2 deletions
@@ -0,0 +1,86 @@
name: Auto-merge Speakeasy PR
# Speakeasy mode:pr opens PRs (speakeasy-sdk-regen-*) and labels them
# patch/minor/major. Merge automatically so sdk_publish.yaml can run.
on:
pull_request:
types: [labeled]
permissions:
contents: write
pull-requests: write
concurrency:
group: auto-merge-speakeasy
cancel-in-progress: false
jobs:
auto-merge:
if: |
github.event.sender.login == 'github-actions[bot]' &&
github.event.pull_request.user.login == 'github-actions[bot]' &&
startsWith(github.event.pull_request.head.ref, 'speakeasy-sdk-regen-') &&
contains(github.event.pull_request.title, '🐝 Update SDK') &&
contains(fromJSON('["patch", "minor", "major"]'), github.event.label.name)
runs-on: ubuntu-latest
steps:
- name: Close superseded Speakeasy PRs
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
CURRENT_PR="${{ github.event.pull_request.number }}"
PRIOR_JSON=$(gh pr list \
--repo "${{ github.repository }}" \
--state open \
--search "head:speakeasy-sdk-regen-" \
--limit 500 \
--json number \
| jq -r --arg cur "$CURRENT_PR" \
'[.[].number | select(tostring != $cur)] | .[]')
if [ -z "$PRIOR_JSON" ]; then
echo "No superseded Speakeasy PRs to close"
exit 0
fi
mapfile -t PRIOR <<< "$PRIOR_JSON"
echo "Closing ${#PRIOR[@]} superseded Speakeasy PR(s)"
for N in "${PRIOR[@]}"; do
gh pr close "$N" --repo "${{ github.repository }}" --delete-branch \
--comment "Superseded by newer Speakeasy SDK generation PR #${CURRENT_PR}" \
|| echo "::warning::Failed to close PR #$N (continuing)"
sleep 1
done
- name: Auto-merge Speakeasy PR
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
PR_NUM="${{ github.event.pull_request.number }}"
REPO="${{ github.repository }}"
STATE=$(gh pr view "$PR_NUM" --repo "$REPO" --json state --jq .state)
if [ "$STATE" != "OPEN" ]; then
echo "PR #$PR_NUM is $STATE — skipping merge"
exit 0
fi
# Prefer GitHub auto-merge when required checks exist; otherwise
# squash-merge directly (same pattern as sdk-release-prs.yaml).
AUTO_MERGE_NOOP_PATTERN='is in clean status|protected branch rules|Branch does not have required protected branch rules'
if gh pr merge "$PR_NUM" --repo "$REPO" --squash --auto --delete-branch 2> /tmp/gh-merge.err; then
echo "Auto-merge enabled for Speakeasy PR #$PR_NUM"
elif grep -qiE "$AUTO_MERGE_NOOP_PATTERN" /tmp/gh-merge.err; then
echo "Auto-merge not applicable — merging PR #$PR_NUM directly"
cat /tmp/gh-merge.err >&2
gh pr merge "$PR_NUM" --repo "$REPO" --squash --delete-branch
else
echo "::error::Failed to enable auto-merge on Speakeasy PR #$PR_NUM"
cat /tmp/gh-merge.err >&2
exit 1
fi
@@ -28,7 +28,7 @@ jobs:
uses: speakeasy-api/sdk-generation-action/.github/workflows/workflow-executor.yaml@v15
with:
force: ${{ github.event.inputs.force }}
mode: direct
mode: pr
set_version: ${{ github.event.inputs.set_version }}
secrets:
github_access_token: ${{ secrets.GITHUB_TOKEN }}
+53 -1
View File
@@ -12202,6 +12202,15 @@ components:
image: '0'
prompt: '0.00003'
request: '0'
reasoning:
default_effort: medium
default_enabled: true
mandatory: false
supported_efforts:
- high
- medium
- low
- minimal
supported_parameters:
- temperature
- top_p
@@ -12264,6 +12273,8 @@ components:
$ref: '#/components/schemas/PerRequestLimits'
pricing:
$ref: '#/components/schemas/PublicPricing'
reasoning:
$ref: '#/components/schemas/ModelReasoning'
supported_parameters:
description: List of supported parameters for this model
items:
@@ -12426,6 +12437,47 @@ components:
description: Model to use for completion
example: openai/gpt-4
type: string
ModelReasoning:
description: Reasoning effort configuration. Omitted for non-reasoning models and dynamic router models.
example:
default_effort: medium
default_enabled: true
mandatory: false
supported_efforts:
- high
- medium
- low
- minimal
properties:
default_effort:
allOf:
- $ref: '#/components/schemas/ReasoningEffort'
- description: >-
Default reasoning effort when the client enables reasoning without specifying effort. Maps to
`reasoning.effort` in chat requests. When `"none"`, prefer omitting effort unless the user explicitly
disables reasoning.
default_enabled:
description: Default reasoning enabled state when the client does not set `reasoning.enabled`.
type: boolean
mandatory:
description: When true, reasoning cannot be disabled and effort "none" is rejected.
type: boolean
supported_efforts:
description: >-
Allowed reasoning effort values for this model, in descending effort order (highest first). Null means no
allowlist — all gateway effort values are accepted.
items:
$ref: '#/components/schemas/ReasoningEffort'
nullable: true
type: array
supports_max_tokens:
description: >-
Present and `true` when the model accepts `reasoning.max_tokens` in requests (Anthropic-style) instead of or
in addition to `reasoning.effort`. Omitted otherwise.
type: boolean
required:
- mandatory
type: object
ModelResponse:
description: Single model response
example:
@@ -28837,7 +28889,7 @@ paths:
id: openai/gpt-4
knowledge_cutoff: null
links:
details: /api/v1/models/openai/gpt-5.4/endpoints
details: /api/v1/models/openai/gpt-4/endpoints
name: GPT-4
per_request_limits: null
pricing: