Skip to content

feature: Add uses to /maps endpoint - #473

Merged
TeKrop merged 2 commits into
TeKrop:mainfrom
RealGatt:feature/map-uses
Oct 17, 2026
Merged

TeKrop merged 2 commits into
TeKrop:mainfrom
RealGatt:feature/map-uses

Conversation

@RealGatt

@RealGatt RealGatt commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

I constantly had to do manual sorting for valid maps within my applications, figured this was a better system.

Watchpoint: Grimsvotn was also misnamed, this PR fixes that.

Add a uses array to each map returned by /maps so clients can distinguish Standard, Stadium, Arcade, Workshop, and Training maps. The field supports multiple values, such as ["standard", "stadium"] for Busan.

Classifications are stored in the maps CSV and exposed through the parser and a typed response field. Assault and Clash maps are classified as Arcade-only, Wuxing University as Stadium-only, Workshop maps as Workshop, and Practice Range as Training. Existing map fields and gamemode filtering are preserved.

All 59 existing maps were reviewed against the Overwatch Wiki map list,

Validation:

  • Type checking, Ruff linting and formatting checks passed.
  • All seven import-linter architecture contracts passed.
[
  {
    "key": "aatlis",
    "name": "Aatlis",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/aatlis.jpg",
    "gamemodes": [
      "flashpoint"
    ],
    "uses": [
      "standard"
    ],
    "location": "Morocco",
    "country_code": "MA"
  },
  {
    "key": "antarctic-peninsula",
    "name": "Antarctic Peninsula",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/antarctic-peninsula.jpg",
    "gamemodes": [
      "control"
    ],
    "uses": [
      "standard"
    ],
    "location": "Antarctica",
    "country_code": "AQ"
  },
  {
    "key": "anubis",
    "name": "Temple of Anubis",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/anubis.jpg",
    "gamemodes": [
      "assault"
    ],
    "uses": [
      "arcade"
    ],
    "location": "Giza Plateau, Egypt",
    "country_code": "EG"
  },
  {
    "key": "arena-victoriae",
    "name": "Arena Victoriae",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/arena-victoriae.jpg",
    "gamemodes": [
      "control"
    ],
    "uses": [
      "stadium"
    ],
    "location": "Colosseo, Rome, Italy",
    "country_code": "IT"
  },
  {
    "key": "ayutthaya",
    "name": "Ayutthaya",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/ayutthaya.jpg",
    "gamemodes": [
      "capture-the-flag"
    ],
    "uses": [
      "arcade"
    ],
    "location": "Thailand",
    "country_code": "TH"
  },
  {
    "key": "black-forest",
    "name": "Black Forest",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/black-forest.jpg",
    "gamemodes": [
      "elimination"
    ],
    "uses": [
      "arcade"
    ],
    "location": "Germany",
    "country_code": "DE"
  },
  {
    "key": "blizzard-world",
    "name": "Blizzard World",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/blizzard-world.jpg",
    "gamemodes": [
      "hybrid"
    ],
    "uses": [
      "standard"
    ],
    "location": "Irvine, California, United States",
    "country_code": "US"
  },
  {
    "key": "busan",
    "name": "Busan",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/busan.jpg",
    "gamemodes": [
      "control"
    ],
    "uses": [
      "standard",
      "stadium"
    ],
    "location": "South Korea",
    "country_code": "KR"
  },
  {
    "key": "castillo",
    "name": "Castillo",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/castillo.jpg",
    "gamemodes": [
      "elimination"
    ],
    "uses": [
      "arcade"
    ],
    "location": "Mexico",
    "country_code": "MX"
  },
  {
    "key": "chateau-guillard",
    "name": "Château Guillard",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/chateau-guillard.jpg",
    "gamemodes": [
      "deathmatch",
      "team-deathmatch"
    ],
    "uses": [
      "arcade"
    ],
    "location": "Annecy, France",
    "country_code": "FR"
  },
  {
    "key": "circuit-royal",
    "name": "Circuit Royal",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/circuit-royal.jpg",
    "gamemodes": [
      "escort"
    ],
    "uses": [
      "standard"
    ],
    "location": "Monte Carlo, Monaco",
    "country_code": "MC"
  },
  {
    "key": "colosseo",
    "name": "Colosseo",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/colosseo.jpg",
    "gamemodes": [
      "push"
    ],
    "uses": [
      "standard",
      "stadium"
    ],
    "location": "Rome, Italy",
    "country_code": "IT"
  },
  {
    "key": "dorado",
    "name": "Dorado",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/dorado.jpg",
    "gamemodes": [
      "escort"
    ],
    "uses": [
      "standard"
    ],
    "location": "Mexico",
    "country_code": "MX"
  },
  {
    "key": "ecopoint-antarctica",
    "name": "Ecopoint: Antarctica",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/ecopoint-antarctica.jpg",
    "gamemodes": [
      "elimination"
    ],
    "uses": [
      "arcade"
    ],
    "location": "Antarctica",
    "country_code": "AQ"
  },
  {
    "key": "eichenwalde",
    "name": "Eichenwalde",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/eichenwalde.jpg",
    "gamemodes": [
      "hybrid"
    ],
    "uses": [
      "standard"
    ],
    "location": "Stuttgart, Germany",
    "country_code": "DE"
  },
  {
    "key": "esperanca",
    "name": "Esperança",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/esperanca.jpg",
    "gamemodes": [
      "push"
    ],
    "uses": [
      "standard",
      "stadium"
    ],
    "location": "Portugal",
    "country_code": "PT"
  },
  {
    "key": "gogadoro",
    "name": "Gogadoro",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/gogadoro.jpg",
    "gamemodes": [
      "control"
    ],
    "uses": [
      "stadium"
    ],
    "location": "Busan, South Korea",
    "country_code": "KR"
  },
  {
    "key": "grimsvotn",
    "name": "Grímsvötn",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/grimsvotn.jpg",
    "gamemodes": [
      "escort"
    ],
    "uses": [
      "standard"
    ],
    "location": "Iceland",
    "country_code": "IS"
  },
  {
    "key": "hanamura",
    "name": "Hanamura",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/hanamura.jpg",
    "gamemodes": [
      "assault"
    ],
    "uses": [
      "arcade"
    ],
    "location": "Tokyo, Japan",
    "country_code": "JP"
  },
  {
    "key": "hanaoka",
    "name": "Hanaoka",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/hanaoka.jpg",
    "gamemodes": [
      "clash"
    ],
    "uses": [
      "arcade"
    ],
    "location": "Tokyo, Japan",
    "country_code": "JP"
  },
  {
    "key": "havana",
    "name": "Havana",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/havana.jpg",
    "gamemodes": [
      "escort"
    ],
    "uses": [
      "standard"
    ],
    "location": "Havana, Cuba",
    "country_code": "CU"
  },
  {
    "key": "hollywood",
    "name": "Hollywood",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/hollywood.jpg",
    "gamemodes": [
      "hybrid"
    ],
    "uses": [
      "standard"
    ],
    "location": "Los Angeles, United States",
    "country_code": "US"
  },
  {
    "key": "horizon",
    "name": "Horizon Lunar Colony",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/horizon.jpg",
    "gamemodes": [
      "assault"
    ],
    "uses": [
      "arcade"
    ],
    "location": "Earth's moon",
    "country_code": null
  },
  {
    "key": "ilios",
    "name": "Ilios",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/ilios.jpg",
    "gamemodes": [
      "control"
    ],
    "uses": [
      "standard",
      "stadium"
    ],
    "location": "Greece",
    "country_code": "GR"
  },
  {
    "key": "junkertown",
    "name": "Junkertown",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/junkertown.jpg",
    "gamemodes": [
      "escort"
    ],
    "uses": [
      "standard"
    ],
    "location": "Central Australia",
    "country_code": "AU"
  },
  {
    "key": "lijiang-tower",
    "name": "Lijiang Tower",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/lijiang-tower.jpg",
    "gamemodes": [
      "control"
    ],
    "uses": [
      "standard",
      "stadium"
    ],
    "location": "China",
    "country_code": "CN"
  },
  {
    "key": "kanezaka",
    "name": "Kanezaka",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/kanezaka.jpg",
    "gamemodes": [
      "deathmatch",
      "team-deathmatch"
    ],
    "uses": [
      "arcade"
    ],
    "location": "Tokyo, Japan",
    "country_code": "JP"
  },
  {
    "key": "kings-row",
    "name": "King’s Row",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/kings-row.jpg",
    "gamemodes": [
      "hybrid"
    ],
    "uses": [
      "standard"
    ],
    "location": "London, United Kingdom",
    "country_code": "UK"
  },
  {
    "key": "malevento",
    "name": "Malevento",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/malevento.jpg",
    "gamemodes": [
      "deathmatch",
      "team-deathmatch"
    ],
    "uses": [
      "arcade"
    ],
    "location": "Italy",
    "country_code": "IT"
  },
  {
    "key": "midtown",
    "name": "Midtown",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/midtown.jpg",
    "gamemodes": [
      "hybrid"
    ],
    "uses": [
      "standard"
    ],
    "location": "New York, United States",
    "country_code": "US"
  },
  {
    "key": "necropolis",
    "name": "Necropolis",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/necropolis.jpg",
    "gamemodes": [
      "elimination"
    ],
    "uses": [
      "arcade"
    ],
    "location": "Egypt",
    "country_code": "EG"
  },
  {
    "key": "nepal",
    "name": "Nepal",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/nepal.jpg",
    "gamemodes": [
      "control"
    ],
    "uses": [
      "standard",
      "stadium"
    ],
    "location": "Nepal",
    "country_code": "NP"
  },
  {
    "key": "neon-junction",
    "name": "Neon Junction",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/neon-junction.jpg",
    "gamemodes": [
      "hybrid"
    ],
    "uses": [
      "standard"
    ],
    "location": "Japan",
    "country_code": "JP"
  },
  {
    "key": "new-junk-city",
    "name": "New Junk City",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/new-junk-city.jpg",
    "gamemodes": [
      "flashpoint"
    ],
    "uses": [
      "standard"
    ],
    "location": "Central Australia",
    "country_code": "AU"
  },
  {
    "key": "new-queen-street",
    "name": "New Queen Street",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/new-queen-street.jpg",
    "gamemodes": [
      "push"
    ],
    "uses": [
      "standard"
    ],
    "location": "Toronto, Canada",
    "country_code": "CA"
  },
  {
    "key": "numbani",
    "name": "Numbani",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/numbani.jpg",
    "gamemodes": [
      "hybrid"
    ],
    "uses": [
      "standard"
    ],
    "location": "Numbani (near Nigeria)",
    "country_code": null
  },
  {
    "key": "oasis",
    "name": "Oasis",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/oasis.jpg",
    "gamemodes": [
      "control"
    ],
    "uses": [
      "standard",
      "stadium"
    ],
    "location": "Iraq",
    "country_code": "IQ"
  },
  {
    "key": "paraiso",
    "name": "Paraíso",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/paraiso.jpg",
    "gamemodes": [
      "hybrid"
    ],
    "uses": [
      "standard"
    ],
    "location": "Rio de Janeiro, Brazil",
    "country_code": "BR"
  },
  {
    "key": "paris",
    "name": "Paris",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/paris.jpg",
    "gamemodes": [
      "assault"
    ],
    "uses": [
      "arcade"
    ],
    "location": "Paris, France",
    "country_code": "FR"
  },
  {
    "key": "petra",
    "name": "Petra",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/petra.jpg",
    "gamemodes": [
      "deathmatch",
      "team-deathmatch"
    ],
    "uses": [
      "arcade"
    ],
    "location": "Southern Jordan",
    "country_code": "JO"
  },
  {
    "key": "place-lacroix",
    "name": "Place Lacroix",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/place-lacroix.jpg",
    "gamemodes": [
      "push"
    ],
    "uses": [
      "stadium"
    ],
    "location": "Paris, France",
    "country_code": "FR"
  },
  {
    "key": "powder-keg-mine",
    "name": "Powder Keg Mine",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/powder-keg-mine.jpg",
    "gamemodes": [
      "payload-race"
    ],
    "uses": [
      "stadium"
    ],
    "location": "Deadlock Gorge, Arizona, United States",
    "country_code": "US"
  },
  {
    "key": "practice-range",
    "name": "Practice Range",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/practice-range.jpg",
    "gamemodes": [
      "practice-range"
    ],
    "uses": [
      "training"
    ],
    "location": "Swiss HQ",
    "country_code": "CH"
  },
  {
    "key": "redwood-dam",
    "name": "Redwood Dam",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/redwood-dam.jpg",
    "gamemodes": [
      "push"
    ],
    "uses": [
      "stadium"
    ],
    "location": "Gibraltar",
    "country_code": "GI"
  },
  {
    "key": "rialto",
    "name": "Rialto",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/rialto.jpg",
    "gamemodes": [
      "escort"
    ],
    "uses": [
      "standard"
    ],
    "location": "Venice, Italy",
    "country_code": "IT"
  },
  {
    "key": "route-66",
    "name": "Route 66",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/route-66.jpg",
    "gamemodes": [
      "escort"
    ],
    "uses": [
      "standard"
    ],
    "location": "Albuquerque, New Mexico, United States",
    "country_code": "US"
  },
  {
    "key": "runasapi",
    "name": "Runasapi",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/runasapi.jpg",
    "gamemodes": [
      "push"
    ],
    "uses": [
      "standard"
    ],
    "location": "Peru",
    "country_code": "PE"
  },
  {
    "key": "samoa",
    "name": "Samoa",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/samoa.jpg",
    "gamemodes": [
      "control"
    ],
    "uses": [
      "standard",
      "stadium"
    ],
    "location": "Samoa",
    "country_code": "WS"
  },
  {
    "key": "shambali-monastery",
    "name": "Shambali Monastery",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/shambali-monastery.jpg",
    "gamemodes": [
      "escort"
    ],
    "uses": [
      "standard"
    ],
    "location": "Nepal",
    "country_code": "NP"
  },
  {
    "key": "suravasa",
    "name": "Suravasa",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/suravasa.jpg",
    "gamemodes": [
      "flashpoint"
    ],
    "uses": [
      "standard"
    ],
    "location": "India",
    "country_code": "IN"
  },
  {
    "key": "thames-district",
    "name": "Thames District",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/thames-district.jpg",
    "gamemodes": [
      "payload-race"
    ],
    "uses": [
      "stadium"
    ],
    "location": "London, United Kingdom",
    "country_code": "UK"
  },
  {
    "key": "throne-of-anubis",
    "name": "Throne of Anubis",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/throne-of-anubis.jpg",
    "gamemodes": [
      "clash"
    ],
    "uses": [
      "arcade"
    ],
    "location": "Giza Plateau, Egypt",
    "country_code": "EG"
  },
  {
    "key": "volskaya",
    "name": "Volskaya Industries",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/volskaya.jpg",
    "gamemodes": [
      "assault"
    ],
    "uses": [
      "arcade"
    ],
    "location": "St. Petersburg, Russia",
    "country_code": "RU"
  },
  {
    "key": "watchpoint-gibraltar",
    "name": "Watchpoint: Gibraltar",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/watchpoint-gibraltar.jpg",
    "gamemodes": [
      "escort"
    ],
    "uses": [
      "standard"
    ],
    "location": "Gibraltar",
    "country_code": "GI"
  },
  {
    "key": "workshop-chamber",
    "name": "Workshop Chamber",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/workshop-chamber.jpg",
    "gamemodes": [
      "workshop"
    ],
    "uses": [
      "workshop"
    ],
    "location": "Earth",
    "country_code": null
  },
  {
    "key": "workshop-expanse",
    "name": "Workshop Expanse",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/workshop-expanse.jpg",
    "gamemodes": [
      "workshop"
    ],
    "uses": [
      "workshop"
    ],
    "location": "Earth",
    "country_code": null
  },
  {
    "key": "workshop-green-screen",
    "name": "Workshop Green Screen",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/workshop-green-screen.jpg",
    "gamemodes": [
      "workshop"
    ],
    "uses": [
      "workshop"
    ],
    "location": "Earth",
    "country_code": null
  },
  {
    "key": "workshop-island",
    "name": "Workshop Island",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/workshop-island.jpg",
    "gamemodes": [
      "workshop"
    ],
    "uses": [
      "workshop"
    ],
    "location": "Earth",
    "country_code": null
  },
  {
    "key": "wuxing-university",
    "name": "Wuxing University",
    "screenshot": "https://discord.aoesports.com.au/overfast/static/maps/wuxing-university.jpg",
    "gamemodes": [
      "control"
    ],
    "uses": [
      "stadium"
    ],
    "location": "Chengdu, Sichuan, China",
    "country_code": "CN"
  }
]

