mirror of
https://github.com/compiler-explorer/compiler-explorer.git
synced 2026-05-16 09:03:34 -04:00
## Summary Adds a structured `releaseTrack: 'stable' | 'nightly' | 'prerelease' | 'experimental'` field on `CompilerInfo` so consumers can distinguish release tracks that aren't currently separable from the existing `isSemVer` / `isNightly` / `semver` fields. Today every compiler with a non-numeric semver and `isNightly=true` looks the same from the outside: Rust nightly, Rust beta, gcc snapshot, and gcc's various experimental forks (`gcontracts-trunk`, `gcc-modules-trunk`, `glambda-p2034-trunk`, ...) all share the same shape. Anything that wants to ask "what's the canonical newest build of language X" — a UI badge, the upcoming MCP `latestPerMajor` knob (#8644), etc. — has no way to tell those apart. ## Implementation - **Heuristic** in `lib/release-track.ts` driven by `asSafeVer` + the existing `isSemVer`/`isNightly` flags. Real semvers with a prerelease segment (e.g. micropython `1.28.0-preview`) are flagged `prerelease`; semvers containing `trunk`/`main` and the literal `nightly` tag go to `nightly`; bare `beta`/`alpha`/`rc` tags go to `prerelease`; `isNightly` with anything else (the c++ experimental forks) goes to `experimental`; everything else stays `stable`. - **Override:** `compiler.releaseTrack=` / `group.releaseTrack=` in `.properties` for cases the heuristic can't reach from structural fields. Used here for `rustccggcc-master` / `mrustc-master`, where "master" lives in the compiler id but not the semver field. - **Backfill** in `loadPrediscovered()` so cached discovery JSON written before this field existed doesn't break, and so a hand-edited invalid value gets re-inferred rather than violating the type contract. - **Tests:** 18 unit tests covering each rule + edge cases (whitespace, mixed case, prerelease segments) and the `isReleaseTrack` type guard. ## API exposure `releaseTrack` is on `CompilerInfo` so it appears via `/api/compilers?fields=all`. It is **not** in the default field set, so existing API responses are unchanged. UI consumers can opt in. ## Why this is a separate PR This started as a piece of #8644 (MCP endpoint) — the MCP `list_compilers` `latestPerMajor` knob needs this distinction to give clean answers ("newest GCC" should not return a sea of experimental forks). Rather than hack around the missing metadata in just the MCP layer, the metadata belongs at the source where other features (UI badging, etc.) can consume it. #8644 will rebase on top of this. ## Test plan - [ ] `npm run test -- --run release-track` — 18/18 pass - [ ] `npm run test:props` — 90/90 pass - [ ] `make pre-commit` — exits 0 (pre-existing warnings only) - [ ] Manual sanity check on staging: `/api/compilers/c%2B%2B?fields=all` returns `releaseTrack` for each compiler 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: mattgodbolt-molty <mattgodbolt-molty@users.noreply.github.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>