App::Ariza::Versions
NAME
App::Ariza::Versions - the pinned component versions every ariza artefact is built against
SYNOPSIS
use App::Ariza::Versions;
my $v = App::Ariza::Versions.load; # ariza's shipped resources/versions.toml
say $v.rakudo-version; # 2026.07 (bundled runtime)
say $v.rakudo-revision; # 01
say $v.rakudo-tag; # 2026.07-01
say $v.rakudo-test-versions; # (2026.07 2026.09) (test.yml's matrix)
say $v.sqlcipher; # 4.14.0 (advisory ā see below)
.note for $v.warnings; # unrecognised keys, if any
# An alternate pin set (tests, experiments):
my $alt = App::Ariza::Versions.load('/tmp/versions.toml'.IO);
DESCRIPTION
Everything ariza produces ā a bundle, a generated installer, a CI
workflow ā quotes version numbers of software ariza does not own: a
Rakudo release, a SQLCipher build. Those numbers live in exactly one
file, resources/versions.toml, so that bumping a pin regenerates
every app's artefacts in lockstep and nothing can drift.
This class is that file, parsed. It holds no logic beyond parsing: consumers ask it for a string and put the string where it belongs.
THE FILE
sqlcipher = "4.14.0"
[rakudo]
version = "2026.07"
revision = "01"
test-versions = ["2026.07", "2026.09"]
The SQLCipher pin is advisory
sqlcipher is the version ariza expects, not one it can enforce. A
bundle's SQLCipher comes from the build machine's package manager
(App::Ariza::Native) ā there is no ariza-operated mirror, because
SQLCipher's ABI does not move often enough to justify release
infrastructure of its own ā and a package manager ships what it ships.
So a staged library whose version differs from this pin warns and the
build continues, and the manifest records the version that was actually
staged with the pin alongside it.
One flat pin, one nested
sqlcipher and [rakudo] are not shaped the same, and the shapes are
not interchangeable:
sqlcipheris a flat pin ā a single string, compared against whatever the build machine's package manager actually staged. See above.[rakudo]is a table, because the runtime a bundle embeds needs two coordinates,versionandrevision, not one.revisiondisambiguates rebuilds of the same upstream release ā a repackaged runtime, a patched MoarVM ā without pretending upstream cut a new version.rakudo-tagjoins the two asversion-revision.
The Rakudo a bundle embeds is not the Rakudo an app is tested on
[rakudo] carries a third key, test-versions, that has nothing to
do with the other two. version and revision name the one runtime a
bundle ships; test-versions names every Rakudo release an app's own
suite has to pass on, and ariza scaffold-ci renders it as the
raku-version axis of the generated test.yml's matrix:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
raku-version: ['2026.07', '2026.09']
The two move for different reasons. The embedded runtime changes when a bundle should ship a newer one; the tested set changes when a release stops being worth supporting, or a new one ā a new compiler frontend, say ā becomes the one users are upgrading to. A user who installed Raku themselves may be on the older of them for a long time, so both stay in the matrix until the older one is dropped here on purpose.
This key is strict where the others are not, because every entry
becomes a CI job on every runner. It must be a non-empty array of
strings, each a Rakudo release name ā YYYY.MM, or YYYY.MM.N for a
point release (2026.07, 2025.12.1) ā with none repeated, listed
oldest first. Anything else dies naming rakudo.test-versions:
ariza: rakudo.test-versions must be an array of strings
ariza: rakudo.test-versions must not be empty (a test matrix with no Rakudo release in it runs nothing)
ariza: rakudo.test-versions must be an array of strings (got 2026.07; quote every release, since a bare 2026.10 is the number 2026.1)
ariza: rakudo.test-versions entry '2026.7' is not a Rakudo release (expected YYYY.MM or YYYY.MM.N, e.g. 2026.07 or 2025.12.1)
ariza: rakudo.test-versions names '2026.07' more than once (each entry is one matrix job per runner)
ariza: rakudo.test-versions must list the oldest release first, but '2026.09' comes before '2026.07'
The quoting rule is the one most likely to bite: TOML reads an unquoted
2026.10 as the number 2026.1, so a bare number is refused rather
than turned back into a string that names a different release.
An absent test-versions is not an error here, any more than an
absent version is ā every pin in this file is optional to the parser,
and comes back undefined. It is App::Ariza::CI that refuses to
render without one, because a test.yml with no Rakudo in its matrix
tests nothing.
Unknown keys warn; wrong types die
The house rule, shared with App::Ariza::Config and
App::Shigur::Config: an unrecognised key at any level is collected
into warnings and parsing continues, so a pin file written for a
newer ariza still loads in an older one (and vice versa). A key whose
value is the wrong type dies immediately, naming the dotted path and
the expected shape ā "ariza: rakudo.version must be a string" ā
because a mistyped pin would otherwise be silently baked into an
artefact.
Keys beginning with // are ignored entirely, without a warning. TOML
has real comments, so this convention is redundant here; it is kept
because every ariza config file behaves the same way, and a config
author should never have to remember which file format they are in.
METHODS
load(IO() $path = resource('versions.toml') --> App::Ariza::Versions)
Parse a pin file. The default is ariza's own shipped copy, located through App::Ariza::Resources so it works installed and from a checkout alike.
Dies if the file is missing, unreadable, not valid TOML, or not a TOML table ā each with its own message naming the path, so an unreadable file is never confused with a malformed one.
An empty (or whitespace-only) file is not an error: an empty
document is a valid, empty TOML table, and every pin comes back
undefined. Config::TOML rejects it outright, so load short-circuits
before handing it over rather than reporting a legal file as malformed.
warnings(--> List)
Human-readable strings naming every unrecognised key found while loading. Empty when the file was clean.
path(--> IO::Path)
The file this instance was loaded from. Useful in error messages from consumers ("pin X missing from {$v.path}").
sqlcipher
The flat top-level pin, as a string. Undefined Str if absent from the
file.
rakudo-version / rakudo-revision / rakudo-tag
The [rakudo] table's two keys, and the version-revision join of
them. rakudo-tag is the undefined Str unless both halves are
present.
rakudo-test-versions(--> List)
rakudo.test-versions, as a List of release-name strings in file
order ā oldest first, which is enforced at load time. The undefined
List type object when the key is absent: never an empty list, since
an empty array in the file dies rather than loading. The rules are
The Rakudo a bundle embeds is not the Rakudo an app is tested on,
above.
AUTHOR
Matt Doughty
COPYRIGHT AND LICENSE
Copyright 2026 Matt Doughty
This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.