diff --git a/.gitea/workflows/dev.yaml b/.gitea/workflows/dev.yaml index 595cd5e..c159628 100644 --- a/.gitea/workflows/dev.yaml +++ b/.gitea/workflows/dev.yaml @@ -3,6 +3,15 @@ name: Dev — Build & local smoke test # Validates that the build compiles and the server starts cleanly. # No GCP deployment — this is the inner dev loop gate. # Merge to stage when you want a real environment. +# +# Build approach: pull ci-base from Artifact Registry (has elb + elc + runtime +# at /opt/el), extract the SDK onto the runner host, then run elb build. +# elb compiles each .el source independently — no combined mega-file, no OOM. +# Output: dist/neuron-landing (linux/amd64). Dockerfile.stage COPYs it directly. +# +# For pull_request events: secrets are not injected, so ci-base can't be pulled. +# Fall back to committed bin/elb-linux-amd64 + bin/elc-linux-amd64 + runtime/. +# No docker cache (no Artifact Registry auth), but the full build + smoke test runs. on: push: @@ -11,8 +20,20 @@ on: - 'src/**' - 'dist/**' - 'runtime/**' - - 'Dockerfile.stage' - 'manifest.el' + - 'Dockerfile.stage' + - '.gitea/workflows/dev.yaml' + - '.gitea/workflows/stage.yaml' + - '.gitea/workflows/deploy.yaml' + + pull_request: + branches: [dev] + paths: + - 'src/**' + - 'dist/**' + - 'runtime/**' + - 'manifest.el' + - 'Dockerfile.stage' - '.gitea/workflows/dev.yaml' - '.gitea/workflows/stage.yaml' - '.gitea/workflows/deploy.yaml' @@ -34,63 +55,104 @@ jobs: with: fetch-depth: 2 - - name: Set up El SDK - run: echo "EL_HOME=/opt/el" >> "$GITHUB_ENV" + # ── GCP auth (push/workflow_dispatch only) ──────────────────────────── + # pull_request events don't get secrets injected. GCP auth is skipped + # for PRs — El SDK comes from committed bin/ + runtime/ instead. - name: Authenticate to GCP + if: github.event_name != 'pull_request' uses: google-github-actions/auth@v2 with: credentials_json: ${{ secrets.GCP_SA_KEY }} - name: Set up gcloud SDK + if: github.event_name != 'pull_request' uses: google-github-actions/setup-gcloud@v2 with: project_id: neuron-785695 - name: Configure docker auth for Artifact Registry + if: github.event_name != 'pull_request' run: gcloud auth configure-docker us-central1-docker.pkg.dev --quiet + # ── El SDK setup ────────────────────────────────────────────────────── + # Push builds: extract elb + elc + runtime from ci-base (always latest). + # PR builds: use committed bin/elb-linux-amd64 + bin/elc-linux-amd64 + runtime/. + + - name: Extract El SDK from ci-base (push builds) + if: github.event_name != 'pull_request' + run: | + set -euo pipefail + docker pull us-central1-docker.pkg.dev/neuron-785695/neuron-ci/ci-base:latest + CID=$(docker create us-central1-docker.pkg.dev/neuron-785695/neuron-ci/ci-base:latest) + sudo mkdir -p /opt/el + docker cp "$CID:/opt/el" /opt/ + docker rm "$CID" + echo "ELB=/opt/el/dist/bin/elb" >> "$GITHUB_ENV" + echo "ELC=/opt/el/dist/platform/elc" >> "$GITHUB_ENV" + echo "EL_RUNTIME=/opt/el/el-compiler/runtime" >> "$GITHUB_ENV" + + - name: Set up El SDK from committed bin/ (PR builds) + if: github.event_name == 'pull_request' + run: | + set -euo pipefail + DEST="${{ github.workspace }}/../foundation-el" + mkdir -p "$DEST/dist/bin" "$DEST/dist/platform" "$DEST/el-compiler/runtime" + cp bin/elb-linux-amd64 "$DEST/dist/bin/elb" + cp bin/elc-linux-amd64 "$DEST/dist/platform/elc" + chmod +x "$DEST/dist/bin/elb" "$DEST/dist/platform/elc" + cp runtime/el_runtime.c "$DEST/el-compiler/runtime/" + cp runtime/el_runtime.h "$DEST/el-compiler/runtime/" + cp runtime/el_runtime.js "$DEST/el-compiler/runtime/" + echo "ELB=$DEST/dist/bin/elb" >> "$GITHUB_ENV" + echo "ELC=$DEST/dist/platform/elc" >> "$GITHUB_ENV" + echo "EL_RUNTIME=$DEST/el-compiler/runtime" >> "$GITHUB_ENV" + + # ── Build neuron-web binary ─────────────────────────────────────────── + + - name: Build neuron-web with elb + run: | + set -euo pipefail + "$ELB" build \ + --elc "$ELC" \ + --runtime "$EL_RUNTIME" + echo "Binary: $(ls -lh dist/neuron-landing)" + + # ── Compile JS client sources ───────────────────────────────────────── + + - name: Compile JS El sources + run: | + set -euo pipefail + cp "$EL_RUNTIME/el_runtime.js" src/js/ + 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 + rm -f src/js/el_runtime.js + + # ── Docker build + smoke test ───────────────────────────────────────── + - name: Compute image tag id: tag run: echo "tag=dev-${GITHUB_SHA:0:8}" >> "$GITHUB_OUTPUT" - name: Touch HTML placeholder files - # El binary regenerates these at startup via fs_write. They must exist - # in the build context for Dockerfile COPY to succeed. touch is - # 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 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 \ - --elc=/opt/el/dist/platform/elc \ - --runtime=/opt/el/el-compiler/runtime - 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 }}" + CACHE_ARGS="" + if [ "${{ github.event_name }}" != "pull_request" ]; then + CACHE_ARGS="--cache-from us-central1-docker.pkg.dev/neuron-785695/neuron-marketing/marketing:latest" + fi docker build \ - --cache-from us-central1-docker.pkg.dev/neuron-785695/neuron-marketing/marketing:latest \ + --build-arg BUILDKIT_INLINE_CACHE=1 \ + $CACHE_ARGS \ -f Dockerfile.stage \ -t "marketing:${TAG}" \ . @@ -107,8 +169,6 @@ jobs: -e LANDING_ROOT=/srv/landing \ "$IMAGE" - # entrypoint.sh sleeps 4s for soul-demo to load before starting neuron-web. - # Poll up to 45s total. for i in $(seq 1 15); do STATUS=$(curl -sSo /dev/null -w "%{http_code}" --max-time 5 http://localhost:8080/ || echo "000") echo "Attempt $i/15: HTTP $STATUS" @@ -125,4 +185,3 @@ jobs: docker stop dev-smoke && docker rm dev-smoke || true echo "Dev smoke test FAILED" exit 1 -