From 83555f5f32784c27c5e582778b6905060d5f2c0e Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Tue, 5 May 2026 13:59:06 -0500 Subject: [PATCH] =?UTF-8?q?Switch=20CI=20from=20build-stage.sh=20to=20elb?= =?UTF-8?q?=20=E2=80=94=20no=20OOM?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit elb compiles each .el source independently (per-file codegen), avoiding the exponential memory growth from concatenating all sources into main-combined.el and feeding it to elc in one shot. - dev.yaml: replace build-stage.sh with elb build + per-file JS elc - Dockerfile.stage: COPY dist/neuron-landing (elb binary) directly instead of compiling from pre-generated main.c. soul-demo stays as cc compilation (small file, no risk). --- .gitea/workflows/dev.yaml | 36 +++++++++++++++++++++++++++++++--- Dockerfile.stage | 41 +++++++++++++-------------------------- 2 files changed, 46 insertions(+), 31 deletions(-) diff --git a/.gitea/workflows/dev.yaml b/.gitea/workflows/dev.yaml index 56ff2a3..0e400a5 100644 --- a/.gitea/workflows/dev.yaml +++ b/.gitea/workflows/dev.yaml @@ -12,7 +12,7 @@ on: - 'dist/**' - 'runtime/**' - 'Dockerfile.stage' - - 'build-stage.sh' + - 'manifest.el' - '.gitea/workflows/dev.yaml' - '.gitea/workflows/stage.yaml' - '.gitea/workflows/deploy.yaml' @@ -60,8 +60,38 @@ jobs: # idempotent if the files already exist from a prior run. run: touch src/index.html src/about.html src/terms.html src/enterprise-terms.html - - name: Build image (local only — no push) - run: ./build-stage.sh "${{ steps.tag.outputs.tag }}" + - name: Build El binary (elb) + # elb compiles each .el source independently (no combined mega-file), + # then links via cc. Output: dist/neuron-landing (linux/amd64 binary). + # This avoids the exponential memory growth that hits elc on the + # concatenated main-combined.el approach. + run: | + set -euo pipefail + export EL_HOME=/opt/el + /opt/el/dist/bin/elb build + echo "Binary: $(ls -lh dist/neuron-landing)" + + - name: Compile JS El sources + run: | + set -euo pipefail + ELC=/opt/el/dist/platform/elc + mkdir -p dist/js + for f in src/js/*.el; do + [ -f "$f" ] || continue + name=$(basename "$f" .el) + "$ELC" --target=js --bundle --minify --obfuscate "$f" > "dist/js/${name}.js" + echo " compiled: $f → dist/js/${name}.js" + done + + - name: Build Docker image (local only — no push) + run: | + set -euo pipefail + TAG="${{ steps.tag.outputs.tag }}" + docker build \ + --cache-from us-central1-docker.pkg.dev/neuron-785695/neuron-marketing/marketing:latest \ + -f Dockerfile.stage \ + -t "marketing:${TAG}" \ + . - name: Local smoke test run: | diff --git a/Dockerfile.stage b/Dockerfile.stage index 176c0da..48d967e 100644 --- a/Dockerfile.stage +++ b/Dockerfile.stage @@ -4,12 +4,14 @@ # - neuron-web on port 8080 (landing page server) # - soul-demo on port 7772 (demo chat, localhost only) # -# bootstrap.py is no longer in the build path. The host-side build-stage.sh -# pre-compiles src/*.el → dist/main.c using the canonical native elc and -# applies the stub forward-declaration sed before this Dockerfile runs. -# The image just compiles the finished C source. +# neuron-web is built by `elb build` in CI (not here). elb compiles each +# .el source independently and links the result — no combined mega-file, +# no exponential memory growth. The binary lands at dist/neuron-landing +# (linux/amd64) and is COPY'd directly into the runtime image. +# +# soul-demo.c is pre-committed (small, no OOM risk) and compiled here. -# ── Stage 1: compile both binaries ──────────────────────────────────────────── +# ── Stage 1: compile soul-demo ──────────────────────────────────────────────── FROM debian:bookworm-slim AS builder RUN apt-get update \ @@ -22,30 +24,10 @@ RUN apt-get update \ WORKDIR /build -# El runtime (shared by both binaries) COPY runtime/el_runtime.c runtime/el_runtime.h ./ - -# Pre-compile el_runtime as a separate cached layer. -# el_runtime.c changes rarely; main.c changes every run. -# Splitting this out means el_runtime.o is cached across builds when only main.c changes. RUN cc -O2 -c el_runtime.c -I. -o el_runtime.o -# ── Build neuron-web ────────────────────────────────────────────────────────── -# -# main.c was generated on the host by build-stage.sh from src/*.el via the -# native elc compiler. Stub forward-declarations were already injected on -# the host side, so this stage is a straight cc invocation. -COPY dist/web_stubs.c ./ -COPY dist/main.c ./ - -RUN cc -O2 -rdynamic \ - -o neuron-web \ - main.c web_stubs.c el_runtime.o \ - -lcurl -lpthread -ldl -lm -lssl -lcrypto - -# ── Build soul-demo ─────────────────────────────────────────────────────────── -COPY dist/soul-demo.c ./ -COPY dist/vessel_stubs.c ./ +COPY dist/soul-demo.c dist/vessel_stubs.c ./ RUN cc -O2 -rdynamic \ -o soul-demo \ @@ -66,8 +48,11 @@ RUN apt-get update \ && mkdir -p /srv/soul/engram-demo \ && chown -R landing:landing /srv/landing /srv/soul -COPY --from=builder /build/neuron-web /usr/local/bin/neuron-web -COPY --from=builder /build/soul-demo /usr/local/bin/soul-demo +# neuron-web binary — produced by `elb build` in CI (linux/amd64) +COPY dist/neuron-landing /usr/local/bin/neuron-web +RUN chmod +x /usr/local/bin/neuron-web + +COPY --from=builder /build/soul-demo /usr/local/bin/soul-demo # Engram snapshot — baked in so soul has memory from cold start COPY dist/engram-snapshot.json /srv/soul/engram-demo/snapshot.json