From 4d3c12e3c90f1175dfd575c695a6756092608b4b Mon Sep 17 00:00:00 2001 From: Rohit Agarwal Date: Sun, 27 Sep 2026 17:05:53 +0530 Subject: [PATCH 1/2] ci: make the Mintlify trigger wait for a fresh spec and report failures The job called Mintlify about 5s after each push, but raw.githubusercontent.com caches the spec for 300s, so builds could use a stale spec. curl also ignored HTTP errors and the job never checked the deployment result, so failures showed green. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/mintlify-update.yml | 66 +++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 5 deletions(-) diff --git a/.github/workflows/mintlify-update.yml b/.github/workflows/mintlify-update.yml index 1e4ed663..14272d62 100644 --- a/.github/workflows/mintlify-update.yml +++ b/.github/workflows/mintlify-update.yml @@ -4,14 +4,70 @@ on: push: branches: - master + workflow_dispatch: + +concurrency: + group: mintlify-update + cancel-in-progress: true jobs: trigger-update: runs-on: ubuntu-latest - + timeout-minutes: 30 + env: + SPEC_URL: https://raw.githubusercontent.com/Portkey-AI/openapi/refs/heads/master/openapi.yaml + MINTLIFY_TOKEN: ${{ secrets.MINTLIFY_TOKEN }} + MINTLIFY_PROJECT_ID: ${{ secrets.MINTLIFY_PROJECT_ID }} + steps: - - name: Trigger Mintlify Update + - uses: actions/checkout@v4 + + # Mintlify builds from SPEC_URL, which raw.githubusercontent.com caches for up to 300s. + - name: Wait for the raw spec cache to expire + if: github.event_name == 'push' + run: sleep 310 + + - name: Check that the raw spec matches this commit + run: | + expected=$(sha256sum openapi.yaml | cut -d' ' -f1) + actual=$(curl -sSfL "$SPEC_URL" | sha256sum | cut -d' ' -f1) + if [ "$expected" != "$actual" ]; then + echo "::error::$SPEC_URL does not match openapi.yaml at $GITHUB_SHA" + exit 1 + fi + + - name: Trigger Mintlify update + id: trigger + run: | + resp=$(curl -sS --fail-with-body --request POST \ + --url "https://api.mintlify.com/v1/project/update/$MINTLIFY_PROJECT_ID" \ + --header "Authorization: Bearer $MINTLIFY_TOKEN") + status_id=$(jq -r '.statusId // empty' <<<"$resp") + if [ -z "$status_id" ]; then + echo "::error::No statusId in Mintlify response: $resp" + exit 1 + fi + echo "status_id=$status_id" >> "$GITHUB_OUTPUT" + + - name: Wait for Mintlify deployment + env: + STATUS_ID: ${{ steps.trigger.outputs.status_id }} run: | - curl --request POST \ - --url https://api.mintlify.com/v1/project/update/${{ secrets.MINTLIFY_PROJECT_ID }} \ - --header 'Authorization: Bearer ${{ secrets.MINTLIFY_TOKEN }}' + for _ in $(seq 1 60); do + resp=$(curl -sS --fail-with-body \ + --url "https://api.mintlify.com/v1/project/update-status/$STATUS_ID" \ + --header "Authorization: Bearer $MINTLIFY_TOKEN") + status=$(jq -r '.status' <<<"$resp") + echo "Mintlify status: $status" + case "$status" in + success) exit 0 ;; + failure) + jq -r '.summary // empty, (.logs // [])[]' <<<"$resp" + echo "::error::Mintlify deployment failed" + exit 1 + ;; + esac + sleep 20 + done + echo "::error::Mintlify deployment did not finish in 20 minutes" + exit 1 From 4714e242972e538ba84536df38baa6bbe3430b06 Mon Sep 17 00:00:00 2001 From: Rohit Agarwal Date: Sun, 27 Sep 2026 17:10:09 +0530 Subject: [PATCH 2/2] ci: queue Mintlify deploys instead of cancelling them Cancelling a run after the POST left its Mintlify build running, so builds could finish out of order. Split the job: the wait job can be cancelled because it has no remote side effects, and the deploy job queues. Also restrict the workflow to master, because the spec check always reads the master URL. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/mintlify-update.yml | 30 ++++++++++++++++++++------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/.github/workflows/mintlify-update.yml b/.github/workflows/mintlify-update.yml index 14272d62..5f2a273d 100644 --- a/.github/workflows/mintlify-update.yml +++ b/.github/workflows/mintlify-update.yml @@ -6,18 +6,18 @@ on: - master workflow_dispatch: -concurrency: - group: mintlify-update - cancel-in-progress: true - jobs: - trigger-update: + wait-for-spec: + # Mintlify always builds from master, so a run on any other ref would check the wrong spec. + if: github.ref == 'refs/heads/master' runs-on: ubuntu-latest - timeout-minutes: 30 + timeout-minutes: 10 + # Safe to cancel: nothing has been sent to Mintlify yet. + concurrency: + group: mintlify-wait + cancel-in-progress: true env: SPEC_URL: https://raw.githubusercontent.com/Portkey-AI/openapi/refs/heads/master/openapi.yaml - MINTLIFY_TOKEN: ${{ secrets.MINTLIFY_TOKEN }} - MINTLIFY_PROJECT_ID: ${{ secrets.MINTLIFY_PROJECT_ID }} steps: - uses: actions/checkout@v4 @@ -36,6 +36,20 @@ jobs: exit 1 fi + deploy: + needs: wait-for-spec + runs-on: ubuntu-latest + timeout-minutes: 25 + # Never cancel: a cancelled run cannot stop a Mintlify build it already started. + # Queueing makes each build finish before the next one starts. + concurrency: + group: mintlify-deploy + cancel-in-progress: false + env: + MINTLIFY_TOKEN: ${{ secrets.MINTLIFY_TOKEN }} + MINTLIFY_PROJECT_ID: ${{ secrets.MINTLIFY_PROJECT_ID }} + + steps: - name: Trigger Mintlify update id: trigger run: |