Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ on:
push:
branches: [main]
pull_request:
# Dispatched by spec-drift.yml on auto-regen branches, whose GITHUB_TOKEN
# pushes cannot fire pull_request events.
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/generated.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ name: Generated code check

on:
pull_request:
# Dispatched by spec-drift.yml on auto-regen branches, whose GITHUB_TOKEN
# pushes cannot fire pull_request events.
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand Down
76 changes: 56 additions & 20 deletions .github/workflows/spec-drift.yml
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
name: Spec drift check
name: Spec drift — auto regen PR

on:
schedule:
- cron: "0 9 * * 1"
workflow_dispatch:

permissions:
contents: read
issues: write
contents: write
pull-requests: write
actions: write

jobs:
check:
regen:
runs-on: ubuntu-latest
timeout-minutes: 5
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: ./.github/actions/setup-uv
- run: uv sync --group regen
- name: Fetch latest spec
run: |
BASE_URL=$(jq -r '.servers[0].url' openapi.json)
Expand All @@ -26,27 +29,60 @@ jobs:
id: drift
run: |
norm() { jq -S 'del(.info.description)' "$1"; }
if ! diff -u --label vendored --label upstream <(norm openapi.json) <(norm /tmp/latest-spec.json) > /tmp/spec.diff; then
if ! diff -u --label vendored --label upstream \
<(norm openapi.json) <(norm /tmp/latest-spec.json) > /tmp/spec.diff; then
echo "drifted=true" >> "$GITHUB_OUTPUT"
fi
- name: Open or update issue
- name: Regenerate client
if: steps.drift.outputs.drifted == 'true'
run: |
cp /tmp/latest-spec.json openapi.json
if [[ -f openapi-overlay.yaml ]]; then
uv run oas-patch overlay openapi.json openapi-overlay.yaml -o /tmp/patched-spec.json
else
cp openapi.json /tmp/patched-spec.json
fi
uv run openapi-python-client generate \
--path /tmp/patched-spec.json \
--meta none \
--config openapi-python-client-config.yaml \
--custom-template-path custom-templates \
--output-path ionq_core \
--overwrite
- name: Compose PR body
if: steps.drift.outputs.drifted == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
{
echo "The spec at ${BASE_URL}/api-docs has diverged from the vendored openapi.json. Fetch the new spec and regenerate the client."
printf '\n<details><summary>Diff (sorted, pretty-printed JSON)</summary>\n\n```diff\n'
echo "The spec at \`${BASE_URL}/api-docs\` has diverged from the vendored \`openapi.json\`. This PR fetches the new spec and regenerates the client."
printf '\n<details><summary>Spec diff (sorted, pretty-printed JSON)</summary>\n\n```diff\n'
head -c 60000 /tmp/spec.diff
[[ $(wc -c < /tmp/spec.diff) -gt 60000 ]] && printf '\n... (truncated)\n'
printf '```\n</details>\n'
} > /tmp/body.md
existing=$(gh issue list --label spec-drift --state open --json number --jq '.[0].number // empty')
if [[ -z "$existing" ]]; then
gh issue create \
--title "OpenAPI spec has changed upstream" \
--body-file /tmp/body.md \
--label spec-drift
else
gh issue edit "$existing" --body-file /tmp/body.md
fi
# Pushes and PR creation made with GITHUB_TOKEN never fire pull_request
# events, so the required checks are dispatched explicitly below —
# workflow_dispatch is exempt from that suppression. Team review comes
# from CODEOWNERS (GITHUB_TOKEN cannot request team reviewers itself).
- name: Open or update PR
if: steps.drift.outputs.drifted == 'true'
id: pr
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
branch: spec-drift/auto-regen
base: main
add-paths: |
openapi.json
ionq_core/
commit-message: Regenerate client for updated OpenAPI spec
title: Regenerate client for updated OpenAPI spec
body-path: /tmp/body.md
labels: spec-drift
- name: Trigger required checks
if: steps.pr.outputs.pull-request-operation == 'created' || steps.pr.outputs.pull-request-operation == 'updated'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# CodeQL runs via GitHub's default setup and has no dispatchable
# workflow file — confirm it reports on regen PRs.
gh workflow run ci.yml --ref spec-drift/auto-regen
gh workflow run generated.yml --ref spec-drift/auto-regen