From 6ad21240015e4c7f72c7cf7fefd3777f08a65f72 Mon Sep 17 00:00:00 2001 From: Ahmedhossamdev Date: Fri, 13 Mar 2026 19:59:37 -0700 Subject: [PATCH 1/6] feat: Add auto-sync for OpenAPI spec in CI workflow --- Makefile | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f3b784a1..6cbf3a8c 100644 --- a/Makefile +++ b/Makefile @@ -36,7 +36,8 @@ LDFLAGS := -ldflags "-X 'maglev.onebusaway.org/internal/buildinfo.CommitHash=$(G .PHONY: build build-debug clean coverage-report check-jq coverage test run lint watch fmt \ gtfstidy models check-golangci-lint \ test-latency bench-sqlite-all bench-sqlite-perftest \ - docker-build docker-push docker-run docker-stop docker-compose-up docker-compose-down docker-compose-dev docker-clean docker-clean-all + docker-build docker-push docker-run docker-stop docker-compose-up docker-compose-down docker-compose-dev docker-clean docker-clean-all \ + update-openapi check-openapi run: build bin/maglev -f config.json @@ -96,6 +97,28 @@ test-pure: models: go tool sqlc generate -f gtfsdb/sqlc.yml +# Fetch the latest upstream OpenAPI spec and overwrite testdata/openapi.yml. +update-openapi: + @echo "Fetching upstream OpenAPI spec from sdk-config..." + curl -sSfL "https://raw.githubusercontent.com/OneBusAway/sdk-config/main/openapi.yml" \ + -o /tmp/openapi.latest.yml + @printf '# Source: https://github.com/OneBusAway/sdk-config/blob/main/openapi.yml\n# Fetched: %s\n# Auto-synced by .github/workflows/go.yml on every CI run\n' "$$(date +%Y-%m-%d)" > testdata/openapi.yml + cat /tmp/openapi.latest.yml >> testdata/openapi.yml + @echo "Updated testdata/openapi.yml" + +# Check whether testdata/openapi.yml matches the live upstream (skipping header). +# Exits 1 if out of date (useful for CI checks). +check-openapi: + @echo "Checking upstream OpenAPI spec for changes..." + @curl -sSfL "https://raw.githubusercontent.com/OneBusAway/sdk-config/main/openapi.yml" \ + -o /tmp/openapi.check.yml + @if tail -n +4 testdata/openapi.yml | cmp -s /tmp/openapi.check.yml -; then \ + echo "openapi.yml is up to date with upstream"; \ + else \ + echo "WARNING: upstream openapi.yml has changed. Run 'make update-openapi' to update."; \ + exit 1; \ + fi + watch: air From a8ec6683e34cb0e246aa666834a5450415846e42 Mon Sep 17 00:00:00 2001 From: Ahmedhossamdev Date: Fri, 13 Mar 2026 19:59:43 -0700 Subject: [PATCH 2/6] feat: Fetch latest upstream OpenAPI spec in CI workflow --- .github/workflows/go.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 71e35fe9..010868c5 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -54,6 +54,14 @@ jobs: - name: Verify dependencies run: go mod verify + - name: Fetch latest upstream OpenAPI spec + run: | + curl -sSfL "https://raw.githubusercontent.com/OneBusAway/sdk-config/main/openapi.yml" \ + -o /tmp/openapi.latest.yml + printf '# Source: https://github.com/OneBusAway/sdk-config/blob/main/openapi.yml\n# Fetched: %s\n# Auto-synced by .github/workflows/go.yml on every CI run\n' "$(date +%Y-%m-%d)" > testdata/openapi.yml + cat /tmp/openapi.latest.yml >> testdata/openapi.yml + shell: bash + - name: Run tests (fast mode) if: matrix.os == 'ubuntu-latest' run: go test -v -tags=sqlite_fts5 -coverprofile=profile.cov -timeout 40m ./... From df2179726c25f092e4c0e546919bffbb2427ded7 Mon Sep 17 00:00:00 2001 From: Ahmedhossamdev Date: Fri, 13 Mar 2026 20:00:16 -0700 Subject: [PATCH 3/6] docs: add te new update-openapi and check-open-api --- CLAUDE.md | 4 ++++ README.markdown | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index 33b2d916..b3db7ab5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -30,9 +30,13 @@ All commands are managed through the Makefile: - `make clean` - Clean build artifacts - `make build-pure` - Build without CGO (pure Go SQLite driver) - `make test-pure` - Run tests without CGO +- `make update-openapi` - Fetch latest upstream OpenAPI spec and overwrite `testdata/openapi.yml` +- `make check-openapi` - Verify `testdata/openapi.yml` matches upstream (exits 1 if out of date) **Build tags**: When running `go` commands directly (not via Makefile), you must pass `-tags "sqlite_fts5"` for CGO builds or `-tags "purego"` for pure Go builds. +**OpenAPI spec**: `testdata/openapi.yml` is auto-fetched from [OneBusAway/sdk-config](https://github.com/OneBusAway/sdk-config/blob/main/openapi.yml) on every CI run, so conformance tests always validate against the latest upstream spec. + ## Load Testing and Profiling See `loadtest/README.md`. Start with pprof enabled: `MAGLEV_ENABLE_PPROF=1 make run`, then run `k6 run loadtest/k6/scenarios.js`. Capture CPU profiles with `go tool pprof http://localhost:4000/debug/pprof/profile?seconds=30`. diff --git a/README.markdown b/README.markdown index 9fadc731..da90659a 100644 --- a/README.markdown +++ b/README.markdown @@ -187,6 +187,10 @@ All basic commands are managed by our Makefile: * `make test` - Run tests. * `make models` - Generate Go code from SQL queries using sqlc. * `make watch` - Build and run the app with Air for live reloading. +* `make update-openapi` - Fetch the latest upstream OpenAPI spec and overwrite `testdata/openapi.yml`. +* `make check-openapi` - Check whether `testdata/openapi.yml` is in sync with upstream (exits 1 if out of date). + +The OpenAPI spec (`testdata/openapi.yml`) is auto-fetched from [OneBusAway/sdk-config](https://github.com/OneBusAway/sdk-config/blob/main/openapi.yml) on every CI run, so conformance tests always validate against the latest upstream spec. ### FTS5 (SQLite) builds and tests From 8bfb0e511375c19beaec829067a11d6de86e115e Mon Sep 17 00:00:00 2001 From: Ahmedhossamdev Date: Fri, 13 Mar 2026 20:10:28 -0700 Subject: [PATCH 4/6] docs: update --- CLAUDE.md | 2 +- README.markdown | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index b3db7ab5..abfcbfc0 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -35,7 +35,7 @@ All commands are managed through the Makefile: **Build tags**: When running `go` commands directly (not via Makefile), you must pass `-tags "sqlite_fts5"` for CGO builds or `-tags "purego"` for pure Go builds. -**OpenAPI spec**: `testdata/openapi.yml` is auto-fetched from [OneBusAway/sdk-config](https://github.com/OneBusAway/sdk-config/blob/main/openapi.yml) on every CI run, so conformance tests always validate against the latest upstream spec. +**OpenAPI spec**: CI checks that `testdata/openapi.yml` is in sync with [OneBusAway/sdk-config](https://github.com/OneBusAway/sdk-config/blob/main/openapi.yml) on every push and PR. If upstream has changed, CI fails — run `make update-openapi` locally and commit the updated file. ## Load Testing and Profiling diff --git a/README.markdown b/README.markdown index da90659a..6905593e 100644 --- a/README.markdown +++ b/README.markdown @@ -190,7 +190,7 @@ All basic commands are managed by our Makefile: * `make update-openapi` - Fetch the latest upstream OpenAPI spec and overwrite `testdata/openapi.yml`. * `make check-openapi` - Check whether `testdata/openapi.yml` is in sync with upstream (exits 1 if out of date). -The OpenAPI spec (`testdata/openapi.yml`) is auto-fetched from [OneBusAway/sdk-config](https://github.com/OneBusAway/sdk-config/blob/main/openapi.yml) on every CI run, so conformance tests always validate against the latest upstream spec. +CI checks that `testdata/openapi.yml` is in sync with [OneBusAway/sdk-config](https://github.com/OneBusAway/sdk-config/blob/main/openapi.yml) on every push and PR. If the upstream spec has changed, CI will fail with a message to run `make update-openapi` and commit the result. ### FTS5 (SQLite) builds and tests From f70c10e91df967a1d12aa4a77a5c4a6221c2a4a3 Mon Sep 17 00:00:00 2001 From: Ahmedhossamdev Date: Fri, 13 Mar 2026 20:10:33 -0700 Subject: [PATCH 5/6] refactor: streamline OpenAPI spec check in CI workflow --- .github/workflows/go.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 010868c5..063cf701 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -54,12 +54,8 @@ jobs: - name: Verify dependencies run: go mod verify - - name: Fetch latest upstream OpenAPI spec - run: | - curl -sSfL "https://raw.githubusercontent.com/OneBusAway/sdk-config/main/openapi.yml" \ - -o /tmp/openapi.latest.yml - printf '# Source: https://github.com/OneBusAway/sdk-config/blob/main/openapi.yml\n# Fetched: %s\n# Auto-synced by .github/workflows/go.yml on every CI run\n' "$(date +%Y-%m-%d)" > testdata/openapi.yml - cat /tmp/openapi.latest.yml >> testdata/openapi.yml + - name: Check OpenAPI spec is up to date with upstream + run: make check-openapi shell: bash - name: Run tests (fast mode) From 00618959b80aeeebf8a804ddc024eddf5b169d2f Mon Sep 17 00:00:00 2001 From: Ahmedhossamdev Date: Fri, 13 Mar 2026 20:22:35 -0700 Subject: [PATCH 6/6] fix: update OpenAPI using make-update-openapi --- testdata/openapi.yml | 84 ++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 54 deletions(-) diff --git a/testdata/openapi.yml b/testdata/openapi.yml index b6a8ec05..a0298e7a 100644 --- a/testdata/openapi.yml +++ b/testdata/openapi.yml @@ -1,6 +1,6 @@ # Source: https://github.com/OneBusAway/sdk-config/blob/main/openapi.yml -# Fetched: 2026-03-08 -# Local modifications: Added 'nullable: true' to optional fields (location, tripStatus) and resolved wrapper inconsistencies to pass Go strict validation. +# Fetched: 2026-03-13 +# Auto-synced by .github/workflows/go.yml on every CI run openapi: 3.0.0 info: title: OneBusAway @@ -543,7 +543,6 @@ paths: $ref: '#/components/schemas/Reference' required: - list - - limitExceeded - references required: - data @@ -751,7 +750,12 @@ paths: schema: allOf: - $ref: '#/components/schemas/ResponseWrapper' - - $ref: '#/components/schemas/StopsForRouteResponse' + - type: object + properties: + data: + $ref: '#/components/schemas/StopsForRouteResponse' + required: + - data /api/where/stops-for-agency/{agencyID}.json: parameters: @@ -1191,9 +1195,6 @@ components: - vehicleId - lastUpdateTime - lastLocationUpdateTime - - location - - tripId - - tripStatus VehiclesForAgencyResponse: type: object @@ -1208,7 +1209,6 @@ components: $ref: '#/components/schemas/Reference' required: - list - - limitExceeded - references Coverage: @@ -1234,15 +1234,12 @@ components: AgencyResponse: type: object properties: - limitExceeded: - type: boolean entry: $ref: '#/components/schemas/Agency' references: $ref: '#/components/schemas/Reference' required: - entry - - limitExceeded - references CoverageResponse: type: object @@ -1257,7 +1254,6 @@ components: $ref: '#/components/schemas/Reference' required: - list - - limitExceeded - references CurrentTime: @@ -1373,12 +1369,6 @@ components: reason: type: string description: Reason for the service alert, taken from TPEG codes. - enum: - - equipmentReason - - environmentReason - - personnelReason - - miscellaneousReason - - securityAlert summary: type: object properties: @@ -1650,7 +1640,6 @@ components: required: - list - references - - limitExceeded StopsForAgencyResponse: type: object @@ -1668,7 +1657,6 @@ components: required: - list - references - - limitExceeded ArrivalDepartureForStop: type: object @@ -1883,7 +1871,6 @@ components: required: - list - references - - limitExceeded - outOfRange ScheduleForRouteResponse: @@ -1936,7 +1923,6 @@ components: $ref: '#/components/schemas/Reference' required: - list - - limitExceeded - references RoutesForAgencyResponse: @@ -1953,7 +1939,6 @@ components: required: - list - references - - limitExceeded Polylines: type: object @@ -1993,35 +1978,30 @@ components: StopsForRouteResponse: type: object properties: - data: + entry: type: object properties: - entry: - type: object - properties: - polylines: - type: array - items: - $ref: '#/components/schemas/Polylines' - routeId: - type: string - example: '1_100224' - stopGroupings: - type: array - items: - $ref: '#/components/schemas/StopGrouping' - stopIds: - type: array - items: - type: string - example: '1_10911' - references: - $ref: '#/components/schemas/Reference' - required: - - entry - - references + polylines: + type: array + items: + $ref: '#/components/schemas/Polylines' + routeId: + type: string + example: '1_100224' + stopGroupings: + type: array + items: + $ref: '#/components/schemas/StopGrouping' + stopIds: + type: array + items: + type: string + example: '1_10911' + references: + $ref: '#/components/schemas/Reference' required: - - data + - entry + - references # Trip Components TripEntry: type: object @@ -2078,7 +2058,7 @@ components: lon: type: number description: Longitude of the last known location of the transit vehicle. - description: Last known location of the transit vehicle. + description: Last known location of the transit vehicle (optional). lastKnownOrientation: type: number description: Last known orientation value received in real-time from the transit vehicle. @@ -2263,7 +2243,6 @@ components: $ref: '#/components/schemas/Reference' required: - - limitExceeded - list - references @@ -2314,7 +2293,6 @@ components: references: $ref: '#/components/schemas/Reference' required: - - limitExceeded - list - references @@ -2471,7 +2449,6 @@ components: references: $ref: '#/components/schemas/Reference' required: - - limitExceeded - list - outOfRange - references @@ -2610,7 +2587,6 @@ components: references: $ref: '#/components/schemas/Reference' required: - - limitExceeded - list - outOfRange - references