29 Commits

Author SHA1 Message Date
will.anderson 62385b53c2 Also skip El rebuild for .gitea/ workflow-only changes
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 2m16s
Workflow file changes don't require rebuilding the El binary. Without
this, merging workflow fixes to main triggers a full El build which
hits a codegen issue in the CI version of elb.
2026-05-11 15:46:37 -05:00
will.anderson d2628ec42e Skip El rebuild for migration/script/test-only changes
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 2m17s
migrations/, scripts/, tests/ changes don't require rebuilding the El
binary. Classifying them as asset-only avoids spurious full builds that
regenerate dist/*.c and can hit codegen incompatibilities.
2026-05-11 15:44:59 -05:00
will.anderson adbdfd3e90 Fix CI migration step: extract Python to scripts/run_migrations.py
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m36s
go-yaml (Gitea's parser) mishandles << inside block scalars, treating the
bash heredoc delimiter as a YAML merge key. Move the migration logic to a
standalone script called via python3 scripts/run_migrations.py.
2026-05-11 13:33:44 -05:00
will.anderson 4a915c1a11 Wire Supabase migrations into CI/CD
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m30s
Adds a "Run database migrations" step to both stage.yaml and deploy.yaml.
Uses the Supabase Management API (access token from GCP Secret Manager)
to apply pending migrations tracked in a schema_migrations table.
Migrations run unconditionally before every deploy — asset-only or full.

Also adds migrations/** to paths filter so a migrations-only commit
triggers the pipeline.
2026-05-11 13:21:42 -05:00
will.anderson ddbb568f1d feat: embed k3s in neuron-web image to run soul-demo as managed pods
soul-demo now runs as a k3s Deployment with HPA (1–8 replicas, 60% CPU
target) instead of a bare background process. k3s starts first in
entrypoint.sh, imports the soul-demo:local OCI tar from
/var/lib/rancher/k3s/agent/images, and auto-applies the Deployment,
NodePort Service, and HPA from the server/manifests dir. neuron-web
starts only after the soul-demo pod is Running. Cloud Run gen2 execution
environment required for k3s (provides /dev/kmsg and Linux capabilities).
2026-05-09 12:40:27 -05:00
will.anderson 4ec5558517 fix(ci): use --key=value form for elb flags
Dev — Build & local smoke test / build-smoke (pull_request) Failing after 16m8s
elb's flag_val only matches --key=value, not --key value.
All three workflows were passing flags space-separated which
elb silently ignored, causing 'cannot locate el_runtime.c'.
2026-05-07 09:36:21 -05:00
will.anderson 3e377e2bb6 ci: replace build-stage.sh concatenation with elb build from ci-base
- stage.yaml and deploy.yaml now extract El SDK from ci-base (docker cp /opt/el) and run elb build to produce dist/neuron-landing
- JS El sources compiled via elc --target=js in a dedicated step, matching dev.yaml exactly
- build-stage.sh replaced with thin elb wrapper for local dev use
- Removes the broken "Set up El SDK" stub (echo EL_HOME) and old build-stage.sh invocation from both workflows
2026-05-07 01:55:08 -05:00
will.anderson 3509dda67c ci: use pre-installed El SDK from ci-base image 2026-05-05 12:48:54 -05:00
will.anderson 2854b89e35 ci: restore El SDK v1.2.1 release download (repo clone uses incompatible elc) 2026-05-05 11:33:04 -05:00
will.anderson b5eecc94ff ci: use elc-linux-amd64 from El repo, fix EL_HOME to lang/ across all workflows 2026-05-05 09:45:20 -05:00
Will Anderson 23ba7b8ec5 ci: enforce branch protection + source-branch rules
- Gitea branch protection enabled on stage and main:
  - Direct pushes disabled (non-admin)
  - stage requires "Dev — Build & local smoke test / build-smoke" to pass
  - main requires "Stage — Build, push & deploy to marketing-stage / deploy-stage" to pass

- Enforcement step added to stage.yaml and deploy.yaml:
  - stage only accepts merges from dev
  - main only accepts merges from stage
  - workflow_dispatch exempt (allows manual redeploy)
  - Direct non-admin pushes are blocked at the Gitea layer before CI runs
2026-05-04 08:18:09 -05:00
Will Anderson c75d8a9563 ci: add gitflow — dev/stage/main branches with CI workflows
Dev — Build & local smoke test / build-smoke (push) Successful in 2m51s
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Successful in 2m52s
Deploy marketing to Cloud Run / deploy (push) Successful in 3m37s
- dev.yaml: build + local docker smoke test only (no push, no deploy)
- stage.yaml: build + push + deploy to marketing-stage + smoke test (stops here)
- deploy.yaml: add HTML placeholder touch step before docker build

Proper human gate between stage and prod: the stage→main merge decision.
2026-05-03 11:28:43 -05:00
Will Anderson 254afd2fb2 fix(ci+chat): drop docker buildx flags + style chat code blocks
Deploy marketing to Cloud Run / deploy (push) Failing after 2m27s
CI: gitea runner ships docker without the buildx plugin, so
`docker buildx build --platform linux/amd64 --load` exits 125
("unknown flag: --platform") in both the full build (build-stage.sh)
and the asset-only fast path (deploy.yaml). Runner host is already
linux/amd64, so explicit --platform is redundant. Switch both call
sites to plain `docker build`. This unblocks the pipeline — every
run since the workflow was added (~26 runs) has failed at this
exact step.

Chat: the live chat bubble renders marked.parse() output via
innerHTML, but .demo-msg-ai .demo-msg-bubble only had CSS rules
for p/ul/ol/li/strong. Fenced code blocks rendered as <pre><code>
with no styling — they appeared as wrapped plaintext, hard to
distinguish from prose. Add rules for code (inline and block),
pre, blockquote, em, h1-h4, and a, mirroring the share-card
styling (which always had them) so chat code blocks finally get
the monospace + tinted-background treatment users expect.
2026-05-03 10:15:24 -05:00
Will Anderson 44c7621c85 ci: use neuron-marketing-sa for stage service (fixes secret access)
Deploy marketing to Cloud Run / deploy (push) Has been cancelled
2026-05-03 03:52:17 -05:00
Will Anderson cac0b0d9dc ci: use pre-built elc-linux-amd64 from El SDK v1.2.1 release
Deploy marketing to Cloud Run / deploy (push) Failing after 48s
Replaces the three-step apt install + GCS cache probe + gcc build sequence
with a single curl download of the pre-built binary. Eliminates build-time
C toolchain dependency and shaves ~2-3 minutes off every full build.
2026-05-03 02:02:29 -05:00
Will Anderson adf780b1a6 ci: add test Stripe publishable key to stage env vars
Deploy marketing to Cloud Run / deploy (push) Failing after 51m20s
2026-05-02 19:26:56 -05:00
Will Anderson 12ec770392 ci: gate prod deploy behind stage smoke test
Deploy marketing to Cloud Run / deploy (push) Has been cancelled
Nothing reaches prod without deploying to marketing-stage first and
passing a 90s HTTP smoke test. Stage uses test Stripe keys
(stripe-secret-key-stage) so checkout can be exercised safely.

Set STRIPE_PUBLISHABLE_KEY on the stage service manually once:
  gcloud run services update marketing-stage --region us-central1 \
    --project neuron-785695 \
    --update-env-vars STRIPE_PUBLISHABLE_KEY=pk_test_...
2026-05-02 19:02:17 -05:00
Will Anderson baba6fbb71 ci: add asset-only fast path (<5min for PNG changes)
Deploy marketing to Cloud Run / deploy (push) Has been cancelled
- Detect asset-only changes (src/assets/, src/shares/, static HTML, llms.txt)
  and skip El compilation, C build deps, and Docker full build entirely
- Fast path pulls :latest as base and rebuilds only the assets layer
- Gate clone-el, install-C-deps, elc-cache, build-elc, build-image, push-image
  behind asset_only != 'true'; deploy steps run unconditionally
- Switch build-stage.sh from registry cache driver (requires docker-container
  buildx driver) to inline cache backed by :latest — compatible with default
  docker driver on the runner
2026-05-02 18:08:43 -05:00
Will Anderson b83504c837 ci: raise timeout to 60min for cold elc cache warm-up
Deploy marketing to Cloud Run / deploy (push) Has been cancelled
2026-05-02 17:31:49 -05:00
Will Anderson a185b8ae69 ci: cache elc binary + Docker layers, asset changes from 42min to ~5min
Deploy marketing to Cloud Run / deploy (push) Has been cancelled
- deploy.yaml: restore elc from GCS (gs://neuron-ci-cache) keyed on
  source SHA; only compile on cache miss, then upload for future runs
- Dockerfile.stage: pre-compile el_runtime.o as its own layer so the
  expensive object is cached when only main.c changes between runs
- build-stage.sh: add --cache-from/--cache-to pointing at Artifact
  Registry so apt-get + compilation layers survive across cold builds
2026-05-02 17:30:18 -05:00
Will Anderson 5bf7b18f06 ci: update el repo clone URL (engram-lang renamed to el)
Deploy marketing to Cloud Run / deploy (push) Has been cancelled
2026-05-02 15:14:34 -05:00
Will Anderson 7a7f2970e5 ci: build elc from dist/platform/elc.c with system curl/ssl headers
Deploy marketing to Cloud Run / deploy (push) Has been cancelled
elc-bootstrap.c isn't committed to engram-lang; the actual C source
is dist/platform/elc.c. Add libcurl4-openssl-dev/libssl-dev install
step so cc has the right headers.
2026-05-02 13:01:36 -05:00
Will Anderson 138e1cde64 ci: compile elc from elc-bootstrap.c instead of looking for build.sh
Deploy marketing to Cloud Run / deploy (push) Failing after 10s
engram-lang doesn't have a build.sh in its tree; bootstrap is via
dist/elc-bootstrap.c + el-compiler/runtime/el_runtime.c.
2026-05-02 13:00:45 -05:00
Will Anderson 483408611c ci: always rebuild elc on the runner (committed binary may be cross-arch)
Deploy marketing to Cloud Run / deploy (push) Failing after 10s
The committed dist/platform/elc was an arm64 binary from the local dev
box; runner is linux/amd64 and got 'cannot execute binary file: Exec
format error'. Always rebuild.
2026-05-02 12:59:46 -05:00
Will Anderson 654b977796 ci: fall back to GCP_SA_KEY (Gitea doesn't inject OIDC request token)
Deploy marketing to Cloud Run / deploy (push) Failing after 1m2s
Gitea Actions doesn't currently inject ACTIONS_ID_TOKEN_REQUEST_TOKEN /
ACTIONS_ID_TOKEN_REQUEST_URL into job env, so google-github-actions/auth
can't mint a federated token. The WIF infrastructure stays in Terraform
so we can flip back once that gap closes; the JSON key in GCP_SA_KEY is
the working path today.
2026-05-02 12:58:06 -05:00
Will Anderson 00a63a202c ci: replace second actions/checkout with raw git clone for engram-lang
Deploy marketing to Cloud Run / deploy (push) Failing after 5s
act_runner v0.6 host-mode hits a 'permission denied' error on
.git/objects/pack/*.idx when running two checkout steps in the same
job. Drop down to a plain git clone of engram-lang and pin EL_HOME
outside the workspace.
2026-05-02 12:57:25 -05:00
Will Anderson 4629796a75 ci: use CHECKOUT_TOKEN repo secret for cross-repo engram-lang checkout
Deploy marketing to Cloud Run / deploy (push) Failing after 6s
The auto-issued GITHUB_TOKEN is scoped to the current repo only, so
cross-repo actions/checkout needs an explicit token. CHECKOUT_TOKEN
holds an admin-scoped Gitea API token; long-term we should switch to
a dedicated read-only PAT.
2026-05-02 12:54:35 -05:00
Will Anderson 248ff89230 ci: use GITHUB_TOKEN for cross-repo engram-lang checkout
Deploy marketing to Cloud Run / deploy (push) Failing after 37s
Gitea Actions auto-issues GITHUB_TOKEN per workflow run; the previous
GITEA_TOKEN reference evaluated to literal text and broke the checkout.
2026-05-02 12:52:49 -05:00
Will Anderson b29ac61005 ci: add Gitea Actions deploy workflow for Cloud Run
Deploy marketing to Cloud Run / deploy (push) Failing after 28s
Push to main triggers build-stage.sh, push to Artifact Registry,
parallel deploy to all 3 marketing prod regions, traffic flip,
verify. Auth via Workload Identity Federation against the
Gitea OIDC provider — no long-lived keys on the runner.

Falls back to GCP_SA_KEY repo secret if WIF doesn't work end
to end against this Gitea instance.
2026-05-02 12:44:51 -05:00