CI: build with the Crafter.Build Flatpak on a repo-scoped privileged runner
Some checks failed
Deploy / build-deploy (push) Failing after 6m19s

Crafter.Build's CI publishes only the Flatpak since 2026-10-02, so the
rolling `latest` tarball the Install crafter-build step downloaded is gone
and the 2026-10-12 deploy failed with a 404 before building anything.

Take the route imsd's package job takes. The job runs on `flatpak`, a
privileged runner registered to this repository alone
(forgejo-runner-catcrafts on the box, same arrangement as imsd's), with the
installed Flatpak and its Sdk kept on a docker volume between runs. The
container installs nothing that compiles any more: clang, lld, libc++, the
WASI sysroot, cmake, perl, gpg and OpenSSL all come with the Flatpak and its
Sdk. `crafter-build` is a wrapper around `flatpak run`, `crafter-run` runs a
built binary inside the sandbox, cast is installed under /opt where the
sandbox can see it, and the cache path is the Flatpak's own.

The server binary links the Flatpak's libc++, libc++abi and libunwind, which
are newer than the host's, so the deploy ships them next to the binary the
way it already ships libmsquic; the rpath finds them there. They need at
most GLIBC_2.38, the host has 2.41.

ShouldMatchBankTransfers passed braced lists straight into a std::span
parameter. That compiled only because libc++ 22 had the C++26
span(initializer_list) constructor; the libc++ 23 in the Flatpak does not,
so the lists now go through a vector like the rest of the file.

deploy/README.md documents the runner, the sandbox's private /tmp and how
to run a built binary where the host lacks a matching libc++.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Jorijn van der Graaf 2026-10-12 16:32:57 +02:00
commit 0bfa715e6a
Signed by: jorijnvdgraaf
GPG key ID: 2937E59CDCC1BCFB
3 changed files with 181 additions and 44 deletions

View file

@ -47,8 +47,16 @@ BankCredit Credit(std::string reference, std::int64_t amountMinor,
return c;
}
// The braced lists below land in a vector on purpose. MatchCredits takes a
// span, and the libc++ 23 inside the Crafter.Build 2.1.0 Flatpak (what CI
// builds with) has no span(initializer_list) constructor; libc++ 22 had one
// under C++26, which is the only reason the lists ever compiled.
Server::TransferMatch Match(std::vector<BankCredit> credits, std::string_view reference) {
return Server::MatchCredits(credits, reference);
}
std::int64_t PaidFor(std::vector<BankCredit> credits, std::string_view reference) {
return Server::MatchCredits(credits, reference).paidMinor;
return Match(std::move(credits), reference).paidMinor;
}
} // namespace
@ -102,7 +110,7 @@ int main() {
Credit("CC-2B6457", 2000, "sepa", "b") }, ref) == 5000,
"two credits for one order are summed");
{
const Server::TransferMatch m = Server::MatchCredits(
const Server::TransferMatch m = Match(
{ Credit("CC-2B6457", 3000, "sepa", "a"),
Credit("CC-2B6457", 2000, "sepa", "b") }, ref);
Check(m.count == 2, "the count reports how many credits carried it",
@ -114,7 +122,7 @@ int main() {
// transfer is final, and anything with a dispute window is not.
{
const Server::TransferMatch m =
Server::MatchCredits({ Credit("CC-2B6457", 5000, "ideal") }, ref);
Match({ Credit("CC-2B6457", 5000, "ideal") }, ref);
Check(m.method == "ideal", "the settling method is carried out", m.method);
}
@ -129,11 +137,11 @@ int main() {
// the same money. The matcher cannot fix it, so it flags it for a human.
{
const Server::TransferMatch m =
Server::MatchCredits({ Credit("CC-2B6457 and CC-AAAAAA", 10000) }, ref);
Match({ Credit("CC-2B6457 and CC-AAAAAA", 10000) }, ref);
Check(m.ambiguous,
"a credit quoting a second order reference is flagged ambiguous");
const Server::TransferMatch clean =
Server::MatchCredits({ Credit("CC-2B6457 thanks", 10000) }, ref);
Match({ Credit("CC-2B6457 thanks", 10000) }, ref);
Check(!clean.ambiguous, "an ordinary credit is not flagged");
}