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