Version Sources
This page documents, for every supported language, where json2vars-setter fetches versions from, which candidate sources were considered, why the chosen source was picked, and the language-specific characteristics that follow from it.
How fetching works
Each language has a fetcher under json2vars_setter/version/fetchers/. Most fetchers
extend BaseVersionFetcher, which reads Git tags from a GitHub repository via the
GitHub REST API, filters them to stable releases, and derives:
latest— the most recent stable releasestable— a "known-good" release (usually the previous minor/major line)recent_releases— the most recent stable releases (used by the cache feature)
A language whose versions are not cleanly expressed as a single repo's tags (currently
Java, Dart, and Swift) overrides fetch_versions and queries an official
API instead.
The dynamic-update strategies map onto these fields:
stable→[stable]latest→[latest]both→[stable, latest]
The example matrices under
examples/<lang>/are hand-curated to the version format the language'ssetup-*action expects, which may differ from the raw fetcher output (e.g. major-only vs fullX.Y.Z).
What the example projects are for
Each examples/<lang>/ project is a small, self-contained example that the matching
<lang>_test.yml workflow runs across the matrix — demonstrating json2vars-setter
driving the language's setup-* action end to end.
They are examples only: their exact contents are illustrative and may change. In
particular they are not a check that a specific version is installable — that is the
setup-* action's responsibility, and its supported-version list can lag the upstream
source the fetcher reads (see the Swift caveat below).
Summary
| Language | Source | latest |
stable |
setup action |
|---|---|---|---|---|
| Python | python/cpython tags |
newest stable | previous minor | actions/setup-python |
| Node.js | nodejs/node tags + LTS metadata |
newest stable | newest LTS | actions/setup-node |
| Ruby | ruby/ruby tags |
newest stable | previous minor | ruby/setup-ruby |
| Go | golang/go tags |
newest stable | previous minor | actions/setup-go |
| Rust | rust-lang/rust tags + channel info |
newest stable | previous minor | dtolnay/rustup toolchain |
| PHP | php/php-src tags |
newest stable | previous minor | shivammathur/setup-php |
| .NET (C#) | dotnet/sdk tags |
newest SDK | previous major | actions/setup-dotnet |
| Java | Adoptium API | newest feature | newest LTS | actions/setup-java |
| Deno | denoland/deno tags |
newest stable | previous minor | denoland/setup-deno |
| Bun | oven-sh/bun tags |
newest stable | previous minor | oven-sh/setup-bun |
| Zig | ziglang/zig tags |
newest stable | previous minor | mlugg/setup-zig |
| Elixir | elixir-lang/elixir tags |
newest stable | previous minor | erlef/setup-beam |
| Dart | Dart release archive | newest stable | previous minor | dart-lang/setup-dart |
| Swift | swift.org install API | newest stable | previous minor | swift-actions/setup-swift |
| Julia | JuliaLang/julia tags (sorted) |
newest stable | previous minor line | julia-actions/setup-julia |
| Crystal | crystal-lang/crystal tags (sorted) |
newest stable | previous minor line | crystal-lang/install-crystal |
| Haskell | ghc/ghc tags (sorted) |
newest stable | previous minor line | haskell-actions/setup |
| OCaml | ocaml/ocaml tags (sorted) |
newest stable | previous minor line | ocaml/setup-ocaml |
| Kotlin | JetBrains/kotlin tags |
newest stable | previous minor | JetBrains release zip (direct download) |
| Clang | llvm/llvm-project tags |
newest stable | previous line | aminya/setup-cpp |
| GCC | gcc-mirror/gcc tags (sorted) |
newest stable | previous major | aminya/setup-cpp |
| Flutter | Flutter release manifest | newest stable | previous minor | subosito/flutter-action |
Per-language details
Python — python/cpython
- Source: tags of the official CPython repository (
vX.Y.Z). - Why: CPython is the reference implementation; its tags are the canonical version list. Direct fit for the GitHub-tags fetcher.
- Characteristics: pre-releases (
a/b/rc) are excluded;stableis the previous minor line oflatest. - Pre-release versions (e.g. 3.15): the fetcher only returns stable releases, so a
beta like
3.15will not appear inlatest/stableuntil it ships. You can still test against it by listing it in the matrix JSON by hand and settingallow-prereleases: trueonactions/setup-python(see the tip in Getting Started).
Node.js — nodejs/node
- Source: tags of the official Node.js repository, plus LTS metadata to identify Long-Term-Support lines.
- Candidates: plain tags only (rejected — Node's notion of "stable" is the current LTS, which tags alone don't convey).
- Why: Node users target LTS releases, so
stableis resolved to the most recent LTS rather than simply the previous minor.
Ruby — ruby/ruby
- Source: tags of the official Ruby repository (underscore form, e.g.
v3_4_2). - Why: canonical source; clean fit for the GitHub-tags fetcher.
- Characteristics: pre-release suffixes are excluded;
stableis the previous minor.
Go — golang/go
- Source: tags of the official Go repository (
goX.Y.Z). - Why: canonical source; clean fit.
- Characteristics: the
goprefix is stripped;rc/betabuilds are excluded;stableis the previous minor.
Rust — rust-lang/rust
- Source: tags of the official Rust repository (
1.XX.Y), plus channel info fromstatic.rust-lang.org. - Why: canonical source; channel info documents the
stable/beta/nightlyavailability alongside the concrete version.
PHP — php/php-src
- Source: tags of the official PHP source repository (
php-X.Y.Z). - Candidates: none better — there is no official "setup-php" from GitHub, but the source repo's tags are authoritative for versions.
- Why: clean fit for the GitHub-tags fetcher.
- Characteristics: only tags matching
php-X.Y.Zexactly are kept (...RC1,...beta1,...alpha1, and unrelated tags likeyaf-*are excluded);stableis the previous minor. The consumer side usesshivammathur/setup-php(the de-facto standard, since no official action exists).
.NET (C#) — dotnet/sdk
- Source: tags of the official .NET SDK repository (
vX.Y.Z, e.g.v8.0.100). - Candidates considered:
dotnet/sdktags (chosen) — consistent with the other languages' GitHub-tags approach.releases-index.jsonrelease metadata (not chosen) — richer (LTS/STS, support phase, per-channel latest), but diverges from the common fetcher pattern.- Why: keeps .NET on the same simple, consistent GitHub-tags mechanism as the other languages.
- Characteristics: the SDK minor is always
0, so the meaningful release line is the major (8.0, 9.0, 10.0).latestis the newest SDK;stableis the newest SDK of the previous major.preview/rctags are excluded. Example matrices use the channel form ("8.0","9.0") thatactions/setup-dotnetaccepts.
Java — Adoptium API
- Source: the Adoptium API
GET /v3/info/available_releases. - Candidates considered:
openjdk/jdktags (rejected) — that repository carries only early-access builds of the in-development release (e.g.jdk-28+0); GA and LTS lines live in separate update repositories, so a single repo's tags cannot represent stable Java versions.openjdk/jdkXXuupdate repos (rejected) — would require juggling many repositories and still mixes build metadata.- Adoptium API (chosen) — a single authoritative endpoint that reports
available_releases,available_lts_releases,most_recent_feature_release, andmost_recent_lts. - Why: it is the only clean, single-source way to enumerate real, installable Java versions and to distinguish LTS from feature releases.
- Characteristics: this is the only fetcher that does not use GitHub tags — it
overrides
fetch_versions.latest= most recent feature release (e.g.26);stable= most recent LTS (e.g.25);recent_releases= the available LTS releases, newest first. The consumer side uses the officialactions/setup-javawith thetemurindistribution; example matrices use major versions ("11","17","21").
Deno — denoland/deno
- Source: tags of the official Deno repository (
vX.Y.Z). - Why: Deno publishes clean, stable-only release tags (no pre-release noise), so it is a direct fit for the GitHub-tags fetcher.
- Characteristics: the
vprefix is stripped;stableis the previous minor oflatest. Example matrices use the channel form ("v1.x","v2.x") thatdenoland/setup-denoaccepts.
Bun — oven-sh/bun
- Source: tags of the official Bun repository (
bun-vX.Y.Z). - Why: Bun's release tags are a clean, direct fit for the GitHub-tags fetcher.
- Characteristics: only tags matching
bun-vX.Y.Zare kept (canaryand the legacyv0.xtags are excluded); thebun-vprefix is stripped;stableis the previous minor oflatest. Example matrices use the form ("1.2.x","1.3.x") thatoven-sh/setup-bunaccepts.
Zig — ziglang/zig
- Source: tags of the official Zig repository (plain
X.Y.Z). - Why: Zig's stable release tags are bare semantic versions — a clean, direct fit for the GitHub-tags fetcher.
- Characteristics: only tags matching
X.Y.Zare kept (masterandX.Y.Z-dev.*nightly builds are excluded); Zig is still pre-1.0, sostableis the previous minor (second component) oflatest. Example matrices use the exact form ("0.14.1","0.15.2") thatmlugg/setup-zigaccepts. - Setup action note:
mlugg/setup-zighas moved its main repository to Codeberg. The version fetcher is unaffected — it reads theziglang/zigcompiler repo (still on GitHub), which is a different project from the setup action. Themlugg/setup-zigGitHub repo used byzig_test.ymlis now an auto-synced mirror; the maintainer commits to keep supporting GitHub Actions, so the pinneduses:reference and Dependabot tracking continue to work.
Elixir — elixir-lang/elixir
- Source: tags of the official Elixir repository (
vX.Y.Z). - Why: Elixir's release tags are a clean, direct fit for the GitHub-tags fetcher.
- Characteristics: only tags matching
vX.Y.Zare kept (release candidatesvX.Y.Z-rc.Nand the movingvX.Y-latesttags are excluded); thevprefix is stripped;stableis the previous minor oflatest. Example matrices use the form ("1.18","1.19") thaterlef/setup-beamaccepts.setup-beamalso requires an Erlang/OTP version, which the example workflow pins separately.
Dart — Dart release archive
- Source: the Dart SDK release archive on Google Cloud Storage
(
channels/stable/release/), listed via the GCS JSON API. - Why: the
dart-lang/sdkGitHub tags are dominated by per-package tags (analyzer-*,meta-*) with the plain SDK version tags buried, so — like Java — Dart uses a dedicated source rather than the GitHub-tags fetcher. - Characteristics: release "folders" matching
X.Y.Zare extracted and sorted numerically (the listing is lexicographic, so3.9.xsorts after3.12.x);latestis the newest version andstableis the previous minor. Example matrices use the form ("3.11.6","3.12.1") thatdart-lang/setup-dartaccepts.
Swift — swift.org install API
- Source: the official swift.org install API
(
https://www.swift.org/api/v1/install/releases.json). - Why: the
apple/swiftGitHub tags are dominated byDEVELOPMENT-SNAPSHOTtags and theswift-X.Y.Z-RELEASEtags do not appear within the first pages of the tags listing, so — like Java and Dart — Swift uses a dedicated source. - Characteristics: release
names matchingX.Y[.Z]are kept and sorted numerically;latestis the newest andstableis the previous minor. Example matrices use the form ("6.1.3","6.2.1") thatswift-actions/setup-swiftaccepts, and targetubuntu/macos(Swift's first-class CI platforms). - Caveat:
swift-actions/setup-swiftinstalls from its own bundled list of known Swift versions, which can lag behind the newest swift.org release. When using the dynamic update, pin to versions the action supports if the very latest is not yet available there.
Julia — JuliaLang/julia
- Source:
JuliaLang/juliaGitHub tags. - Characteristics: stable tags look like
vX.Y.Z; pre-releases (-rc,-beta,-alpha) are excluded. Unlike most repositories, the JuliaLang/julia tag API is not reliably newest-first, sojulia.pyoverrides_get_github_tagsto sort the stable tags numerically by semantic version before selecting;latestis the newest andstableis the newest release from the previous minor line. Example matrices use the short form ("1.10","1.11") thatjulia-actions/setup-juliaaccepts (it also accepts an exactX.Y.Zor aliases such aslts/nightly).
Crystal — crystal-lang/crystal
- Source:
crystal-lang/crystalGitHub tags. - Characteristics: stable tags are plain
X.Y.Zfor recent releases andvX.Y.Zfor older ones (both forms are accepted; thevis stripped). The tag API interleaves those forms with junk tags (ruby,test-ci-1) and is not newest-first, so — likejulia.py—crystal.pyoverrides_get_github_tagsto sort the stable tags numerically before selecting;latestis the newest andstableis the newest release from the previous minor line. Example matrices use exact versions ("1.19.2","1.20.2") thatcrystal-lang/install-crystalaccepts, and targetubuntu/macos(Crystal's first-class CI platforms).
Haskell — ghc/ghc
- Source:
ghc/ghcGitHub tags. Final GHC releases are taggedghc-X.Y.Z-release; the version is extracted from that pattern. - Characteristics: the tag list is dominated by pre-release (
-rc,-alpha), branch-marker (-start) andwip/*tags and is not newest-first, so — likejulia.py—haskell.pyoverrides_get_github_tagsto sort the release tags numerically before selecting.latestis the newest;stableis the newest release from the previous minor line (GHC ships only even minor lines, so this is resolved by version rather thanminor - 1). Example matrices use exact GHC versions ("9.8.4","9.10.1") thathaskell-actions/setupaccepts, and targetubuntu/macos(Haskell's first-class CI platforms).
OCaml — ocaml/ocaml
- Source:
ocaml/ocamlGitHub tags. Stable releases are plainX.Y.Z(e.g.5.4.1). - Characteristics: pre-releases (
5.5.0-beta1,5.5.0-alpha1) carry a suffix and the ancientcsl-*(Caml Special Light) tags carry a prefix, so neither matches and both are excluded. The tag list interleaves those and is not reliably newest-first, so — likejulia.py—ocaml.pyoverrides_get_github_tagsto sort the stable tags numerically before selecting;latestis the newest andstableis the newest release from the previous minor line. Example matrices use exact compiler versions ("5.2.1","5.3.0") thatocaml/setup-ocamlaccepts, and targetubuntu/macos(OCaml's first-class CI platforms).
Kotlin — JetBrains/kotlin
- Source: tags of the official Kotlin repository (
vX.Y.Z). - Why: canonical source; clean fit for the GitHub-tags fetcher.
- Characteristics: pre-releases carry a suffix (
-RC,-RC2,-Beta1, the older-M1milestones), which an anchored^v\d+\.\d+\.\d+$pattern rejects; unlike Julia / OCaml the tags are already newest-first, so no sort override is needed.stableis the previous minor line oflatest. There is no official Kotlin setup action, so the example downloads the exactkotlin-compiler-<version>.zipstraight from the matching JetBrains release (verifying its published SHA-256) and putskotlinconPATH, rather than depending on the third-party (and self-deprecated)fwilhe2/setup-kotlin. It targetsubuntu/macos(the Kotlin CLI is driven from abashstep, where the Windowskotlinc.batis brittle; the compiled JVM bytecode is platform-independent).
Clang — llvm/llvm-project
- Source: tags of the LLVM monorepo (
llvmorg-X.Y.Z). - Why: canonical source for the Clang/LLVM compiler; the axis real C++ CI matrices
vary over. (The C++ language standard —
-std=c++17/20/23— is a static list you hand-write in your matrix JSON, so it needs no fetcher.) - Characteristics: release candidates carry a
-rcNsuffix and each dev cycle opens with a non-releasellvmorg-NN-inittag, both rejected by the anchored^llvmorg-\d+\.\d+\.\d+$pattern. The tags are already newest-first, so no sort override is needed. LLVM bumps the major roughly yearly while the minor is almost always1(e.g.22.1.xfollows21.1.x), sostableis the newest release on the previous version line (the previous distinctmajor.minor), not "previous minor". There is no official Clang setup action, and the LLVM release assets are named inconsistently across versions/platforms, so the example usesaminya/setup-cpp(the de-facto cross-platform compiler-install action) onubuntu/macos.
GCC — gcc-mirror/gcc
- Source: tags of the GCC mirror (
releases/gcc-X.Y.Z). - Why: canonical source for the GCC compiler; the other dynamic C++ axis alongside Clang.
- Characteristics: the tag list interleaves release tags with
releases/libgcj-*,releases/libf2c-*,vendors/*andbasepoints/*tags and is not reliably newest-first, so the fetcher overrides_get_github_tagsto filter toreleases/gcc-X.Y.Zand sort by semantic version (the Julia / Haskell / OCaml pattern) before truncating. GCC's release series is the major (15.1.0 / 15.2.0 / 15.3.0 are all "GCC 15"), sostableis the newest release of the previous major series, not the previous minor. There is no official GCC setup action, so the example usesaminya/setup-cpp; GCC's apt/Homebrew packaging is by major, so the example matrix pins majors (14,13).
Flutter — official release manifest
- Source: the official Flutter release manifest JSON
(
storage.googleapis.com/flutter_infra_release/releases/releases_linux.json). - Why: the
flutter/flutterGitHub tags are useless here (they return stale1.xtags and are not newest-first). The manifest is the authoritative list of released Flutter SDKs; the version numbers are platform-independent, so the Linux manifest is sufficient (the fetcher overridesfetch_versionsrather than reading GitHub tags, likedart.py/swift.py). - Characteristics: the fetcher keeps the
stable-channel entries with a cleanX.Y.Zversion (older1.x.y+hotfix.zforms are excluded), de-duplicates and semver-sorts them. Flutter's stable minors are not contiguous (e.g. 3.41 then 3.44), sostableis the newest release on the previous distinctmajor.minorline. Flutter bundles its own Dart SDK and is tracked as a separate language fromdart. There is no official Flutter setup action, so the example usessubosito/flutter-actiononubuntu/macos.
Adding another language
See the "Adding a New Language" checklist in CLAUDE.md for the full set of files to
touch (fetcher, registry, action contract, tests, example, workflow, badges, docs). When
choosing a version source, prefer the language's canonical GitHub repository tags;
if those don't cleanly express installable releases (as with Java), use the official
project API and override fetch_versions.