nandi/frqpublic Fork 0
43a02c2ddd7ebb7cdcd7d46f8c9a20b5b1b55b5e
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.

container.toml · 160 lines · 7.4 KBTOML Blame HistoryRaw
The window opens, and a devShell that remembers what it built c20643a nandi 5d ago1[container]
2name = "frq-flutter-dev"
3description = "the Flutter desktop build, incremental, in a nix devShell"
4base = "arch-nix"
5# A Sandbox, not a Function: runs on a real VM, and the command is
6# the sandbox's own process so it dies when the command does.
7runtime = "sandbox"
8
9[build]
10# The container lives inside the repo it builds, so the copy is rooted two
11# levels up and `.` is the whole tree.
12context = "../.."
13include = ["."]
One frontend where there were three, and a core that is not Clojure 438b247 nandi 21h ago14# `dev` is the shell you actually want. There is no default shell in this
15# flake any more -- the one that used to be there belonged to the retired
16# libcosmic frontend -- so a bare `nix develop` here fails rather than
17# resolving to the wrong tree.
Stop shipping the build tree, and let a shell be the devShell 013945f nandi 5d ago18# The devShell, baked in rather than entered. `print-dev-env` writes the whole
19# environment out as shell -- PATH, the compiler, every variable mkShell sets
20# -- and realises its inputs on the way, so the closure becomes an image layer
21# instead of a fetch every container pays for. Sourcing it from .bashrc means a
22# shell attached to this container *is* the devShell: no `nix develop`, no
23# clone of the flake's git inputs, no wait.
24#
25# `dev` stays for the case where the baked env is stale against a flake edit.
26commands = [
A shell that is already the devShell, and two recipes to reach it e853593 nandi 5d ago27 "nix print-dev-env /app#flutter-desktop --accept-flake-config --extra-substituters file:///nix-cache > /etc/devshell.sh",
Stop shipping the build tree, and let a shell be the devShell 013945f nandi 5d ago28 "echo '. /etc/devshell.sh' >> /root/.bashrc",
29 "printf '#!/bin/sh\\nexec nix develop /app#flutter-desktop \"$@\"\\n' > /usr/local/bin/dev && chmod +x /usr/local/bin/dev",
30]
31# The build state a local checkout carries: 395MB of a 441MB repo, uploaded on
32# every start and wanted by nothing out there. Flutter builds into a volume of
One frontend where there were three, and a core that is not Clojure 438b247 nandi 21h ago33# its own, and the clojure caches are this machine's.
Stop shipping the build tree, and let a shell be the devShell 013945f nandi 5d ago34ignore = [
35 "flutter/build", "flutter/.home", "flutter/.dart_tool",
36 "flutter/.clojuredart", "flutter/.cpcache",
One frontend where there were three, and a core that is not Clojure 438b247 nandi 21h ago37 ".cpcache", "result", "build", ".git",
Stop shipping the build tree, and let a shell be the devShell 013945f nandi 5d ago38]
The window opens, and a devShell that remembers what it built c20643a nandi 5d ago39
40# Two volumes doing two different jobs. `nix-cache` is the binary cache every
41# container here reads from and writes back to. `devshell` is the working
42# state of a `nix develop` loop, and it is shared by every container that has
43# one -- each gets its own directory under it, named for the devShell it
44# belongs to, so two projects (or two shells of one project) never write the
45# same tree. Modal Volumes have no locking, so the directories are the only
46# thing keeping them apart, and two runs of the *same* devshell must not
47# overlap.
48[volumes]
49nix-cache = "/nix-cache"
50devshell = "/devshell"
51
52[resources]
53cpu = 8
54memory = 16384
55timeout = 3600
56
57[run]
58workdir = "/app"
59# Nix for the dependencies, the ordinary toolchain for the build. `nix build`
60# cannot do this: a derivation is all-or-nothing, so any edit is a fresh
61# sandbox and a fresh compile of everything. Here the devShell supplies the
62# compiler and the libraries, and `flutter build` decides what is stale --
63# which is the whole reason `just flutter-desktop` exists as the working-tree
64# loop rather than as another `nix build`.
65#
66# rsync and not cp, with --checksum and not mtimes: Modal copies the source in
67# with fresh timestamps on every run, so a plain copy would look entirely new
68# to Flutter and rebuild the lot. --checksum compares content, leaves the
69# unchanged files' timestamps alone, and lets the incremental build work.
70#
71# The excludes are the state that must NOT be overwritten from /app -- it is
72# what we are here to keep. `just flutter-desktop` seeds those caches only
73# when they are missing, so finding them warm is all it takes.
74command = """
75set -e
76# This container's own directory on the shared devshell volume, named for the
77# devShell it keeps the state of. Anything else using this volume picks its
78# own name and the two never meet.
79SHELL_DIR=/devshell/frq-flutter-desktop
Stop shipping the build tree, and let a shell be the devShell 013945f nandi 5d ago80mkdir -p "$SHELL_DIR" "$SHELL_DIR/.cache"
The window opens, and a devShell that remembers what it built c20643a nandi 5d ago81
82# A worktree's `.git` is a *file* naming a gitdir back on the machine that
83# copied it in, and nix believes it and goes looking for a path that is not
84# here. It has to go before any flake reference to /app.
85rm -rf /app/.git
86
87echo "sync: /app -> $SHELL_DIR"
88# `nix shell --command` and not `nix profile install`: a profile install puts
89# rsync in ~/.nix-profile/bin, which is not on the PATH of the shell already
90# running, so the very next line said `rsync: command not found`.
91#
92# rsync and not cp, with --checksum and not mtimes: Modal copies the source in
93# with fresh timestamps every run, so a plain copy looks entirely new to
94# Flutter and rebuilds the lot. --checksum compares content and leaves the
95# unchanged files' timestamps alone, which is the whole basis of the
96# incremental build.
97#
98# The excludes are the state we are here to keep -- overwriting them from /app
99# would defeat the volume. `just flutter-desktop` seeds those caches only when
100# they are missing, so finding them warm is all it takes.
101nix shell nixpkgs#rsync --accept-flake-config \
102 --extra-substituters file:///nix-cache --command \
103 rsync -a --checksum --delete \
104 --exclude 'flutter/.home/' \
105 --exclude 'flutter/.clojuredart/' \
106 --exclude 'flutter/build/' \
107 --exclude 'flutter/.dart_tool/' \
108 --exclude '.git' \
109 /app/ "$SHELL_DIR/"
110
111cd "$SHELL_DIR"
112echo "state carried over:"
113du -sh flutter/.home flutter/.clojuredart flutter/build 2>/dev/null \
114 || echo " (none yet -- first run)"
115
116# Nix for the dependencies, the ordinary toolchain for the build. `nix build`
117# cannot do this: a derivation is all-or-nothing, so any edit is a fresh
118# sandbox and a fresh compile of everything. Here the devShell supplies the
119# compiler and the libraries and `flutter build` decides what is stale.
120# Evaluated from /app and built in the volume. Both halves matter: /app is the
121# pristine copy, so nix stores a source tree of the repo rather than one
122# carrying gigabytes of flutter/build, while the recipe still runs where the
123# state it reuses lives -- `just -f` is what puts it there, since the recipe
124# cds to its own justfile's directory.
125nix develop /app#flutter-desktop --accept-flake-config \
126 --extra-substituters file:///nix-cache \
127 --max-jobs auto --command just -f "$SHELL_DIR/justfile" flutter-desktop
128
129echo "built:"
130du -sh flutter/build
131
132# The devShell's closure is gigabytes of Flutter, Dart, clang and GTK, and the
133# store it landed in belongs to the image rather than to a volume -- so
134# without this every run re-fetches it from upstream. Written back, the next
135# run substitutes it from file:///nix-cache instead.
136if [ -f /nix-cache/nix-cache-info ]; then
137 echo "cache: writing the devShell closure back"
138 nix copy --no-check-sigs --all --to file:///nix-cache
139fi
140"""
Stop shipping the build tree, and let a shell be the devShell 013945f nandi 5d ago141# Nix's own cache, on the volume rather than in the container. Without it
142# every Sandbox starts empty and `nix develop` re-clones the flake's git
One frontend where there were three, and a core that is not Clojure 438b247 nandi 21h ago143# inputs -- nixgl and its transitives --
Stop shipping the build tree, and let a shell be the devShell 013945f nandi 5d ago144# because flake.lock pins which revision to fetch, not whether it is already
145# on disk. Set here rather than in the command so an interactive shell into
146# this container gets it too.
147env = { XDG_CACHE_HOME = "/devshell/frq-flutter-desktop/.cache" }
The window opens, and a devShell that remembers what it built c20643a nandi 5d ago148
149[nix]
Stop shipping the build tree, and let a shell be the devShell 013945f nandi 5d ago150# Every nix command in the container reads the mounted cache, including one
151# typed by hand in a shell. Passing --extra-substituters per command only ever
152# covered the scripts.
153substituters = ["file:///nix-cache"]
The window opens, and a devShell that remembers what it built c20643a nandi 5d ago154# No devShell warming at image build time: this enters `nix develop` at run
155# time, on the VM, where the cache answers for its closure. The ptyshim that
156# warming would need under gVisor is deprecated and does not come back.
157flake = false
158shim = false
159
160# [experimental] overrides the sandbox default of vm_runtime = true.