Deployment note: existing reverse-proxy cache entries may continue returning the previous response shape until they expire or are refreshed.

Summary by Sourcery

Add map-use classifications to /maps so clients can distinguish maps by supported play context.

New Features:

  • Expose a typed uses classification for every map returned by the /maps endpoint, covering standard, Stadium, Arcade, Workshop, and Training usage, including maps with multiple classifications.

Bug Fixes:

  • Correct the displayed name of Watchpoint: Gibraltar’s Grímsvötn map entry.

Enhancements:

  • Review and classify the complete map catalog while preserving existing map fields and gamemode filtering.

Deployment:

  • Note that reverse-proxy caches may continue serving the previous /maps response shape until refreshed or expired.

Tests:

  • Add coverage validating map-use classifications and allowed values across the /maps response.

@sourcery-ai

sourcery-ai Bot commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Adds CSV-backed, typed uses classifications to every /maps response, including corrected map metadata, while preserving existing fields and gamemode filtering and adding comprehensive parser and route coverage.

Sequence diagram for CSV-backed map uses in the maps endpoint

sequenceDiagram
    participant Client
    participant MapsRoute
    participant parse_maps_csv
    participant maps_csv
    participant Map

    Client->>MapsRoute: GET /maps
    MapsRoute->>parse_maps_csv: parse_maps_csv()
    parse_maps_csv->>maps_csv: read_csv_file("maps")
    maps_csv-->>parse_maps_csv: map rows with uses
    parse_maps_csv-->>MapsRoute: maps with uses
    MapsRoute->>Map: validate response
    Map-->>Client: maps including uses
