feat(irv-ml1): provision the Draupnir geometry engine, acceptance-tested
Operator-authorized. build123d 0.12.0 + OCP, numpy 2.4.6, trimesh 5.1.0 in a 3.11 venv, FreeCAD 1.0.0 headless as an AppImage, artifact root on smithy. The acceptance test is the point and it PASSES: brokkr-smithy-dev shipped a contrastive control pair whose every property is construction-known, so the install is checked against arithmetic rather than against a render. Both parts build, both bounding boxes are exactly 40x40x5, and both volumes match to float tolerance. These scripts had never been executed by anyone -- build123d is deliberately absent from the authoring box -- so this was their first run. FreeCAD is an AppImage BY CHOICE: the distro package drags a GUI/Qt dependency tree onto a host running twelve GPU and audio services, where an AppImage is self-contained, pinned and removable with one rm. Slicer DEFERRED rather than guessed. PrusaSlicer's latest release ships no Linux AppImage at all, and a guessed release filename had already produced a 4 KB error page in this same session. It is the one item they said could lag. Two things worth keeping in the header: irv-ml1's ssh config pins the gitea host to gitea_brokkr_smithy with IdentitiesOnly, whose comment is irv-ml1-r14-deploy and NOT the arbo key that sorts first in ~/.ssh/*.pub -- I registered the wrong one first, and the failure names the right one. And `ssh irv-ml1` is lkraven with no NOPASSWD sudo while `ssh infra-ops@irv-ml1` has it, so only the artifact-root step needs the other identity. The deploy key was registered with claude-bot's own token rather than the operator's site-admin token -- the org grant from earlier today doing real work on its first use.
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
# Provision the Draupnir geometry engine on irv-ml1.
|
||||
#
|
||||
# scripts/elway irv-ml1 --playbook playbooks/irv-ml1-draupnir-engine.yaml
|
||||
#
|
||||
# Records what was VERIFIED on 2026-09-21, not what was planned.
|
||||
#
|
||||
# ⚠ SUDO IDENTITY. `ssh irv-ml1` is lkraven and has NO NOPASSWD sudo;
|
||||
# `ssh infra-ops@irv-ml1` does. The only step needing root is the artifact
|
||||
# root, so everything else runs as lkraven, where the ssh config and deploy
|
||||
# keys live.
|
||||
#
|
||||
# ⚠ DEPLOY KEY. irv-ml1's ~/.ssh/config pins gitea.phasefinal.com to
|
||||
# `gitea_brokkr_smithy` with IdentitiesOnly yes — its comment is
|
||||
# "irv-ml1-r14-deploy", NOT the arbo key that sorts first in ~/.ssh/*.pub.
|
||||
# Registering the wrong one fails with a message naming the right one, which is
|
||||
# the clue. The key is registered read-only on pfi/draupnir (id 8).
|
||||
#
|
||||
# ⚠ FreeCAD is an AppImage BY CHOICE. The distro package drags a GUI/Qt
|
||||
# dependency tree onto a box running twelve GPU and audio services; an AppImage
|
||||
# is self-contained, pinned, and removable with one rm. Run it as
|
||||
# `FreeCAD.AppImage --appimage-extract-and-run freecadcmd`.
|
||||
#
|
||||
# ⚠ SLICER DEFERRED. PrusaSlicer's latest release ships NO Linux AppImage
|
||||
# (Windows/macOS only), and guessing at a release filename already produced a
|
||||
# 4 KB error page here once. Left undone deliberately rather than done blind.
|
||||
vars:
|
||||
repo: git@gitea.phasefinal.com:pfi/draupnir.git
|
||||
checkout: /home/lkraven/development/draupnir
|
||||
freecad_url: https://github.com/FreeCAD/FreeCAD/releases/download/1.0.0/FreeCAD_1.0.0-conda-Linux-x86_64-py311.AppImage
|
||||
|
||||
steps:
|
||||
- name: Artifact root on smithy (500 GB budget, per draupnir remote.py)
|
||||
sudo: true
|
||||
shell: mkdir -p /mnt/smithy/draupnir && chmod 2775 /mnt/smithy/draupnir
|
||||
creates: /mnt/smithy/draupnir
|
||||
|
||||
- name: Clone the engine repo
|
||||
shell: git clone {{ repo }} {{ checkout }}
|
||||
creates: "{{ checkout }}/.git"
|
||||
|
||||
- name: uv venv on the 3.11 floor
|
||||
shell: cd {{ checkout }} && uv venv --python 3.11
|
||||
creates: "{{ checkout }}/.venv/bin/python"
|
||||
|
||||
- name: Install the engine extra (build123d + OCP + numpy + trimesh)
|
||||
shell: cd {{ checkout }} && uv pip install -e '.[engine]'
|
||||
# Idempotent on the INSTALLED package, not on the venv existing.
|
||||
when: "! {{ checkout }}/.venv/bin/python -c 'import build123d' 2>/dev/null"
|
||||
|
||||
- name: FreeCAD headless AppImage
|
||||
shell: mkdir -p ~/opt && curl -sL -o ~/opt/FreeCAD.AppImage {{ freecad_url }} && chmod +x ~/opt/FreeCAD.AppImage
|
||||
creates: /home/lkraven/opt/FreeCAD.AppImage
|
||||
|
||||
verify:
|
||||
- name: build123d, numpy and trimesh all import
|
||||
shell: "{{ checkout }}/.venv/bin/python -c 'import build123d, numpy, trimesh, OCP'"
|
||||
changed_when: "false"
|
||||
- name: FreeCAD runs headless
|
||||
shell: ~/opt/FreeCAD.AppImage --appimage-extract-and-run freecadcmd --version
|
||||
changed_when: "false"
|
||||
- name: artifact root is writable by the docker group
|
||||
shell: test -w /mnt/smithy/draupnir
|
||||
changed_when: "false"
|
||||
# The real gate. Both control parts must BUILD and both volumes must match
|
||||
# construction-known arithmetic — not a render, not an opinion.
|
||||
- name: acceptance — contrastive control pair builds with correct volumes
|
||||
shell: >-
|
||||
cd {{ checkout }} && .venv/bin/python -c
|
||||
"import math,runpy;
|
||||
g=runpy.run_path('parts/plate-good/model.py')['result'];
|
||||
t=runpy.run_path('parts/plate-thin-wall/model.py')['result'];
|
||||
wg=40*40*5-math.pi*5**2*5; wt=40*40*5-math.pi*19**2*5;
|
||||
assert abs(g.volume-wg)<1e-6*wg, (g.volume,wg);
|
||||
assert abs(t.volume-wt)<1e-6*wt, (t.volume,wt);
|
||||
assert (round(g.bounding_box().size.X,6),round(g.bounding_box().size.Z,6))==(40.0,5.0);
|
||||
print('acceptance OK')"
|
||||
changed_when: "false"
|
||||
Reference in New Issue
Block a user