nandi/frqpublic Fork 0
1403956859648c3d39892e3994df8fee863ec653
Commits
Clone
git clone https://git.rickub.com/nandi/frq.git
git clone ssh://git@rickub.com/nandi/frq.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

CI that can actually build the Nim core 1403956 · on 1403956859648c3d39892e3994df8fee863ec653 · nandi · 14h ago
build.yml · 136 lines · 5.7 KBYAML Blame HistoryRaw
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# The build, on rickub. GitLab CI next door reads source and no more —
# check-common on every push — and deliberately builds nothing. This is the
# other half: the web bundle, actually compiled.
#
# It is not compiled *here*. The job hands the work to Modal exactly as a
# person at a terminal would, and the Sandbox does it against the `devshell`
# volume. What a runner contributes is a checkout, a python, and somewhere to
# put the result afterwards. The reason it goes to Modal is the volume the
# toolchain is cached on, not the size of the build.
#
# Lives in .rickub/workflows/ rather than .github/workflows/ because rickub
# reads one or the other and never both: with this directory present, a
# .github/workflows/ added later would be silently ignored. There is none
# today, so nothing is being shadowed — see
# https://rickub.com/docs/actions and https://rickub.com/docs/migrating-from-github
name: build

on:
  push:
  workflow_dispatch:

jobs:
  # The same read-only check GitLab runs, for the same reason: common/ compiles
  # for two targets, so a host-specific call in shared code breaks one of them
  # at a namespace nobody touched. Seconds, no toolchain. Worth having on both
  # hosts rather than depending on which one a given push reaches.
  check-common:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: python3 tools/check-common.py common

  # The Nim core: its own suite, and the library the Dart job needs.
  #
  # Debian and not the Alpine image this used to name. `libfrqcore.so` links
  # OpenSSL and is glibc, so it has to be built somewhere its runtime can load
  # it — a musl build would not load in `dart:*` at all.
  #
  # `libssl-dev` because `nim/nim.cfg` sets `-d:ssl`: std/net links -lssl and
  # -lcrypto for the TLS on :6697, and `frq.atproto` uses httpclient over the
  # same. Without it the compile fails on a missing -lcrypto, which reads as
  # nothing to do with TLS.
  nim-test:
    runs-on: ubuntu-latest
    container: nimlang/nim:2.2.10
    steps:
      - uses: actions/checkout@v4
      - run: apt-get update -qq && apt-get install -y -qq libssl-dev
      - name: The Nim suite
        run: cd nim && for t in tests/t*.nim; do nim c -r --hints:off --path:src "$t"; done
      - name: Build libfrqcore.so
        run: |
          cd nim && nim c --app:lib --mm:orc -d:release --hints:off --path:src \
            --out:../build/nim/libfrqcore.so src/frq_core.nim
          # Diagnostic, not a gate: prints what the .so will want at
          # runtime, so a missing libssl in the Dart job is obvious
          # from this log rather than from a StateError in that one.
          objdump -p ../build/nim/libfrqcore.so | grep NEEDED || true
      - uses: actions/upload-artifact@v4
        with:
          name: libfrqcore
          path: build/nim/libfrqcore.so
          if-no-files-found: error

  # The Dart side of the same boundary, on the plain VM — no Flutter, no
  # emulator, which is what makes it a second to run. It dlopens the library
  # the job above built, so `libssl3` has to be there: the Dart SDK carries
  # its own BoringSSL and does not bring OpenSSL with it.
  dart-test:
    runs-on: ubuntu-latest
    container: dart:3.13
    needs: [nim-test]
    steps:
      - uses: actions/checkout@v4
      - run: apt-get update -qq && apt-get install -y -qq libssl3
      - uses: actions/download-artifact@v4
        with:
          name: libfrqcore
          path: build/nim
      - run: cd dart/frq_core && dart pub get && dart test -r expanded

  web:
    runs-on: ubuntu-latest
    needs: [check-common, nim-test, dart-test]
    # What it spends its time on is the ClojureDart compile and, on a cold
    # toolchain, fetching the pinned Flutter/JDK/Clojure tarballs.
    timeout-minutes: 30
    steps:
      # The container copies `.` — the whole working tree, uncommitted edits
      # included. On a runner that is whatever the checkout left, so it wants
      # to be the commit and not a shallow surprise.
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - run: pip install --disable-pip-version-check modal

      # Two secrets, set under Settings -> Secrets and variables. A Modal
      # token is the whole of this job's configuration: no nix, no builder,
      # no cache of its own.
      - name: Build the web bundle, on Modal
        env:
          MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
          MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
        # Unpiped on purpose. The image build streams to this client and
        # nowhere else, and `modal app logs` cannot reach an ephemeral run —
        # so this terminal is the only place the build is visible. tee, not
        # tail: a run killed mid-pipe through tail takes its output with it.
        run: modal run .modal/flutter-web/container.py 2>&1 | tee /tmp/frq-build.log

      # The Sandbox leaves the bundle on the devshell volume rather than
      # anywhere a runner can see, so fetch it back out.
      - name: Fetch the bundle out of the volume
        env:
          MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
          MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
        run: |
          modal volume get --force devshell \
            frq-flutter-web/flutter/build/web web

      - uses: actions/upload-artifact@v4
        with:
          name: frq-web-${{ github.sha }}
          path: web
          if-no-files-found: error

      # Kept whether or not the build succeeded: a failed run's log is the
      # one most worth reading, and it is gone with the runner otherwise.
      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: build-log
          path: /tmp/frq-build.log
          if-no-files-found: ignore