Loading

File-Level Changes

Change Details Files
Adds typed map-use classifications to the /maps response and propagates them from source data through parsing.
  • Introduces the MapUse enum with standard, Stadium, Arcade, Workshop, and training values.
  • Adds a required, constrained uses array to the API model.
  • Reads comma-separated classifications from the maps CSV in the parser.
app/domain/enums.py
app/domain/parsers/maps.py
app/api/models/maps.py
app/domain/utils/data/maps.csv
Corrects and verifies map metadata and classifications across the complete map catalog.
  • Classifies all 59 maps, including multi-use Standard/Stadium maps and Arcade-only Clash and Assault maps.
  • Corrects the Grimsvotn map name to Grímsvötn.
app/domain/utils/data/maps.csv
Expands automated coverage for the new response field without changing existing filtering behavior.
  • Updates parser expectations to include uses.
  • Adds route coverage for expected uses on every map and validates allowed classification combinations.
tests/maps/parsers/test_maps_parser.py
tests/maps/test_maps_route.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 2 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="app/domain/parsers/maps.py" line_range="28" />
<code_context>
             "name": map_dict["name"],
             "screenshot": get_static_url_maps(map_dict["key"]),
             "gamemodes": map_dict["gamemodes"].split(","),
+            "uses": map_dict["uses"].split(","),
             "location": map_dict["location"],
             "country_code": map_dict.get("country_code") or None,
