No containers for the JS-action jobs
Run 9 got further than any run since the cosmic removal and then failed on `node: command not found` at `actions/upload-artifact`. JS actions run inside the job container on this host, and `nimlang/nim` carries no node — so the upload died after apt, 203 passing tests and a successful library build had all gone through. The runner image has node. Nim and Dart are what it lacks, and both are easier to bring than node is to add to someone else's image, so neither job uses a `container:` now. Both toolchains are fetched by sha256 instead, which is this repo's habit elsewhere — `tools/toolchain.sh` does exactly this for Flutter, a JDK and the Clojure CLI — and it also settles the version question an apt install leaves open. `nim/nim.cfg` needs Nim >= 2.0. GitLab keeps its containers: its artifacts are native and no JS runs in them. Run 9 also corrected something I had written down wrong. The NEEDED line came back as libc and the loader alone, where the nix-built library lists libssl.so.3 and libcrypto.so.3 — Nim resolves OpenSSL through dlopen rather than at link time. Nothing to fix, since the Dart job installs libssl3 either way, but the comment claiming a missing libssl would be visible in that output was wrong and is now the opposite. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
3760746 parent: 1403956 modified
.gitlab-ci.yml +4 -3 | @@ -46,9 +46,10 @@ nim-test: | ||
| 46 | 46 | - cd nim && for t in tests/t*.nim; do nim c -r --hints:off --path:src "$t"; done |
| 47 | 47 | - nim c --app:lib --mm:orc -d:release --hints:off --path:src |
| 48 | 48 | --out:../build/nim/libfrqcore.so src/frq_core.nim |
| 49 | - # Diagnostic, not a gate: prints what the .so will want at runtime, so a | |
| 50 | - # missing libssl in the Dart job is obvious from this log rather than from | |
| 51 | - # a StateError in that one. | |
| 49 | + # Diagnostic, not a gate. Worth reading rather than skimming: Nim resolves | |
| 50 | + # OpenSSL through dlopen rather than a link-time NEEDED, so libssl does NOT | |
| 51 | + # appear here and the Dart job still has to install one. A build that did | |
| 52 | + # link it would show libssl.so.3 and libcrypto.so.3. | |
| 52 | 53 | - objdump -p ../build/nim/libfrqcore.so | grep NEEDED || true |
| 53 | 54 | artifacts: |
| 54 | 55 | paths: [build/nim/libfrqcore.so] |
| @@ -46,9 +46,10 @@ nim-test: | |||
| 46 | - cd nim && for t in tests/t*.nim; do nim c -r --hints:off --path:src "$t"; done | 46 | - cd nim && for t in tests/t*.nim; do nim c -r --hints:off --path:src "$t"; done |
| 47 | - nim c --app:lib --mm:orc -d:release --hints:off --path:src | 47 | - nim c --app:lib --mm:orc -d:release --hints:off --path:src |
| 48 | --out:../build/nim/libfrqcore.so src/frq_core.nim | 48 | --out:../build/nim/libfrqcore.so src/frq_core.nim |
| 49 | - # Diagnostic, not a gate: prints what the .so will want at runtime, so a | 49 | + # Diagnostic, not a gate. Worth reading rather than skimming: Nim resolves |
| 50 | - # missing libssl in the Dart job is obvious from this log rather than from | 50 | + # OpenSSL through dlopen rather than a link-time NEEDED, so libssl does NOT |
| 51 | - # a StateError in that one. | 51 | + # appear here and the Dart job still has to install one. A build that did |
| 52 | + # link it would show libssl.so.3 and libcrypto.so.3. | ||
| 52 | - objdump -p ../build/nim/libfrqcore.so | grep NEEDED || true | 53 | - objdump -p ../build/nim/libfrqcore.so | grep NEEDED || true |
| 53 | artifacts: | 54 | artifacts: |
| 54 | paths: [build/nim/libfrqcore.so] | 55 | paths: [build/nim/libfrqcore.so] |
modified
.rickub/workflows/build.yml +57 -17 | @@ -32,30 +32,51 @@ jobs: | ||
| 32 | 32 | |
| 33 | 33 | # The Nim core: its own suite, and the library the Dart job needs. |
| 34 | 34 | # |
| 35 | - # Debian and not the Alpine image this used to name. `libfrqcore.so` links | |
| 36 | - # OpenSSL and is glibc, so it has to be built somewhere its runtime can load | |
| 37 | - # it — a musl build would not load in `dart:*` at all. | |
| 35 | + # NOT in a `container:`, and that is the whole reason this job is shaped the | |
| 36 | + # way it is. `actions/upload-artifact` is a node20 action and JS actions run | |
| 37 | + # inside the job container, so `nimlang/nim` — which carries no node — failed | |
| 38 | + # the upload step with `node: command not found` after everything real had | |
| 39 | + # already passed. The runner image has node; Nim is what it lacks, and Nim is | |
| 40 | + # the easier of the two to bring. | |
| 38 | 41 | # |
| 39 | - # `libssl-dev` because `nim/nim.cfg` sets `-d:ssl`: std/net links -lssl and | |
| 40 | - # -lcrypto for the TLS on :6697, and `frq.atproto` uses httpclient over the | |
| 41 | - # same. Without it the compile fails on a missing -lcrypto, which reads as | |
| 42 | - # nothing to do with TLS. | |
| 42 | + # Pinned by sha256 rather than taken from apt, which is this repo's habit | |
| 43 | + # elsewhere — see `tools/toolchain.sh`, which fetches Flutter, a JDK and the | |
| 44 | + # Clojure CLI the same way. An apt Nim is whatever the distro froze, and | |
| 45 | + # `nim/nim.cfg` needs >= 2.0. | |
| 43 | 46 | nim-test: |
| 44 | 47 | runs-on: ubuntu-latest |
| 45 | - container: nimlang/nim:2.2.10 | |
| 48 | + env: | |
| 49 | + NIM_VERSION: "2.2.10" | |
| 50 | + NIM_SHA256: "0a3a38752e97e9d44aa479b3a7b37336dfe0176daf22ee5b5218ad0991ecd211" | |
| 46 | 51 | steps: |
| 47 | 52 | - uses: actions/checkout@v4 |
| 48 | - - run: apt-get update -qq && apt-get install -y -qq libssl-dev | |
| 53 | + | |
| 54 | + # libssl-dev because `nim/nim.cfg` sets `-d:ssl`: std/net wants OpenSSL | |
| 55 | + # for the TLS on :6697 and `frq.atproto` uses httpclient over the same. | |
| 56 | + - name: OpenSSL headers | |
| 57 | + run: sudo apt-get update -qq && sudo apt-get install -y -qq libssl-dev | |
| 58 | + | |
| 59 | + - name: Nim ${{ env.NIM_VERSION }} | |
| 60 | + run: | | |
| 61 | + set -euo pipefail | |
| 62 | + url="https://nim-lang.org/download/nim-${NIM_VERSION}-linux_x64.tar.xz" | |
| 63 | + curl -fsSL -o /tmp/nim.tar.xz "$url" | |
| 64 | + echo "${NIM_SHA256} /tmp/nim.tar.xz" | sha256sum -c - | |
| 65 | + mkdir -p /opt/nim && tar -xJf /tmp/nim.tar.xz -C /opt/nim --strip-components=1 | |
| 66 | + echo "/opt/nim/bin" >> "$GITHUB_PATH" | |
| 67 | + | |
| 49 | 68 | - name: The Nim suite |
| 50 | 69 | run: cd nim && for t in tests/t*.nim; do nim c -r --hints:off --path:src "$t"; done |
| 70 | + | |
| 51 | 71 | - name: Build libfrqcore.so |
| 52 | 72 | run: | |
| 53 | 73 | cd nim && nim c --app:lib --mm:orc -d:release --hints:off --path:src \ |
| 54 | 74 | --out:../build/nim/libfrqcore.so src/frq_core.nim |
| 55 | - # Diagnostic, not a gate: prints what the .so will want at | |
| 56 | - # runtime, so a missing libssl in the Dart job is obvious | |
| 57 | - # from this log rather than from a StateError in that one. | |
| 75 | + # Diagnostic, not a gate. Worth reading: Nim resolves OpenSSL through | |
| 76 | + # dlopen rather than a link-time NEEDED, so libssl will not appear | |
| 77 | + # here and the Dart job still has to have one installed. | |
| 58 | 78 | objdump -p ../build/nim/libfrqcore.so | grep NEEDED || true |
| 79 | + | |
| 59 | 80 | - uses: actions/upload-artifact@v4 |
| 60 | 81 | with: |
| 61 | 82 | name: libfrqcore |
| @@ -63,16 +84,35 @@ jobs: | ||
| 63 | 84 | if-no-files-found: error |
| 64 | 85 | |
| 65 | 86 | # The Dart side of the same boundary, on the plain VM — no Flutter, no |
| 66 | - # emulator, which is what makes it a second to run. It dlopens the library | |
| 67 | - # the job above built, so `libssl3` has to be there: the Dart SDK carries | |
| 68 | - # its own BoringSSL and does not bring OpenSSL with it. | |
| 87 | + # emulator, which is what makes it a second to run. | |
| 88 | + # | |
| 89 | + # No container here either, for the same node reason: `download-artifact` is | |
| 90 | + # a JS action too. Dart comes from its own setup action instead. | |
| 91 | + # | |
| 92 | + # `libssl3` because the .so dlopens OpenSSL at startup and the Dart SDK | |
| 93 | + # carries its own BoringSSL rather than bringing one. | |
| 69 | 94 | dart-test: |
| 70 | 95 | runs-on: ubuntu-latest |
| 71 | - container: dart:3.13 | |
| 72 | 96 | needs: [nim-test] |
| 97 | + env: | |
| 98 | + DART_VERSION: "3.13.4" | |
| 99 | + DART_SHA256: "6487a10df5eab890d746d14a55f4c70bec3c1c0633f51804eb504cbc0fc395bb" | |
| 73 | 100 | steps: |
| 74 | 101 | - uses: actions/checkout@v4 |
| 75 | - - run: apt-get update -qq && apt-get install -y -qq libssl3 | |
| 102 | + | |
| 103 | + # The SDK by sha256 rather than `dart-lang/setup-dart`, for the reason | |
| 104 | + # the Nim job pins its tarball: a third-party action is one more thing | |
| 105 | + # that has to resolve on this host, and this one does not have to. | |
| 106 | + - name: Dart ${{ env.DART_VERSION }} | |
| 107 | + run: | | |
| 108 | + set -euo pipefail | |
| 109 | + url="https://storage.googleapis.com/dart-archive/channels/stable/release/${DART_VERSION}/sdk/dartsdk-linux-x64-release.zip" | |
| 110 | + curl -fsSL -o /tmp/dart.zip "$url" | |
| 111 | + echo "${DART_SHA256} /tmp/dart.zip" | sha256sum -c - | |
| 112 | + sudo unzip -q /tmp/dart.zip -d /opt | |
| 113 | + echo "/opt/dart-sdk/bin" >> "$GITHUB_PATH" | |
| 114 | + | |
| 115 | + - run: sudo apt-get update -qq && sudo apt-get install -y -qq libssl3 | |
| 76 | 116 | - uses: actions/download-artifact@v4 |
| 77 | 117 | with: |
| 78 | 118 | name: libfrqcore |
| @@ -32,30 +32,51 @@ jobs: | |||
| 32 | 32 | ||
| 33 | # The Nim core: its own suite, and the library the Dart job needs. | 33 | # The Nim core: its own suite, and the library the Dart job needs. |
| 34 | # | 34 | # |
| 35 | - # Debian and not the Alpine image this used to name. `libfrqcore.so` links | 35 | + # NOT in a `container:`, and that is the whole reason this job is shaped the |
| 36 | - # OpenSSL and is glibc, so it has to be built somewhere its runtime can load | 36 | + # way it is. `actions/upload-artifact` is a node20 action and JS actions run |
| 37 | - # it — a musl build would not load in `dart:*` at all. | 37 | + # inside the job container, so `nimlang/nim` — which carries no node — failed |
| 38 | + # the upload step with `node: command not found` after everything real had | ||
| 39 | + # already passed. The runner image has node; Nim is what it lacks, and Nim is | ||
| 40 | + # the easier of the two to bring. | ||
| 38 | # | 41 | # |
| 39 | - # `libssl-dev` because `nim/nim.cfg` sets `-d:ssl`: std/net links -lssl and | 42 | + # Pinned by sha256 rather than taken from apt, which is this repo's habit |
| 40 | - # -lcrypto for the TLS on :6697, and `frq.atproto` uses httpclient over the | 43 | + # elsewhere — see `tools/toolchain.sh`, which fetches Flutter, a JDK and the |
| 41 | - # same. Without it the compile fails on a missing -lcrypto, which reads as | 44 | + # Clojure CLI the same way. An apt Nim is whatever the distro froze, and |
| 42 | - # nothing to do with TLS. | 45 | + # `nim/nim.cfg` needs >= 2.0. |
| 43 | nim-test: | 46 | nim-test: |
| 44 | runs-on: ubuntu-latest | 47 | runs-on: ubuntu-latest |
| 45 | - container: nimlang/nim:2.2.10 | 48 | + env: |
| 49 | + NIM_VERSION: "2.2.10" | ||
| 50 | + NIM_SHA256: "0a3a38752e97e9d44aa479b3a7b37336dfe0176daf22ee5b5218ad0991ecd211" | ||
| 46 | steps: | 51 | steps: |
| 47 | - uses: actions/checkout@v4 | 52 | - uses: actions/checkout@v4 |
| 48 | - - run: apt-get update -qq && apt-get install -y -qq libssl-dev | 53 | + |
| 54 | + # libssl-dev because `nim/nim.cfg` sets `-d:ssl`: std/net wants OpenSSL | ||
| 55 | + # for the TLS on :6697 and `frq.atproto` uses httpclient over the same. | ||
| 56 | + - name: OpenSSL headers | ||
| 57 | + run: sudo apt-get update -qq && sudo apt-get install -y -qq libssl-dev | ||
| 58 | + | ||
| 59 | + - name: Nim ${{ env.NIM_VERSION }} | ||
| 60 | + run: | | ||
| 61 | + set -euo pipefail | ||
| 62 | + url="https://nim-lang.org/download/nim-${NIM_VERSION}-linux_x64.tar.xz" | ||
| 63 | + curl -fsSL -o /tmp/nim.tar.xz "$url" | ||
| 64 | + echo "${NIM_SHA256} /tmp/nim.tar.xz" | sha256sum -c - | ||
| 65 | + mkdir -p /opt/nim && tar -xJf /tmp/nim.tar.xz -C /opt/nim --strip-components=1 | ||
| 66 | + echo "/opt/nim/bin" >> "$GITHUB_PATH" | ||
| 67 | + | ||
| 49 | - name: The Nim suite | 68 | - name: The Nim suite |
| 50 | run: cd nim && for t in tests/t*.nim; do nim c -r --hints:off --path:src "$t"; done | 69 | run: cd nim && for t in tests/t*.nim; do nim c -r --hints:off --path:src "$t"; done |
| 70 | + | ||
| 51 | - name: Build libfrqcore.so | 71 | - name: Build libfrqcore.so |
| 52 | run: | | 72 | run: | |
| 53 | cd nim && nim c --app:lib --mm:orc -d:release --hints:off --path:src \ | 73 | cd nim && nim c --app:lib --mm:orc -d:release --hints:off --path:src \ |
| 54 | --out:../build/nim/libfrqcore.so src/frq_core.nim | 74 | --out:../build/nim/libfrqcore.so src/frq_core.nim |
| 55 | - # Diagnostic, not a gate: prints what the .so will want at | 75 | + # Diagnostic, not a gate. Worth reading: Nim resolves OpenSSL through |
| 56 | - # runtime, so a missing libssl in the Dart job is obvious | 76 | + # dlopen rather than a link-time NEEDED, so libssl will not appear |
| 57 | - # from this log rather than from a StateError in that one. | 77 | + # here and the Dart job still has to have one installed. |
| 58 | objdump -p ../build/nim/libfrqcore.so | grep NEEDED || true | 78 | objdump -p ../build/nim/libfrqcore.so | grep NEEDED || true |
| 79 | + | ||
| 59 | - uses: actions/upload-artifact@v4 | 80 | - uses: actions/upload-artifact@v4 |
| 60 | with: | 81 | with: |
| 61 | name: libfrqcore | 82 | name: libfrqcore |
| @@ -63,16 +84,35 @@ jobs: | |||
| 63 | if-no-files-found: error | 84 | if-no-files-found: error |
| 64 | 85 | ||
| 65 | # The Dart side of the same boundary, on the plain VM — no Flutter, no | 86 | # The Dart side of the same boundary, on the plain VM — no Flutter, no |
| 66 | - # emulator, which is what makes it a second to run. It dlopens the library | 87 | + # emulator, which is what makes it a second to run. |
| 67 | - # the job above built, so `libssl3` has to be there: the Dart SDK carries | 88 | + # |
| 68 | - # its own BoringSSL and does not bring OpenSSL with it. | 89 | + # No container here either, for the same node reason: `download-artifact` is |
| 90 | + # a JS action too. Dart comes from its own setup action instead. | ||
| 91 | + # | ||
| 92 | + # `libssl3` because the .so dlopens OpenSSL at startup and the Dart SDK | ||
| 93 | + # carries its own BoringSSL rather than bringing one. | ||
| 69 | dart-test: | 94 | dart-test: |
| 70 | runs-on: ubuntu-latest | 95 | runs-on: ubuntu-latest |
| 71 | - container: dart:3.13 | ||
| 72 | needs: [nim-test] | 96 | needs: [nim-test] |
| 97 | + env: | ||
| 98 | + DART_VERSION: "3.13.4" | ||
| 99 | + DART_SHA256: "6487a10df5eab890d746d14a55f4c70bec3c1c0633f51804eb504cbc0fc395bb" | ||
| 73 | steps: | 100 | steps: |
| 74 | - uses: actions/checkout@v4 | 101 | - uses: actions/checkout@v4 |
| 75 | - - run: apt-get update -qq && apt-get install -y -qq libssl3 | 102 | + |
| 103 | + # The SDK by sha256 rather than `dart-lang/setup-dart`, for the reason | ||
| 104 | + # the Nim job pins its tarball: a third-party action is one more thing | ||
| 105 | + # that has to resolve on this host, and this one does not have to. | ||
| 106 | + - name: Dart ${{ env.DART_VERSION }} | ||
| 107 | + run: | | ||
| 108 | + set -euo pipefail | ||
| 109 | + url="https://storage.googleapis.com/dart-archive/channels/stable/release/${DART_VERSION}/sdk/dartsdk-linux-x64-release.zip" | ||
| 110 | + curl -fsSL -o /tmp/dart.zip "$url" | ||
| 111 | + echo "${DART_SHA256} /tmp/dart.zip" | sha256sum -c - | ||
| 112 | + sudo unzip -q /tmp/dart.zip -d /opt | ||
| 113 | + echo "/opt/dart-sdk/bin" >> "$GITHUB_PATH" | ||
| 114 | + | ||
| 115 | + - run: sudo apt-get update -qq && sudo apt-get install -y -qq libssl3 | ||
| 76 | - uses: actions/download-artifact@v4 | 116 | - uses: actions/download-artifact@v4 |
| 77 | with: | 117 | with: |
| 78 | name: libfrqcore | 118 | name: libfrqcore |