mirror of
https://github.com/wassname/openrouter-python-sdk-retry-errors.git
synced 2026-07-30 12:20:57 +08:00
fix: chain Speakeasy auto-merge into Generate run (#364)
This commit is contained in:
@@ -1,11 +1,27 @@
|
|||||||
name: Auto-merge Speakeasy PR
|
name: Auto-merge Speakeasy PR
|
||||||
|
|
||||||
# Speakeasy mode:pr opens PRs (speakeasy-sdk-regen-*) and labels them
|
# Called as a follow-up job after Speakeasy Generate (mode: pr). Merges the
|
||||||
# patch/minor/major. Merge automatically so sdk_publish.yaml can run.
|
# regen PR opened/updated in the same workflow run so sdk_publish.yaml can run.
|
||||||
|
# Prefer branch_name from Generate logs; fall back to run_started_at heuristics.
|
||||||
|
# Uses GH_DOCS_SYNC GitHub App token (not a PAT) so merges trigger downstream push.
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
workflow_call:
|
||||||
types: [labeled, opened]
|
inputs:
|
||||||
|
run_started_at:
|
||||||
|
description: ISO timestamp when the parent Generate workflow run started
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
branch_name:
|
||||||
|
description: Speakeasy regen branch from the parent Generate run (optional)
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: ""
|
||||||
|
secrets:
|
||||||
|
GH_DOCS_SYNC_APP_ID:
|
||||||
|
required: true
|
||||||
|
GH_DOCS_SYNC_APP_PRIVATE_KEY:
|
||||||
|
required: true
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
@@ -17,18 +33,6 @@ concurrency:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
auto-merge:
|
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') &&
|
|
||||||
(
|
|
||||||
(github.event.action == 'labeled' && contains(fromJSON('["patch", "minor", "major"]'), github.event.label.name)) ||
|
|
||||||
(github.event.action == 'opened' &&
|
|
||||||
(contains(github.event.pull_request.labels.*.name, 'patch') ||
|
|
||||||
contains(github.event.pull_request.labels.*.name, 'minor') ||
|
|
||||||
contains(github.event.pull_request.labels.*.name, 'major')))
|
|
||||||
)
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Generate GitHub App token
|
- name: Generate GitHub App token
|
||||||
@@ -39,21 +43,80 @@ jobs:
|
|||||||
app-id: ${{ secrets.GH_DOCS_SYNC_APP_ID }}
|
app-id: ${{ secrets.GH_DOCS_SYNC_APP_ID }}
|
||||||
private-key: ${{ secrets.GH_DOCS_SYNC_APP_PRIVATE_KEY }}
|
private-key: ${{ secrets.GH_DOCS_SYNC_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
- name: Close superseded Speakeasy PRs
|
- name: Resolve Speakeasy regen PR
|
||||||
|
id: pr
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
CURRENT_PR="${{ github.event.pull_request.number }}"
|
|
||||||
|
|
||||||
PRIOR_JSON=$(gh pr list \
|
REPO="${{ github.repository }}"
|
||||||
--repo "${{ github.repository }}" \
|
RUN_STARTED="${{ inputs.run_started_at }}"
|
||||||
|
BRANCH="${{ inputs.branch_name }}"
|
||||||
|
|
||||||
|
PR_JSON=$(gh pr list \
|
||||||
|
--repo "$REPO" \
|
||||||
--state open \
|
--state open \
|
||||||
--search "head:speakeasy-sdk-regen-" \
|
--search "head:speakeasy-sdk-regen-" \
|
||||||
--limit 500 \
|
--limit 500 \
|
||||||
--json number \
|
--json number,updatedAt,title,labels,author,headRefName)
|
||||||
| jq -r --arg cur "$CURRENT_PR" \
|
|
||||||
'[.[].number | select(tostring != $cur)] | .[]')
|
PR_NUM=""
|
||||||
|
if [ -n "$BRANCH" ]; then
|
||||||
|
CANDIDATE=$(echo "$PR_JSON" | jq -r --arg branch "$BRANCH" \
|
||||||
|
'[.[] | select(.headRefName == $branch)] | .[0] // empty')
|
||||||
|
if [ -n "$CANDIDATE" ] && echo "$CANDIDATE" | jq -e '
|
||||||
|
(.headRefName | startswith("speakeasy-sdk-regen-"))
|
||||||
|
and (.title | contains("🐝 Update SDK"))
|
||||||
|
and ([.labels[].name] | any(. == "patch" or . == "minor" or . == "major"))
|
||||||
|
and (.author.is_bot == true)
|
||||||
|
' > /dev/null; then
|
||||||
|
PR_NUM=$(echo "$CANDIDATE" | jq -r '.number')
|
||||||
|
echo "Resolved Speakeasy regen PR #$PR_NUM from branch $BRANCH"
|
||||||
|
else
|
||||||
|
echo "::warning::branch_name=$BRANCH did not match a valid open regen PR — falling back to run_started_at"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$PR_NUM" ]; then
|
||||||
|
PR_NUM=$(echo "$PR_JSON" | jq -r --arg started "$RUN_STARTED" '
|
||||||
|
[.[]
|
||||||
|
| select(.headRefName | startswith("speakeasy-sdk-regen-"))
|
||||||
|
| select(.title | contains("🐝 Update SDK"))
|
||||||
|
| select([.labels[].name] | any(. == "patch" or . == "minor" or . == "major"))
|
||||||
|
| select(.author.is_bot == true)
|
||||||
|
| select(.updatedAt >= $started)
|
||||||
|
] | sort_by(.updatedAt) | last | .number // empty')
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$PR_NUM" ]; then
|
||||||
|
echo "No Speakeasy regen PR for this Generate run — skipping auto-merge"
|
||||||
|
echo "::notice title=auto-merge-skipped::No qualifying Speakeasy regen PR to merge"
|
||||||
|
{
|
||||||
|
echo "## Auto-merge skipped"
|
||||||
|
echo "No qualifying \`speakeasy-sdk-regen-*\` PR was found."
|
||||||
|
echo "- branch_name input: \`${BRANCH:-<empty>}\`"
|
||||||
|
echo "- run_started_at: \`$RUN_STARTED\`"
|
||||||
|
} >> "$GITHUB_STEP_SUMMARY"
|
||||||
|
echo "pr_num=" >> "$GITHUB_OUTPUT"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "pr_num=$PR_NUM" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "$PR_JSON" > /tmp/speakeasy_pr_json.json
|
||||||
|
|
||||||
|
- name: Close superseded Speakeasy PRs
|
||||||
|
if: steps.pr.outputs.pr_num != ''
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
CURRENT_PR="${{ steps.pr.outputs.pr_num }}"
|
||||||
|
PR_JSON=$(cat /tmp/speakeasy_pr_json.json)
|
||||||
|
|
||||||
|
PRIOR_JSON=$(echo "$PR_JSON" | jq -r --arg current_pr "$CURRENT_PR" \
|
||||||
|
'[.[].number | select(tostring != $current_pr)] | .[]')
|
||||||
|
|
||||||
if [ -z "$PRIOR_JSON" ]; then
|
if [ -z "$PRIOR_JSON" ]; then
|
||||||
echo "No superseded Speakeasy PRs to close"
|
echo "No superseded Speakeasy PRs to close"
|
||||||
@@ -71,30 +134,92 @@ jobs:
|
|||||||
done
|
done
|
||||||
|
|
||||||
- name: Auto-merge Speakeasy PR
|
- name: Auto-merge Speakeasy PR
|
||||||
|
if: steps.pr.outputs.pr_num != ''
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
PR_NUM="${{ github.event.pull_request.number }}"
|
|
||||||
|
PR_NUM="${{ steps.pr.outputs.pr_num }}"
|
||||||
REPO="${{ github.repository }}"
|
REPO="${{ github.repository }}"
|
||||||
|
|
||||||
|
wait_for_checks() {
|
||||||
|
local pr=$1
|
||||||
|
local timeout=600
|
||||||
|
local interval=15
|
||||||
|
local elapsed=0
|
||||||
|
|
||||||
|
echo "Waiting for PR #$pr checks (timeout ${timeout}s)..."
|
||||||
|
while [ "$elapsed" -lt "$timeout" ]; do
|
||||||
|
TOTAL=$(gh pr view "$pr" --repo "$REPO" --json statusCheckRollup --jq \
|
||||||
|
'.statusCheckRollup | length')
|
||||||
|
PENDING=$(gh pr view "$pr" --repo "$REPO" --json statusCheckRollup --jq \
|
||||||
|
'[.statusCheckRollup[]? | select(.status != "COMPLETED")] | length')
|
||||||
|
FAILED=$(gh pr view "$pr" --repo "$REPO" --json statusCheckRollup --jq \
|
||||||
|
'[.statusCheckRollup[]? | select(.status == "COMPLETED") | select(.conclusion != "SUCCESS" and .conclusion != "SKIPPED" and .conclusion != "NEUTRAL")] | length')
|
||||||
|
|
||||||
|
if [ "$TOTAL" -eq 0 ]; then
|
||||||
|
# GITHUB_TOKEN-authored regen PRs get no pull_request checks at all,
|
||||||
|
# so TOTAL stays 0 forever. Wait a short grace window in case checks
|
||||||
|
# are merely slow to register, then proceed rather than time out.
|
||||||
|
if [ "$elapsed" -ge 60 ]; then
|
||||||
|
echo "No checks registered after ${elapsed}s — proceeding (checkless PR)"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
echo "Checks not yet registered — waiting ${interval}s..."
|
||||||
|
sleep "$interval"
|
||||||
|
elapsed=$((elapsed + interval))
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$PENDING" -eq 0 ]; then
|
||||||
|
if [ "$FAILED" -gt 0 ]; then
|
||||||
|
echo "::error::PR #$pr has failing checks — refusing direct merge"
|
||||||
|
gh pr checks "$pr" --repo "$REPO" || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "All checks completed"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Checks pending ($PENDING) — waiting ${interval}s..."
|
||||||
|
sleep "$interval"
|
||||||
|
elapsed=$((elapsed + interval))
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "::error::Timed out waiting for PR #$pr checks"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
STATE=$(gh pr view "$PR_NUM" --repo "$REPO" --json state --jq .state)
|
STATE=$(gh pr view "$PR_NUM" --repo "$REPO" --json state --jq .state)
|
||||||
if [ "$STATE" != "OPEN" ]; then
|
if [ "$STATE" != "OPEN" ]; then
|
||||||
echo "PR #$PR_NUM is $STATE — skipping merge"
|
echo "PR #$PR_NUM is $STATE — skipping merge"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
MERGE_METHOD=""
|
||||||
# Prefer GitHub auto-merge when required checks exist; otherwise
|
# Prefer GitHub auto-merge when required checks exist; otherwise
|
||||||
# squash-merge directly (same pattern as sdk-release-prs.yaml).
|
# squash-merge directly after checks pass (sdk-release-prs.yaml pattern).
|
||||||
AUTO_MERGE_NOOP_PATTERN='is in clean status|protected branch rules|Branch does not have required protected branch rules'
|
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
|
if gh pr merge "$PR_NUM" --repo "$REPO" --squash --auto --delete-branch 2> /tmp/gh-merge.err; then
|
||||||
|
MERGE_METHOD="auto-merge queued"
|
||||||
echo "Auto-merge enabled for Speakeasy PR #$PR_NUM"
|
echo "Auto-merge enabled for Speakeasy PR #$PR_NUM"
|
||||||
elif grep -qiE "$AUTO_MERGE_NOOP_PATTERN" /tmp/gh-merge.err; then
|
elif grep -qiE "$AUTO_MERGE_NOOP_PATTERN" /tmp/gh-merge.err; then
|
||||||
echo "Auto-merge not applicable — merging PR #$PR_NUM directly"
|
echo "Auto-merge not applicable — waiting for checks, then merging PR #$PR_NUM directly"
|
||||||
cat /tmp/gh-merge.err >&2
|
cat /tmp/gh-merge.err >&2
|
||||||
|
wait_for_checks "$PR_NUM"
|
||||||
gh pr merge "$PR_NUM" --repo "$REPO" --squash --delete-branch
|
gh pr merge "$PR_NUM" --repo "$REPO" --squash --delete-branch
|
||||||
|
MERGE_METHOD="direct squash (checks passed)"
|
||||||
else
|
else
|
||||||
echo "::error::Failed to enable auto-merge on Speakeasy PR #$PR_NUM"
|
echo "::error::Failed to enable auto-merge on Speakeasy PR #$PR_NUM"
|
||||||
cat /tmp/gh-merge.err >&2
|
cat /tmp/gh-merge.err >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo "::notice title=auto-merge-pr::Merged Speakeasy PR #$PR_NUM ($MERGE_METHOD)"
|
||||||
|
{
|
||||||
|
echo "## Auto-merge complete"
|
||||||
|
echo "- PR: #$PR_NUM"
|
||||||
|
echo "- Method: $MERGE_METHOD"
|
||||||
|
echo "- Token: GH_DOCS_SYNC GitHub App"
|
||||||
|
} >> "$GITHUB_STEP_SUMMARY"
|
||||||
|
|||||||
@@ -21,6 +21,11 @@ permissions:
|
|||||||
types:
|
types:
|
||||||
- labeled
|
- labeled
|
||||||
- unlabeled
|
- unlabeled
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: speakeasy-generate
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
generate:
|
generate:
|
||||||
uses: speakeasy-api/sdk-generation-action/.github/workflows/workflow-executor.yaml@v15
|
uses: speakeasy-api/sdk-generation-action/.github/workflows/workflow-executor.yaml@v15
|
||||||
@@ -32,3 +37,67 @@ jobs:
|
|||||||
github_access_token: ${{ secrets.GITHUB_TOKEN }}
|
github_access_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
pypi_token: ${{ secrets.PYPI_TOKEN }}
|
pypi_token: ${{ secrets.PYPI_TOKEN }}
|
||||||
speakeasy_api_key: ${{ secrets.SPEAKEASY_API_KEY }}
|
speakeasy_api_key: ${{ secrets.SPEAKEASY_API_KEY }}
|
||||||
|
|
||||||
|
resolve-branch:
|
||||||
|
needs: generate
|
||||||
|
if: ${{ !cancelled() && needs.generate.result == 'success' }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
branch_name: ${{ steps.branch.outputs.branch_name }}
|
||||||
|
run_started_at: ${{ steps.branch.outputs.run_started_at }}
|
||||||
|
steps:
|
||||||
|
- name: Extract branch from Generate logs
|
||||||
|
id: branch
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
REPO="${{ github.repository }}"
|
||||||
|
RUN_ID="${{ github.run_id }}"
|
||||||
|
|
||||||
|
RUN_STARTED="${{ github.run_started_at }}"
|
||||||
|
if [ -z "$RUN_STARTED" ]; then
|
||||||
|
RUN_STARTED=$(gh run view "$RUN_ID" --repo "$REPO" --json startedAt --jq '.startedAt')
|
||||||
|
echo "Resolved run_started_at from API: $RUN_STARTED"
|
||||||
|
fi
|
||||||
|
echo "run_started_at=$RUN_STARTED" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
# Full-run logs are unavailable while the workflow is in progress;
|
||||||
|
# fetch logs from the completed generate job instead.
|
||||||
|
JOB_ID=$(gh run view "$RUN_ID" --repo "$REPO" --json jobs --jq \
|
||||||
|
'[.jobs[] | select(.name == "generate / Generate Target")] | .[0].databaseId // empty')
|
||||||
|
|
||||||
|
BRANCH=""
|
||||||
|
if [ -z "$JOB_ID" ]; then
|
||||||
|
echo "::warning::Could not find generate job id — auto-merge will use run_started_at fallback"
|
||||||
|
else
|
||||||
|
MAX_ATTEMPTS=12
|
||||||
|
INTERVAL=10
|
||||||
|
for attempt in $(seq 1 "$MAX_ATTEMPTS"); do
|
||||||
|
BRANCH=$(gh run view "$RUN_ID" --repo "$REPO" --job "$JOB_ID" --log 2>/dev/null \
|
||||||
|
| grep -oE 'branch_name=speakeasy-sdk-regen-[0-9]+' | tail -1 | cut -d= -f2 || true)
|
||||||
|
if [ -n "$BRANCH" ]; then
|
||||||
|
echo "Extracted branch_name=$BRANCH (attempt $attempt)"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ "$attempt" -lt "$MAX_ATTEMPTS" ]; then
|
||||||
|
echo "Job logs not ready — waiting ${INTERVAL}s (attempt $attempt/$MAX_ATTEMPTS)..."
|
||||||
|
sleep "$INTERVAL"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ -z "$BRANCH" ]; then
|
||||||
|
echo "::warning::Could not extract branch_name from Generate logs after ${MAX_ATTEMPTS} attempts — auto-merge will use run_started_at fallback"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "branch_name=$BRANCH" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
auto-merge:
|
||||||
|
needs: [generate, resolve-branch]
|
||||||
|
if: ${{ !cancelled() && needs.generate.result == 'success' }}
|
||||||
|
uses: ./.github/workflows/auto-merge-speakeasy-pr.yaml
|
||||||
|
with:
|
||||||
|
run_started_at: ${{ needs.resolve-branch.outputs.run_started_at }}
|
||||||
|
branch_name: ${{ needs.resolve-branch.outputs.branch_name }}
|
||||||
|
secrets:
|
||||||
|
GH_DOCS_SYNC_APP_ID: ${{ secrets.GH_DOCS_SYNC_APP_ID }}
|
||||||
|
GH_DOCS_SYNC_APP_PRIVATE_KEY: ${{ secrets.GH_DOCS_SYNC_APP_PRIVATE_KEY }}
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ permissions:
|
|||||||
paths:
|
paths:
|
||||||
- .speakeasy/in.openapi.yaml
|
- .speakeasy/in.openapi.yaml
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: speakeasy-generate-spec-change
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
generate:
|
generate:
|
||||||
if: github.event.pull_request.merged == true || github.event_name == 'workflow_dispatch'
|
if: github.event.pull_request.merged == true || github.event_name == 'workflow_dispatch'
|
||||||
@@ -34,3 +38,67 @@ jobs:
|
|||||||
github_access_token: ${{ secrets.GITHUB_TOKEN }}
|
github_access_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
pypi_token: ${{ secrets.PYPI_TOKEN }}
|
pypi_token: ${{ secrets.PYPI_TOKEN }}
|
||||||
speakeasy_api_key: ${{ secrets.SPEAKEASY_API_KEY }}
|
speakeasy_api_key: ${{ secrets.SPEAKEASY_API_KEY }}
|
||||||
|
|
||||||
|
resolve-branch:
|
||||||
|
needs: generate
|
||||||
|
if: ${{ !cancelled() && needs.generate.result == 'success' }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
branch_name: ${{ steps.branch.outputs.branch_name }}
|
||||||
|
run_started_at: ${{ steps.branch.outputs.run_started_at }}
|
||||||
|
steps:
|
||||||
|
- name: Extract branch from Generate logs
|
||||||
|
id: branch
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
REPO="${{ github.repository }}"
|
||||||
|
RUN_ID="${{ github.run_id }}"
|
||||||
|
|
||||||
|
RUN_STARTED="${{ github.run_started_at }}"
|
||||||
|
if [ -z "$RUN_STARTED" ]; then
|
||||||
|
RUN_STARTED=$(gh run view "$RUN_ID" --repo "$REPO" --json startedAt --jq '.startedAt')
|
||||||
|
echo "Resolved run_started_at from API: $RUN_STARTED"
|
||||||
|
fi
|
||||||
|
echo "run_started_at=$RUN_STARTED" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
# Full-run logs are unavailable while the workflow is in progress;
|
||||||
|
# fetch logs from the completed generate job instead.
|
||||||
|
JOB_ID=$(gh run view "$RUN_ID" --repo "$REPO" --json jobs --jq \
|
||||||
|
'[.jobs[] | select(.name == "generate / Generate Target")] | .[0].databaseId // empty')
|
||||||
|
|
||||||
|
BRANCH=""
|
||||||
|
if [ -z "$JOB_ID" ]; then
|
||||||
|
echo "::warning::Could not find generate job id — auto-merge will use run_started_at fallback"
|
||||||
|
else
|
||||||
|
MAX_ATTEMPTS=12
|
||||||
|
INTERVAL=10
|
||||||
|
for attempt in $(seq 1 "$MAX_ATTEMPTS"); do
|
||||||
|
BRANCH=$(gh run view "$RUN_ID" --repo "$REPO" --job "$JOB_ID" --log 2>/dev/null \
|
||||||
|
| grep -oE 'branch_name=speakeasy-sdk-regen-[0-9]+' | tail -1 | cut -d= -f2 || true)
|
||||||
|
if [ -n "$BRANCH" ]; then
|
||||||
|
echo "Extracted branch_name=$BRANCH (attempt $attempt)"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ "$attempt" -lt "$MAX_ATTEMPTS" ]; then
|
||||||
|
echo "Job logs not ready — waiting ${INTERVAL}s (attempt $attempt/$MAX_ATTEMPTS)..."
|
||||||
|
sleep "$INTERVAL"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ -z "$BRANCH" ]; then
|
||||||
|
echo "::warning::Could not extract branch_name from Generate logs after ${MAX_ATTEMPTS} attempts — auto-merge will use run_started_at fallback"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "branch_name=$BRANCH" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
auto-merge:
|
||||||
|
needs: [generate, resolve-branch]
|
||||||
|
if: ${{ !cancelled() && needs.generate.result == 'success' }}
|
||||||
|
uses: ./.github/workflows/auto-merge-speakeasy-pr.yaml
|
||||||
|
with:
|
||||||
|
run_started_at: ${{ needs.resolve-branch.outputs.run_started_at }}
|
||||||
|
branch_name: ${{ needs.resolve-branch.outputs.branch_name }}
|
||||||
|
secrets:
|
||||||
|
GH_DOCS_SYNC_APP_ID: ${{ secrets.GH_DOCS_SYNC_APP_ID }}
|
||||||
|
GH_DOCS_SYNC_APP_PRIVATE_KEY: ${{ secrets.GH_DOCS_SYNC_APP_PRIVATE_KEY }}
|
||||||
|
|||||||
Reference in New Issue
Block a user