</code_context>
<issue_to_address>
**Old instances overwrite the new map shape**

When old- and new-version API instances overlap during deployment, and an old instance writes to the shared maps cache after a new instance has written its response, an old-version API instance can write its map list to the shared `/maps` cache key after a new instance has populated it. Its parser omits `uses`, so clients then receive responses without the new field until a new-version write or cache expiry.

Prevent old-version instances from writing the new-version cache entry, for example by versioning the cache key or ensuring old instances are drained before refreshing it.
</issue_to_address>

### Comment 2
<location path="app/api/models/maps.py" line_range="24" />
<code_context>
         ...,
         description="Main gamemodes on which the map is playable",
     )
+    uses: list[MapUse] = Field(
+        ...,
+        min_length=1,
</code_context>
<issue_to_address>
**Cached maps lack classifications**

When a pre-deployment `/maps` proxy-cache entry is still valid, fastAPI never runs for a cache hit, so the cached JSON omits `uses` and clients receive map entries in the old shape without the new classifications.

Purge or invalidate the `/maps` proxy cache on deployment.
</issue_to_address>

Sourcery assessment

Approval pending. 2 findings to address first.

Blocking findings: app/domain/parsers/maps.py:28, app/api/models/maps.py:24


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

"name": map_dict["name"],
"screenshot": get_static_url_maps(map_dict["key"]),
"gamemodes": map_dict["gamemodes"].split(","),
"uses": map_dict["uses"].split(","),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium · Old instances overwrite the new map shape

When old- and new-version API instances overlap during deployment, and an old instance writes to the shared maps cache after a new instance has written its response, an old-version API instance can write its map list to the shared /maps cache key after a new instance has populated it. Its parser omits uses, so clients then receive responses without the new field until a new-version write or cache expiry.

Prevent old-version instances from writing the new-version cache entry, for example by versioning the cache key or ensuring old instances are drained before refreshing it.

Prompt for AI agents
In `app/domain/parsers/maps.py` at line 28:

**Old instances overwrite the new map shape**

When old- and new-version API instances overlap during deployment, and an old instance writes to the shared maps cache after a new instance has written its response, an old-version API instance can write its map list to the shared `/maps` cache key after a new instance has populated it. Its parser omits `uses`, so clients then receive responses without the new field until a new-version write or cache expiry.

Prevent old-version instances from writing the new-version cache entry, for example by versioning the cache key or ensuring old instances are drained before refreshing it.

Comment thread app/api/models/maps.py
...,
description="Main gamemodes on which the map is playable",
)
uses: list[MapUse] = Field(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium · Cached maps lack classifications

When a pre-deployment /maps proxy-cache entry is still valid, fastAPI never runs for a cache hit, so the cached JSON omits uses and clients receive map entries in the old shape without the new classifications.

Purge or invalidate the /maps proxy cache on deployment.

Prompt for AI agents
In `app/api/models/maps.py` at line 24:

**Cached maps lack classifications**

When a pre-deployment `/maps` proxy-cache entry is still valid, fastAPI never runs for a cache hit, so the cached JSON omits `uses` and clients receive map entries in the old shape without the new classifications.

Purge or invalidate the `/maps` proxy cache on deployment.

@sonarqubecloud

Copy link
Copy Markdown

@TeKrop TeKrop assigned TeKrop and unassigned TeKrop Oct 17, 2026
@TeKrop TeKrop added the enhancement New feature or request label Oct 17, 2026
@TeKrop
TeKrop merged commit d3bcae1 into TeKrop:main Oct 17, 2026
9 checks passed
@TeKrop

TeKrop commented Oct 17, 2026

Copy link
Copy Markdown
Owner

@RealGatt Thank you for the initiative, good for me !

TeKrop pushed a commit that referenced this pull request Oct 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants