Skip to content

Fix CI build failures and move actions off the Node.js 20 runtime - #1081

Merged
rbergen merged 3 commits into
PlummersSoftwareLLC:drag-racefrom
rbergen:ci-fix-stale-base-images
Sep 13, 2026
Merged

rbergen merged 3 commits into
PlummersSoftwareLLC:drag-racefrom
rbergen:ci-fix-stale-base-images

Conversation

@rbergen

@rbergen rbergen commented Sep 13, 2026 •

Copy link
Copy Markdown
Contributor

Description

Three solutions failed CI on the current drag-race tip. Two are genuinely broken and are fixed here; the third was transient. This also moves the workflow's actions off the unsupported Node.js 20 runtime.

Build failures

PrimeCrystal/solution_2 - stale base image and unreliable package mirrors

Two separate problems, found one after the other.

The solution built on debian:11. Bullseye has reached the end of its LTS window and packages have been dropped from the mirrors, so the build failed during apt-get install curl, before Crystal was reached at all:

E: Failed to fetch .../openssl_1.1.1w-0+deb11u8_amd64.deb       404  Not Found
E: Failed to fetch .../libcurl4_7.74.0-1.3+deb11u16_amd64.deb   404  Not Found

Moving to debian:13 fixed that, and built cleanly locally. It then failed in CI anyway, for a different reason:

E: Failed to fetch http://mirror.aardsoft.fi/opensuse/repositories/devel:/languages:/crystal/
   Debian_13/amd64/crystal1.21_1.21.0-1+1.2_amd64.deb  404  Not Found

The solution installed Crystal from the openSUSE build service repo via crystal-lang.org's install script. download.opensuse.org redirects to regional mirrors that are not always in sync, so whether the build works depends on which mirror the runner is assigned. That is not specific to trixie and would recur on any Debian release.

This now builds on crystallang/crystal:1.21.0, the Crystal project's own image, which removes apt, curl, the install script and the mirror dependency entirely. The image is multi-arch, so no architecture support is lost. CONTRIBUTING points at a language's official image first where one exists, which this is.

Source unchanged. All five implementations still validate:

GordonBGood_bittwiddle;10645;5.000404;1;algorithm=base,faithful=yes,bits=1
GordonBGood_stride8;13890;5.000170;1;algorithm=base,faithful=yes,bits=1
GordonBGood_stride8-rblock16K;20317;5.000650;1;algorithm=base,faithful=yes,bits=1
GordonBGood_extreme;22240;5.000248;1;algorithm=base,faithful=yes,bits=1
GordonBGood_extreme-hybrid;30378;5.000052;1;algorithm=base,faithful=yes,bits=1

All five report Count1: 78498 Count2: 78498 Valid: true, built with --no-cache.

PrimeMojo/solution_1 - unpinned toolchain

The Dockerfile installed the Mojo toolchain unpinned, so it always pulled the latest release. Mojo 26.4 removed fn:

/app/primesieve.mojo:154:5: error: 'fn' has been removed; use 'def' instead

This solution has needed repeated source fixes to track Mojo's breaking changes. Rather than chase another one, the toolchain is now pinned. I tested the range to find the working window:

modular result
25.7.0 fails - function effect 'raises' was already specified
26.1.0 fails - same
26.2.0 builds
26.3.0 builds
26.4.0 fails - 'fn' has been removed (34 occurrences)
26.5.0 fails - same

Pinned to 26.3.0, the newest release the current source compiles on. The source is untouched, and output is unchanged in form:

ELucasCurrie_1bit_meta;5744;5.0;1;algorithm=base,faithful=no,bits=1
ELucasCurrie_8bit_meta;13445;5.0;1;algorithm=base,faithful=no,bits=8
ELucasCurrie_1bit;12071;5.0;1;algorithm=base,faithful=yes,bits=1
ELucasCurrie_8bit;13782;5.0;1;algorithm=base,faithful=yes,bits=8

Moving past 26.3 requires fn to become def in the source. That is a semantic change, so it is left to the contributor rather than folded into a build fix.

PrimePHP/solution_1 - transient, not changed

This failed in the same run, but on a Docker Hub outage rather than anything in the solution:

ERROR: unexpected status from HEAD request to
https://registry-1.docker.io/v2/library/php/manifests/8.1.7-cli: 502 Bad Gateway

It is unchanged, and has since passed CI on this branch.

Action runtimes

GitHub no longer supports the Node.js 20 action runtime. Five of the actions in use ran on node20:

Action Was Now
actions/checkout (build job) v4 v7
docker/setup-qemu-action v3 v4
docker/setup-buildx-action v3 v4
docker/login-action v3 v4
docker/build-push-action v6 v7

All five now resolve to using: node24. The four docker action majors are runtime bumps only, with no input changes; checkout v7 blocks fork checkout for pull_request_target and workflow_run, neither of which this workflow uses.

The checkout in collect-solutions was already on v6, which is node24 - it is moved to v7 so both jobs use one version. jbergstroem/hadolint-gh-action is a composite action with no Node runtime, so it is unchanged.

Note that the docker action majors require Actions Runner v2.327.1 or later. GitHub-hosted runners keep the runner binary current, so this should be satisfied.

Notes

Both changed Dockerfiles pass hadolint against config/hadolint.yml.

PrimePHP/solution_1 pins php:8.1.7-cli and PHP 8.1 is past end of life, but that is a relevance question rather than a build failure and is deliberately not addressed here. No build-no flags were added.

PrimeCrystal/solution_2 built on debian:11. Bullseye has reached the end
of its LTS window and packages have been dropped from the mirrors, so
`apt-get install curl` now fails with 404s before Crystal is reached at
all. Bumped to debian:13 with Crystal 1.21. Crystal 1.14 cannot be used
on trixie because it depends on libpcre3-dev, which Debian 13 dropped in
favour of PCRE2. All five implementations still report Valid: true.

PrimeMojo/solution_1 installed the Mojo toolchain unpinned. Mojo 26.4
removed `fn`, breaking the build. This solution has required repeated
source fixes to track Mojo's breaking changes; pinning the toolchain
stops that from recurring. Pinned to 26.3.0, the newest release the
current source compiles on.

PrimePHP/solution_1 failed in the same run on a transient Docker Hub 502
while resolving php:8.1.7-cli. It builds correctly and is unchanged.
GitHub no longer supports the Node.js 20 action runtime. Five of the
actions in use ran on node20:

  actions/checkout            v4 -> v7
  docker/setup-qemu-action    v3 -> v4
  docker/setup-buildx-action  v3 -> v4
  docker/login-action         v3 -> v4
  docker/build-push-action    v6 -> v7

The four docker action majors are runtime bumps only, with no input
changes. checkout v7 blocks fork checkout for pull_request_target and
workflow_run, neither of which this workflow uses; no other behaviour
relevant here changed.

The checkout in collect-solutions was already on v6, which is node24. It
is moved to v7 so both jobs use one version. jbergstroem/hadolint-gh-action
is a composite action with no Node runtime, and is unchanged.
@rbergen rbergen changed the title Fix CI build failures in Crystal/solution_2 and Mojo/solution_1 Fix CI build failures and move actions off the Node.js 20 runtime Sep 13, 2026
@rbergen

rbergen commented Sep 13, 2026

Copy link
Copy Markdown
Contributor Author

@GordonBGood @Evan-LucasCurrie heads-up: this PR changes the Dockerfiles of your solutions to get them building in CI again. Neither source file is touched.

@GordonBGood, Crystal solution_2 built on debian:11. Bullseye is out of its LTS window and packages have been dropped from the mirrors, so the build now fails on apt-get install curl with 404s, before Crystal is reached at all. It builds on debian:13 with Crystal 1.21 instead. The Crystal bump was forced rather than chosen: 1.14 depends on libpcre3-dev, which Debian 13 dropped in favour of PCRE2. All five implementations still report Valid: true with 78498.

@Evan-LucasCurrie, Mojo solution_1 installed the toolchain unpinned, and Mojo 26.4 removed fn. The install is now pinned to modular==26.3.0, the newest release your current source compiles on. Your code is unchanged.

If you want that solution on a current Mojo, the pin and the source have to move together, since fn becomes def from 26.4 onwards. That changes semantics, so it is your call rather than something to fold into a build fix. Open a PR whenever suits you.

No action needed from either of you otherwise.

The debian:13 bump fixed the base image, but the solution still installed
Crystal from the openSUSE build service repo via crystal-lang.org's
install script. download.opensuse.org redirects to regional mirrors that
are not always in sync, so the build fails wherever the assigned mirror
lacks the package:

  E: Failed to fetch http://mirror.aardsoft.fi/opensuse/repositories/
     devel:/languages:/crystal/Debian_13/amd64/crystal1.21_1.21.0-1+1.2_amd64.deb
     404  Not Found

That is luck of routing rather than anything reproducible, and it is the
same failure mode regardless of which Debian release is targeted.

Using crystallang/crystal:1.21.0 removes apt, curl, the install script
and the mirror dependency entirely. The image is multi-arch, so this also
drops no architecture support. Source unchanged; all five implementations
report Valid: true with 78498.
@rbergen

rbergen commented Sep 13, 2026

Copy link
Copy Markdown
Contributor Author

@GordonBGood correction to my note above: the fix changed after I posted it.

The debian:13 bump on its own was not enough. Crystal was still installed from the openSUSE build service repo via crystal-lang.org's install script, and download.opensuse.org redirects to regional mirrors that are not always in sync. It built locally and then failed in CI on a mirror that did not have the package:

E: Failed to fetch http://mirror.aardsoft.fi/opensuse/repositories/devel:/languages:/crystal/
   Debian_13/amd64/crystal1.21_1.21.0-1+1.2_amd64.deb  404  Not Found

Which mirror you get decides whether the build works, and that would have recurred on any Debian release. So solution_2 now builds on crystallang/crystal:1.21.0, the Crystal project's own image: no apt, no install script, no mirror dependency. It is multi-arch, so no architecture support is lost either.

Your source is still untouched, and all five implementations report Valid: true with 78498. CI is green.

@rbergen
rbergen merged commit e044f5c into PlummersSoftwareLLC:drag-race Sep 13, 2026
180 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant