Docs Health Check #1096
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Docs Health Check | |
| on: | |
| schedule: | |
| - cron: '0 * * * *' # Every hour | |
| workflow_dispatch: # Manual trigger | |
| jobs: | |
| health-check: | |
| name: Check docs accessibility | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check endpoints | |
| id: check | |
| run: | | |
| BASE_URL="https://docs.composio.dev" | |
| FAIL_FILE=$(mktemp) | |
| CHECKED=0 | |
| FAIL_COUNT=0 | |
| check_url() { | |
| local label="$1" | |
| local url="$2" | |
| shift 2 | |
| CHECKED=$((CHECKED + 1)) | |
| local attempt=0 | |
| local STATUS="000" | |
| while [ "$attempt" -lt 2 ]; do | |
| if STATUS=$(curl -sL -o /dev/null -w "%{http_code}" --max-time 15 "$@" "$url" 2>/dev/null); then | |
| : | |
| else | |
| STATUS="000" | |
| fi | |
| if [ "$STATUS" -ge 400 2>/dev/null ] || [ "$STATUS" = "000" ]; then | |
| attempt=$((attempt + 1)) | |
| [ "$attempt" -lt 2 ] && sleep 3 | |
| else | |
| break | |
| fi | |
| done | |
| if [ "$STATUS" -ge 400 2>/dev/null ] || [ "$STATUS" = "000" ]; then | |
| echo "FAIL: ${label} → ${STATUS}" | |
| echo "${label} → ${STATUS}" >> "$FAIL_FILE" | |
| FAIL_COUNT=$((FAIL_COUNT + 1)) | |
| else | |
| echo " OK: ${label} → ${STATUS}" | |
| fi | |
| } | |
| # LLM/AI agent entry points | |
| check_url "/llms.txt" "${BASE_URL}/llms.txt" | |
| check_url "/llms-full.txt" "${BASE_URL}/llms-full.txt" | |
| check_url "/docs/quickstart.md" "${BASE_URL}/docs/quickstart.md" | |
| check_url "/docs/tools-and-toolkits.md" "${BASE_URL}/docs/tools-and-toolkits.md" | |
| # Main pages | |
| check_url "/docs" "${BASE_URL}/docs" | |
| check_url "/docs/quickstart" "${BASE_URL}/docs/quickstart" | |
| check_url "/docs/authentication" "${BASE_URL}/docs/authentication" | |
| check_url "/docs/tools-and-toolkits" "${BASE_URL}/docs/tools-and-toolkits" | |
| check_url "/docs/users-and-sessions" "${BASE_URL}/docs/users-and-sessions" | |
| check_url "/docs/configuring-sessions" "${BASE_URL}/docs/configuring-sessions" | |
| check_url "/cookbooks" "${BASE_URL}/cookbooks" | |
| check_url "/toolkits" "${BASE_URL}/toolkits" | |
| check_url "/reference" "${BASE_URL}/reference" | |
| # Provider pages | |
| check_url "/docs/providers/openai" "${BASE_URL}/docs/providers/openai" | |
| check_url "/docs/providers/vercel" "${BASE_URL}/docs/providers/vercel" | |
| check_url "/docs/providers/anthropic" "${BASE_URL}/docs/providers/anthropic" | |
| # Key sub-pages | |
| check_url "/docs/tools-direct/fetching-tools" "${BASE_URL}/docs/tools-direct/fetching-tools" | |
| check_url "/docs/tools-direct/executing-tools" "${BASE_URL}/docs/tools-direct/executing-tools" | |
| check_url "/docs/authenticating-users/in-chat-authentication" "${BASE_URL}/docs/authenticating-users/in-chat-authentication" | |
| check_url "/docs/common-faq" "${BASE_URL}/docs/common-faq" | |
| # Markdown content negotiation | |
| check_url "/docs/quickstart (markdown)" "${BASE_URL}/docs/quickstart" -H "Accept: text/markdown" | |
| check_url "/docs/tools-and-toolkits (markdown)" "${BASE_URL}/docs/tools-and-toolkits" -H "Accept: text/markdown" | |
| check_url "/docs/authentication (markdown)" "${BASE_URL}/docs/authentication" -H "Accept: text/markdown" | |
| check_url "/docs/providers/openai (markdown)" "${BASE_URL}/docs/providers/openai" -H "Accept: text/markdown" | |
| check_url "/cookbooks (markdown)" "${BASE_URL}/cookbooks" -H "Accept: text/markdown" | |
| if [ "$FAIL_COUNT" -gt 0 ]; then | |
| echo "has_failures=true" >> $GITHUB_OUTPUT | |
| # Build the Slack message with real newlines | |
| FAIL_LIST=$(sed 's/^/• /' "$FAIL_FILE") | |
| RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" | |
| PAYLOAD=$(jq -n \ | |
| --arg fails "$FAIL_LIST" \ | |
| --arg count "$FAIL_COUNT" \ | |
| --arg total "$CHECKED" \ | |
| --arg url "$RUN_URL" \ | |
| '{text: ("🚨 *Docs Health Check*\n\n" + $count + "/" + $total + " endpoints failing:\n" + $fails + "\n\n<" + $url + "|View logs>")}') | |
| echo "slack_payload<<EOF" >> $GITHUB_OUTPUT | |
| echo "$PAYLOAD" >> $GITHUB_OUTPUT | |
| echo "EOF" >> $GITHUB_OUTPUT | |
| else | |
| echo "has_failures=false" >> $GITHUB_OUTPUT | |
| echo "All $CHECKED endpoints healthy" | |
| fi | |
| rm -f "$FAIL_FILE" | |
| - name: Notify Slack | |
| if: steps.check.outputs.has_failures == 'true' | |
| uses: slackapi/slack-github-action@fcfb566f8b0aab22203f066d80ca1d7e4b5d05b3 # v1.27.1 | |
| with: | |
| payload: ${{ steps.check.outputs.slack_payload }} | |
| env: | |
| SLACK_WEBHOOK_URL: ${{ secrets.SLACK_POD_DX_WEBHOOK_URL }} | |
| - name: Fail on unhealthy endpoints | |
| if: steps.check.outputs.has_failures == 'true' | |
| run: exit 1 |