-
-
Notifications
You must be signed in to change notification settings - Fork 72
Live API healthcheck and test updates #151
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
e0c9d0f
b4c5cd9
ebffd59
b74169a
605cd04
c369abb
7635d24
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| name: Live API healthcheck | ||
|
|
||
| on: | ||
| schedule: | ||
| - cron: '0 2 * * 1' # Every Monday at 2 AM UTC | ||
| workflow_dispatch: | ||
|
|
||
| permissions: | ||
| issues: write | ||
|
|
||
| jobs: | ||
| live-api-healthcheck: | ||
| # Workflow logic: | ||
| # 1. Run tests against the live API (skip pytest-recording / vcr behavior) | ||
| # 2. IF tests pass -> Do nothing | ||
| # 3. IF tests fail -> Create issue (if no open issue with same title exists) | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v6 | ||
|
|
||
| - name: Install uv | ||
| uses: astral-sh/setup-uv@v7 | ||
| with: | ||
| python-version: "3.13" | ||
|
|
||
| - name: Install dependencies | ||
| run: make setup | ||
|
|
||
| - name: Run tests against live API | ||
| # Streaming endpoints can intermittently hang or time out for many | ||
| # minutes. To keep the healthcheck fast and reliable we skip tests | ||
| # marked with the `streaming` marker in this workflow and run the | ||
| # non-streaming test target instead. | ||
| run: make test_live_no_streaming | ||
| id: test | ||
| continue-on-error: true | ||
|
|
||
| - name: Check for existing issue | ||
| if: steps.test.outcome != 'success' | ||
| id: existing_issue | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| run: | | ||
| # Search for open issues with the specific title to avoid duplicates | ||
| issues=$(gh issue list --search "in:title Live API healthcheck - Test failures detected" --state open --json number) | ||
| issue_count=$(echo "$issues" | jq 'length') | ||
| if [ "$issue_count" -gt 0 ]; then | ||
| issue_number=$(echo "$issues" | jq -r '.[0].number') | ||
| echo "exists=true" >> $GITHUB_OUTPUT | ||
| echo "Existing issue #${issue_number} found, skipping creation" | ||
| else | ||
| echo "exists=false" >> $GITHUB_OUTPUT | ||
| echo "No existing issue found" | ||
| fi | ||
|
|
||
| - name: Create issue (tests failed - needs review) | ||
| if: steps.test.outcome != 'success' && steps.existing_issue.outputs.exists == 'false' | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| run: | | ||
| run_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" | ||
|
|
||
| gh issue create \ | ||
| --title "Live API healthcheck - Test failures detected" \ | ||
| --body "## Summary | ||
| Test failures detected when running tests against the live API. | ||
|
|
||
| ## Test Results | ||
| The live-run produced failing tests; the exact failure mode may vary (schema change, data mismatch, timeout, auth error, flaky test, etc.). | ||
|
|
||
| ## Action Required | ||
| 1. Review test failures in the [workflow run](${run_url}) | ||
| 2. Reproduce locally: \`make test_live_api\` | ||
| 3. If API changes are confirmed, either: | ||
| - Update the code/tests to match the new API | ||
| - Re-record affected cassettes manually | ||
| 4. To re-record cassettes, run locally: \`uv run pytest --record-mode=rewrite\` | ||
| 5. Run \`make test\` to verify fixes against recorded cassettes before merging | ||
|
|
||
| --- | ||
|
|
||
| **Note**: This issue is automatically created when the live API healthcheck detects possible API changes. Close this issue once the problems are resolved." |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,18 @@ | ||
| from __future__ import annotations | ||
|
|
||
| from typing import Literal, List | ||
| from typing_extensions import TypedDict | ||
| from .common import Speed | ||
| from typing import Generic, Literal, List, TypeVar | ||
| from typing_extensions import TypedDict, NotRequired | ||
| from .common import Color, Speed | ||
|
|
||
| OpeningExplorerRating = Literal[ | ||
| "0", "1000", "1200", "1400", "1600", "1800", "2000", "2200", "2500" | ||
| ] | ||
|
|
||
|
|
||
| MoveT = TypeVar("MoveT") | ||
| GameT = TypeVar("GameT") | ||
|
|
||
|
|
||
| class Opening(TypedDict): | ||
| # The eco code of this opening | ||
| eco: str | ||
|
|
@@ -27,7 +31,7 @@ class GameWithoutUci(TypedDict): | |
| # The id of the game | ||
| id: str | ||
| # The winner of the game. Draw if None | ||
| winner: Literal["white"] | Literal["black"] | None | ||
| winner: Color | None | ||
| # The speed of the game | ||
| speed: Speed | ||
| # The type of game | ||
|
|
@@ -42,11 +46,31 @@ class GameWithoutUci(TypedDict): | |
| month: str | ||
|
|
||
|
|
||
| class MastersGameWithoutUci(TypedDict): | ||
| # The id of the OTB master game | ||
| id: str | ||
| # The winner of the game. Draw if None | ||
| winner: Color | None | ||
| # The black player | ||
| black: Player | ||
| # The white player | ||
| white: Player | ||
| # The year of the game | ||
| year: int | ||
| # The month and year of the game. For example "2023-06" | ||
| month: NotRequired[str] | ||
|
|
||
|
|
||
| class Game(GameWithoutUci): | ||
| # The move in Universal Chess Interface notation | ||
| uci: str | ||
|
|
||
|
|
||
| class MastersGame(MastersGameWithoutUci): | ||
| # The move in Universal Chess Interface notation | ||
| uci: str | ||
|
|
||
|
|
||
| class Move(TypedDict): | ||
| # The move in Universal Chess Interface notation | ||
| uci: str | ||
|
|
@@ -62,9 +86,51 @@ class Move(TypedDict): | |
| draws: int | ||
| # The game where the move was played | ||
| game: GameWithoutUci | None | ||
| # The opening info for this move | ||
| opening: Opening | None | ||
|
Comment on lines
88
to
+90
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. most likely not required
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking at this schema doc have it has required. |
||
|
|
||
|
|
||
| class PlayerMove(TypedDict): | ||
| # The move in Universal Chess Interface notation | ||
| uci: str | ||
| # The move in algebraic notation | ||
| san: str | ||
| # The average opponent rating in games with this move | ||
| averageOpponentRating: int | ||
| # The performance rating for this move | ||
| performance: int | ||
| # The number of white winners after this move | ||
| white: int | ||
| # The number of black winners after this move | ||
| black: int | ||
| # The number of draws after this move | ||
| draws: int | ||
| # The game where the move was played | ||
| game: GameWithoutUci | None | ||
| # The opening info for this move | ||
| opening: Opening | None | ||
|
Comment on lines
+109
to
+111
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking at this schema doc have it has required. |
||
|
|
||
|
|
||
| class OpeningStatistic(TypedDict): | ||
| class MastersMove(TypedDict): | ||
| # The move in Universal Chess Interface notation | ||
| uci: str | ||
| # The move in algebraic notation | ||
| san: str | ||
| # The average rating of games in the position after this move | ||
| averageRating: int | ||
| # The number of white winners after this move | ||
| white: int | ||
| # The number of black winners after this move | ||
| black: int | ||
| # The number of draws after this move | ||
| draws: int | ||
| # The OTB master game where the move was played | ||
| game: MastersGameWithoutUci | None | ||
| # The opening info for this move | ||
| opening: Opening | None | ||
|
Comment on lines
+128
to
+130
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking at this schema doc have it has required. |
||
|
|
||
|
|
||
| class BaseOpeningStatistic(TypedDict, Generic[MoveT, GameT]): | ||
| # Number of game won by white from this position | ||
| white: int | ||
| # Number of game won by black from this position | ||
|
|
@@ -73,9 +139,24 @@ class OpeningStatistic(TypedDict): | |
| black: int | ||
| # Opening info of this position | ||
| opening: Opening | None | ||
| # The list of moves played by players from this position | ||
| moves: List[Move] | ||
| # recent games with this opening | ||
| recentGames: List[Game] | ||
| # The list of moves played from this position | ||
| moves: List[MoveT] | ||
|
|
||
|
|
||
| class OpeningStatistic(BaseOpeningStatistic[Move, Game]): | ||
| # top rating games with this opening | ||
| topGames: List[Game] | ||
| # recent games with this opening (optional per schema) | ||
| recentGames: NotRequired[List[Game]] | ||
|
|
||
|
|
||
| class PlayerOpeningStatistic(BaseOpeningStatistic[PlayerMove, Game]): | ||
| # Queue position for indexing (present when wait_for_indexing parameter used) | ||
| queuePosition: int | ||
| # recent games with this opening | ||
| recentGames: List[Game] | ||
|
|
||
|
|
||
| class MastersOpeningStatistic(BaseOpeningStatistic[MastersMove, MastersGame]): | ||
| # top rating OTB master games with this opening | ||
| topGames: List[MastersGame] | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this would be not required
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am using this schemas doc as a reference, is there another reference I should be looking at?