diff --git a/.github/workflows/rpc_healthcheck.yml b/.github/workflows/rpc_healthcheck.yml new file mode 100644 index 00000000..cd08d189 --- /dev/null +++ b/.github/workflows/rpc_healthcheck.yml @@ -0,0 +1,248 @@ +name: RPC Healthcheck + +permissions: + contents: read + pull-requests: write + +on: + schedule: + - cron: '41 2 * * *' + - cron: '41 10 * * *' + - cron: '41 18 * * *' + workflow_dispatch: + + +jobs: + check-networkinfo: + name: Check ${{ matrix.network }} networkInfo + if: ${{ github.repository == 'QuarkChain/goquarkchain' }} + runs-on: ubuntu-latest + timeout-minutes: 5 + strategy: + fail-fast: false + matrix: + include: + - network: mainnet + rpc_url: https://rpc.indexer.mainnet.quarkchain.io:38391 + expected_network_id: "0x1" + - network: devnet + rpc_url: https://rpc.indexer.devnet.quarkchain.io:38392 + expected_network_id: "0xff" + - network: mainnetHost + rpc_url: http://65.108.121.223:38391 + expected_network_id: "0x1" + - network: devnetHost + rpc_url: http://50.112.62.65:38391 + expected_network_id: "0xff" + + steps: + - name: Check endpoint JSON field + shell: bash + env: + RPC_URL: ${{ matrix.rpc_url }} + EXPECTED_NETWORK_ID: ${{ matrix.expected_network_id }} + NETWORK_NAME: ${{ matrix.network }} + run: | + set -euo pipefail + + payload='{"jsonrpc":"2.0","id":"id","method":"networkInfo","params":[]}' + resp_file="${RUNNER_TEMP}/networkinfo_${NETWORK_NAME}.json" + report_file="${RUNNER_TEMP}/networkinfo_report_${NETWORK_NAME}.json" + : > "$resp_file" + + code="$( + curl --silent --show-error --location \ + --retry 3 --retry-delay 5 --retry-all-errors \ + --connect-timeout 10 --max-time 30 \ + -X POST \ + -H 'Content-Type: application/json' \ + --data "$payload" \ + --output "$resp_file" --write-out '%{http_code}' \ + "$RPC_URL" \ + || echo '000' + )" + + result="success" + error_msg="" + + if [[ "$code" != "200" ]]; then + result="failure" + error_msg="HTTP status not 200: $code" + elif ! jq -e --arg expected "$EXPECTED_NETWORK_ID" '.result.networkId == $expected' "$resp_file" > /dev/null; then + result="failure" + error_msg="JSON check failed: .result.networkId == $EXPECTED_NETWORK_ID" + fi + + jq -n \ + --arg network "$NETWORK_NAME" \ + --arg rpc_url "$RPC_URL" \ + --arg result "$result" \ + --arg error "$error_msg" \ + '{network: $network, rpc_url: $rpc_url, result: $result, error: $error}' > "$report_file" + + if [[ "$result" != "success" ]]; then + echo "[$NETWORK_NAME] $error_msg" + cat "$resp_file" + exit 1 + fi + + echo "[$NETWORK_NAME] JSON check passed: .result.networkId == $EXPECTED_NETWORK_ID" + + - name: Upload endpoint report + if: ${{ always() }} + uses: actions/upload-artifact@v4 + with: + name: rpc-healthcheck-${{ matrix.network }} + path: ${{ runner.temp }}/networkinfo_report_${{ matrix.network }}.json + if-no-files-found: error + + notify: + name: Notify (email) + runs-on: ubuntu-latest + timeout-minutes: 5 + needs: + - check-networkinfo + if: ${{ always() && github.repository == 'QuarkChain/goquarkchain' }} + + steps: + - name: Download endpoint reports + uses: actions/download-artifact@v4 + with: + pattern: rpc-healthcheck-* + merge-multiple: true + path: ${{ runner.temp }}/rpc-healthcheck + + - name: Compose email + id: compose + shell: bash + env: + EVENT_NAME: ${{ github.event_name }} + EVENT_SCHEDULE: ${{ github.event.schedule }} + CHECK_RESULT: ${{ needs.check-networkinfo.result }} + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + run: | + set -euo pipefail + send=false + overall="OK" + report_dir="${RUNNER_TEMP}/rpc-healthcheck" + + table_rows_with_error='' + table_rows_no_error='' + html_rows_with_error='' + html_rows_no_error='' + + shopt -s nullglob + report_files=("$report_dir"/*.json) + if [[ ${#report_files[@]} -eq 0 ]]; then + overall="FAILED" + send=true + table_rows_with_error='| unknown | unknown | failure | missing endpoint report artifact |' + html_rows_with_error='
QuarkChain RPC Healthcheck: ${overall}
" >> "$GITHUB_OUTPUT" + echo "Event: ${EVENT_NAME}
Schedule: ${EVENT_SCHEDULE:-N/A}
Run: ${RUN_URL}
| network | rpc_url | result | |
|---|---|---|---|
| network | rpc_url | result | error |