2 Commits

Author SHA1 Message Date
sam_oneal 920fcd6a1a Add Pulumi preview to CI infra job
CI / Detect changed paths (pull_request) Failing after 0s
CI / Infra unit tests, vet, and preview (pull_request) Has been skipped
CI / Odin unit tests and build (pull_request) Has been skipped
CI / API unit tests and lint (pull_request) Has been skipped
Infra now always runs unit tests + vet on PRs, and additionally runs
`pulumi preview --diff` (posted as a PR comment) when the infra, gui, or
api code changes — since any of those can change what gets deployed.
2026-08-31 14:03:26 -06:00
sam_oneal bd8a7da379 Move Odin renderer into gui/ with per-project Makefiles
CI / Detect changed paths (pull_request) Failing after 1s
CI / Infra unit tests and vet (pull_request) Failing after 1s
CI / Odin unit tests and build (pull_request) Has been skipped
CI / API unit tests and lint (pull_request) Has been skipped
Each sub-project (gui, api, infra) now owns its own Makefile, and the
root Makefile is a lean delegator for the base commands (run, build,
test, clean, fmt). Odin source, deps, and web assets live under gui/
(gui/src, gui/lib, gui/www), with scripts kept under gui/scripts for
build tooling only.
2026-08-31 13:45:58 -06:00
16 changed files with 315 additions and 125 deletions
+94 -11
View File
@@ -1,7 +1,9 @@
# Runs on pull requests: unit tests plus a compile check.
# Split into separate jobs (Odin, API, Infra) so they can run concurrently,
# and gated by changed paths so each only runs when its code changes.
# Infra always runs regardless of what changed.
# Infra always runs (unit tests + vet) regardless of what changed; its Pulumi
# preview (posted as a PR comment) runs when the infra, gui, or api code
# changed, since any of those can change what gets deployed.
name: CI
@@ -28,18 +30,31 @@ jobs:
outputs:
odin: ${{ steps.filter.outputs.odin }}
api: ${{ steps.filter.outputs.api }}
infra: ${{ steps.filter.outputs.infra }}
preview: ${{ steps.decide.outputs.run }}
steps:
- uses: dorny/paths-filter@v4
id: filter
with:
filters: |
odin:
- 'src/**'
- 'lib/**'
- 'gui/**'
- 'scripts/**'
- 'odinfmt.json'
api:
- 'api/**'
infra:
- 'infra/**'
- name: Decide whether to run the infra preview
id: decide
run: |
if [ "${{ steps.filter.outputs.infra }}" = "true" ] || \
[ "${{ steps.filter.outputs.odin }}" = "true" ] || \
[ "${{ steps.filter.outputs.api }}" = "true" ]; then
echo "run=true" >> "$GITHUB_OUTPUT"
else
echo "run=false" >> "$GITHUB_OUTPUT"
fi
odin:
name: Odin unit tests and build
@@ -65,14 +80,10 @@ jobs:
fi
- name: Run Odin unit tests
run: |
mkdir -p lib/local
odin test src -collection:lib=lib/local
run: make -C gui test
- name: Verify build
run: |
mkdir -p bin
odin build src -collection:lib=lib/local -o:speed -out:bin/desi_explorer
run: make -C gui build
api:
name: API unit tests and lint
@@ -103,8 +114,13 @@ jobs:
cargo fmt --all --check
infra:
name: Infra unit tests and vet
name: Infra unit tests, vet, and preview
needs: changes
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: write
steps:
- uses: actions/checkout@v6
with:
@@ -124,3 +140,70 @@ jobs:
run: |
cd infra
go vet ./...
# Pulumi CLI. State uses the local file backend (infra/Pulumi.yaml ->
# file://~/.pulumi), so no Pulumi Cloud token is needed. Preview diffs
# the current source against the last-known stack state; on an ephemeral
# runner the self-hosted environment must persist ~/.pulumi to get a
# meaningful diff (otherwise preview shows the pending creates).
- name: Install Pulumi
if: ${{ needs.changes.outputs.preview == 'true' }}
run: |
curl -fsSL https://get.pulumi.com | sh
echo "$HOME/.pulumi/bin" >> "$GITHUB_PATH"
# The runner must reach the on-prem k3s cluster for preview to diff
# against live state. For a self-hosted runner this is the ambient
# kubeconfig; otherwise populate it from the KUBECONFIG secret here.
- name: Configure kubeconfig
if: ${{ needs.changes.outputs.preview == 'true' }}
run: |
mkdir -p "$HOME/.kube"
if [ -n "$KUBECONFIG_B64" ]; then
printf '%s' "$KUBECONFIG_B64" | base64 -d > "$HOME/.kube/config"
fi
env:
KUBECONFIG_B64: ${{ secrets.KUBECONFIG }}
- name: Pulumi preview
if: ${{ needs.changes.outputs.preview == 'true' }}
working-directory: infra
env:
PULUMI_SKIP_UPDATE_CHECK: 'true'
run: |
go mod download
pulumi preview --diff 2>&1 | tee /tmp/pulumi-preview.txt || true
- name: Comment preview on PR
if: ${{ needs.changes.outputs.preview == 'true' }}
env:
GITEA_API: ${{ gitea.api_url }}
REPO: ${{ gitea.repository }}
TOKEN: ${{ github.token }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
python3 - <<'PY'
import json, os, urllib.request
with open('/tmp/pulumi-preview.txt') as f:
preview = f.read().strip() or '(no changes)'
body = "### Pulumi preview\n\n```\n" + preview + "\n```"
payload = json.dumps({"body": body}).encode()
url = (
f"{os.environ['GITEA_API']}/repos/{os.environ['REPO']}"
f"/issues/{os.environ['PR_NUMBER']}/comments"
)
req = urllib.request.Request(
url,
data=payload,
method='POST',
headers={
'Authorization': f"token {os.environ['TOKEN']}",
'Content-Type': 'application/json',
},
)
urllib.request.urlopen(req)
print('Posted Pulumi preview comment')
PY
+2 -4
View File
@@ -53,10 +53,8 @@ jobs:
base: ${{ steps.prev.outputs.prev }}
filters: |
odin:
- 'src/**'
- 'lib/**'
- 'gui/**'
- 'scripts/**'
- 'odinfmt.json'
api:
- 'api/**'
infra:
@@ -84,7 +82,7 @@ jobs:
- name: Build WebAssembly
run: |
source /tmp/emsdk/emsdk_env.sh
scripts/build_web.sh
gui/scripts/build_web.sh
- name: Package
run: |
+6 -6
View File
@@ -49,8 +49,8 @@ jobs:
- name: Build
run: |
mkdir -p lib/local build/linux
odin build src -o:speed -collection:lib=lib/local -out:build/linux/desi_explorer
mkdir -p build/linux
odin build gui/src -o:speed -collection:lib=gui/lib/local -out:build/linux/desi_explorer
- name: Package
run: |
@@ -110,10 +110,10 @@ jobs:
# next to desi_explorer.exe.
- name: Build
run: |
mkdir -p lib/local build/windows
odin build src -target:windows_amd64 -build-mode:obj \
mkdir -p build/windows
odin build gui/src -target:windows_amd64 -build-mode:obj \
-define:RAYLIB_SHARED=true -o:speed \
-collection:lib=lib/local -out:build/windows/desi_explorer
-collection:lib=gui/lib/local -out:build/windows/desi_explorer
x86_64-w64-mingw32-gcc -O2 -o build/windows/desi_explorer.exe \
build/windows/desi_explorer.obj \
/tmp/odin-win/dist/vendor/raylib/windows/raylibdll.lib \
@@ -151,7 +151,7 @@ jobs:
- name: Build WebAssembly
run: |
source /tmp/emsdk/emsdk_env.sh
scripts/build_web.sh
gui/scripts/build_web.sh
- name: Package
run: |
+15 -14
View File
@@ -2,27 +2,28 @@
Odin + raylib interactive 3D universe map (DESI data), a Rust + axum API, with Go + Pulumi infra and Gitea Actions CI. A clean `odin build` + `cargo test` + `go test` is the verification step.
## Commands (root Makefile)
- Run: `make run` (`odin run src`); Build: `make build` (`odin build src -collection:lib=lib/local -out:bin/desi_explorer`)
- Web: `make build-web` (Emscripten/WASM -> build/web); Debug: `make build-debug`
- Test: `make test` (runs `odin test` for src/, `go test` for infra/, and `cargo test` for api/); Clean: `make clean`
- API: `make api-run` (`cargo run` in api/), `make api-test`, `make api-check` (`cargo fmt --check` + `clippy -D warnings`)
## Commands
The root `Makefile` is a lean delegator: base commands (`run`, `build`, `test`, ...) forward into the per-project Makefiles in `gui/`, `api/`, and `infra/`. Project-specific commands are reached via `make -C <dir> <target>`.
- Run: `make run`; Build: `make build` (`-> bin/desi_explorer`); Web: `make build-web` (Emscripten/WASM -> `build/web`); Debug: `make build-debug`
- Test: `make test` (runs `odin test` in gui/, `cargo test` in api/, `go test` in infra/); Clean: `make clean`; Format: `make fmt`
- API: `make api-run`, `make api-test`, `make api-check` (thin passthroughs to `make -C api <target>`)
- Setup: `make setup` (submodules + `go mod tidy` in infra/)
- Infra: `make infra-preview`, `make infra-up`, `make infra-down`, `make infra-refresh` (Pulumi, `--cwd infra`)
- Infra: `make infra-preview`, `make infra-up`, `make infra-down`, `make infra-refresh` (passthroughs to `make -C infra <target>`)
- Renovate: `make renovate-validate` (npx renovate-config-validator)
- Format Odin with `odinfmt` (config `odinfmt.json`: tabs, width 80); format Rust with `cargo fmt`
- Format Odin with `odinfmt` (config `gui/odinfmt.json`: tabs, width 80); format Rust with `cargo fmt`
## Layout
- `src/main.odin` entrypoint; loop is `update()``draw()`; resizable window with an orbital `Camera3D`; point cloud generated procedurally in `make_universe`.
- `lib/` — third-party Odin deps (submodules / vendored libs). raylib is **not** here: it ships vendored with Odin and is imported as `vendor:raylib`. `lib/local/` is the default `-collection:lib` target and is currently empty.
- `api/` — Rust + axum backend API that will serve DESI catalog data. `src/lib.rs` exposes `routes`/`models`/`config`; `src/main.rs` is the server entrypoint (binds `API_BIND_ADDR`, default `0.0.0.0:8080`). Crate name is `desi-explorer-api` (lib `desi_explorer_api`); Rust version pinned in `api/rust-toolchain.toml`.
- `infra/` — Go + Pulumi (`runtime: go`) targeting the on-prem k3s cluster via the default kubeconfig, mirroring the `homelab` repo's pattern. Module name is `desi-explorer-infra`.
- `.gitea/workflows/``ci.yml` (PR: install Odin, Rust, `odin test` + build, `cargo test` + clippy, `go test`) and `release.yml` (tag `v*`: build native + WASM + publish a Gitea release).
- `gui/` — the Odin + raylib renderer. `gui/src/main.odin` is the entrypoint (loop is `update()``draw()`; resizable window with an orbital `Camera3D`; point cloud generated procedurally in `make_universe`). `gui/lib/` holds third-party Odin deps (see below), `gui/www/` the Web GUI (WASM shell / static web assets), and `gui/scripts/` the build scripts. `gui/Makefile` owns the Odin targets.
- `gui/lib/` — third-party Odin deps (submodules / vendored libs). raylib is **not** here: it ships vendored with Odin and is imported as `vendor:raylib`. `gui/lib/local/` is the default `-collection:lib` target and is currently empty.
- `api/` — Rust + axum backend API that will serve DESI catalog data. `src/lib.rs` exposes `routes`/`models`/`config`; `src/main.rs` is the server entrypoint (binds `API_BIND_ADDR`, default `0.0.0.0:8080`). Crate name is `desi-explorer-api` (lib `desi_explorer_api`); Rust version pinned in `api/rust-toolchain.toml`. `api/Makefile` owns the Rust targets.
- `infra/` — Go + Pulumi (`runtime: go`) targeting the on-prem k3s cluster via the default kubeconfig, mirroring the `homelab` repo's pattern. Module name is `desi-explorer-infra`. `infra/Makefile` owns the Pulumi/Go targets.
- `scripts/` — repo-level build helpers (Odin toolchain install).
- `.gitea/workflows/``ci.yml` (PR: `odin test` + build, `cargo test` + clippy, `go test` + vet; infra always runs tests/vet and posts a `pulumi preview --diff` as a PR comment when infra/gui/api changed) and `release.yml` (tag `v*`: build native + WASM + publish a Gitea release).
## Conventions
- Odin code lives in `src/`; external deps go in `lib/` and are wired via `-collection:lib=lib/local` (or a git submodule imported by relative path).
- Odin code lives in `gui/src/`; external deps go in `gui/lib/` and are wired via `-collection:lib=lib/local` (or a git submodule imported by relative path).
- Everything is plain `make` — no Taskfile — so CI (Gitea Actions) can call `make` directly.
- Keep the renderer (src/), API (api/), and infra (infra/) logically separated; the root Makefile is the only place that ties them together.
- Keep the renderer (gui/), API (api/), and infra (infra/) logically separated; each owns its own Makefile, and the root Makefile is the only place that ties them together.
## Gotchas
- Odin version is pinned in `.gitea/workflows/*.yml` (`ODIN_VERSION`) and defaults in `scripts/install_odin.sh`; bump both together when tracking a new release.
+38 -63
View File
@@ -1,94 +1,69 @@
# DESI Explorer — root Makefile
#
# Orchestrates the Odin renderer (src/) and the Go/Pulumi infrastructure
# (infra/). Intended to be called directly by Gitea Actions CI.
# Lean orchestrator: the "base" commands (`run`, `build`, `test`, ...) delegate
# into the per-project Makefiles in `gui/`, `api/`, and `infra/`. Project-
# specific commands live in those directories and are reached with
# `make -C <dir> <target>` (or the thin passthrough targets below).
ODIN ?= odin
CARGO ?= cargo
BIN ?= bin
BINARY := $(BIN)/desi_explorer
ODIN_FLAGS := -collection:lib=lib/local
WASM_DEFINE := RAYLIB_WASM_LIB=env.o
GUI := gui
API := api
INFRA := infra
.PHONY: help setup run build build-debug build-web test clean fmt \
api-run api-build api-test api-check api-fmt \
infra-preview infra-up infra-down infra-refresh infra-static \
renovate-validate
help: ## List available targets
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-18s\033[0m %s\n", $$1, $$2}'
@echo ""
@echo "Sub-project targets:"
@echo " \033[36mmake -C gui help\033[0m Odin renderer (run, build, build-web, test, fmt, ...)"
@echo " \033[36mmake -C api help\033[0m Rust API (run, build, test, check, fmt, ...)"
@echo " \033[36mmake -C infra help\033[0m Infra (preview, up, down, refresh, test, ...)"
## ---- Setup ---------------------------------------------------------------
setup: ## Pull submodules + tidy Go deps
@git submodule update --init --recursive
@mkdir -p lib/local
@cd infra && go mod tidy
@$(MAKE) -C $(INFRA) tidy
## ---- Renderer (Odin) -----------------------------------------------------
run: ## Run the native app
@mkdir -p lib/local
$(ODIN) run src $(ODIN_FLAGS)
run: ## Run the native app (gui/)
@$(MAKE) -C $(GUI) run
build: ## Release build -> bin/desi_explorer
@mkdir -p lib/local $(BIN)
$(ODIN) build src $(ODIN_FLAGS) -o:speed -out:$(BINARY)
build: ## Release build -> bin/desi_explorer (gui/)
@$(MAKE) -C $(GUI) build
build-debug: ## Debug build -> bin/desi_explorer
@mkdir -p lib/local $(BIN)
$(ODIN) build src $(ODIN_FLAGS) -o:none -debug -out:$(BINARY)
build-debug: ## Debug build -> bin/desi_explorer (gui/)
@$(MAKE) -C $(GUI) build-debug
build-web: ## WebAssembly build -> build/web (needs emscripten)
@scripts/build_web.sh
build-web: ## WebAssembly build -> build/web (gui/, needs emscripten)
@$(MAKE) -C $(GUI) build-web
test: ## Run tests (Odin src/ + Go infra/ + Rust api/)
@mkdir -p lib/local
$(ODIN) test src $(ODIN_FLAGS)
@cd infra && go test ./...
@cd api && $(CARGO) test
## ---- Aggregates ----------------------------------------------------------
clean: ## Remove build artifacts
rm -rf $(BIN) build
@cd api && $(CARGO) clean
test: ## Test all projects (odin + cargo + go)
@$(MAKE) -C $(GUI) test
@$(MAKE) -C $(API) test
@$(MAKE) -C $(INFRA) test
fmt: ## Format Odin sources with odinfmt
odinfmt src
clean: ## Remove build artifacts from all projects
@$(MAKE) -C $(GUI) clean
@$(MAKE) -C $(API) clean
@$(MAKE) -C $(INFRA) clean
## ---- API (Rust + axum) ---------------------------------------------------
fmt: ## Format all projects (odin + rust)
@$(MAKE) -C $(GUI) fmt
@$(MAKE) -C $(API) fmt
api-run: ## Run the API server (dev)
@cd api && $(CARGO) run
## ---- Passthrough to sub-project Makefiles --------------------------------
api-build: ## Release build the API -> api/target/release/
@cd api && $(CARGO) build --release
api-%: ## Forward a target to the api/ Makefile
@$(MAKE) -C $(API) $*
api-test: ## Run API unit/integration tests
@cd api && $(CARGO) test
api-check: ## Typecheck + format-check + lint the API
@cd api && $(CARGO) fmt --all --check && $(CARGO) clippy --all-targets -- -D warnings
api-fmt: ## Format Rust sources with rustfmt
@cd api && $(CARGO) fmt
## ---- Infrastructure (Go + Pulumi) ----------------------------------------
infra-preview: ## Preview infra changes against the cluster
@pulumi preview --cwd infra
infra-up: ## Deploy/update infra
@pulumi up --cwd infra
infra-down: ## Tear down the stack's resources
@pulumi destroy --cwd infra
infra-refresh: ## Refresh Pulumi state against the live cluster
@pulumi refresh --cwd infra
infra-static: ## Typecheck + vet the Go infra without Pulumi
@cd infra && go build -o /dev/null . && go vet ./...
infra-%: ## Forward a target to the infra/ Makefile
@$(MAKE) -C $(INFRA) $*
## ---- Tooling -------------------------------------------------------------
+31 -16
View File
@@ -42,17 +42,20 @@ Early scaffolding. The application currently:
## Repository Layout
```
src/ Odin source — the interactive 3D experience (entrypoint: src/main.odin)
lib/ Third-party Odin dependencies (submodules / vendored libs)
gui/ Odin renderer — the interactive 3D experience (entrypoint: gui/src/main.odin)
gui/lib/ Third-party Odin dependencies (submodules / vendored libs)
gui/www/ Web GUI — WASM shell / static web assets
gui/scripts/ Build scripts (WASM build helper)
api/ Rust backend API (axum) for serving DESI catalog data
infra/ Go + Pulumi infrastructure-as-code (deploys the experience to k8s)
scripts/ Build helpers (Odin install, WASM build)
scripts/ Repo-level build helpers (Odin install)
.gitea/ Gitea Actions CI/CD workflows
```
The renderer (`src/`), the API (`api/`), and the infrastructure (`infra/`) are
kept in separate directories so their logic stays cleanly separated; all are
orchestrated by the root `Makefile`.
The renderer (`gui/`), the API (`api/`), and the infrastructure (`infra/`) are
kept in separate directories so their logic stays cleanly separated. Each
project carries its own `Makefile`; the root `Makefile` delegates the base
commands (`run`, `build`, `test`, ...) into them.
## Building & Running
@@ -62,21 +65,33 @@ vendor bindings. The web build additionally requires [Emscripten](https://emscri
pinned via `api/rust-toolchain.toml`). The infrastructure requires
[Go](https://go.dev) and [Pulumi](https://www.pulumi.com).
All project commands live in the root `Makefile` (`make help` lists them):
The root `Makefile` delegates everything to the per-project Makefiles
(`make help` lists the base targets):
```sh
make setup # pull submodules + tidy Go deps
make run # run the native app
make build # -> bin/desi_explorer
make build-debug # debug native build
make build-web # -> build/web (wasm + html)
make run # run the native app (gui/)
make build # -> bin/desi_explorer (gui/)
make build-debug # debug native build (gui/)
make build-web # -> build/web (wasm + html, gui/)
make test # odin test + go test + cargo test
make clean # remove build artifacts
make api-run # run the Rust API server
make api-test # cargo test
make api-check # rustfmt check + clippy
make clean # remove build artifacts from all projects
make fmt # format all projects
```
Project-specific targets live in their own `Makefile` and are reached with
`make -C <dir> <target>`:
```sh
make -C gui help # Odin renderer (run, build, build-debug, build-web, test, fmt)
make -C api help # Rust API (run, build, test, check, fmt)
make -C infra help # Infra (preview, up, down, refresh, static, test)
```
The root also provides thin passthroughs: `make api-<target>` and
`make infra-<target>` forward to the corresponding sub-project (e.g.
`make api-check` -> `make -C api check`).
## Dependency Updates (Renovate)
[Renovate](https://github.com/renovatebot/renovate) keeps dependencies up to
@@ -91,5 +106,5 @@ It manages four categories:
- **Infra dependencies** — `infra/go.mod` (`gomod` manager); minor/patch updates grouped into a single PR.
- **API dependencies** — `api/Cargo.toml` (`cargo` manager); minor/patch updates grouped into a single PR.
- **Submodules** — `lib/` submodules via `.gitmodules` (`git-submodules` manager).
- **Submodules** — `gui/lib/` submodules via `.gitmodules` (`git-submodules` manager).
- **Workflow actions** — action versions in `.gitea/workflows/*.yml` (`github-actions` manager, which understands Gitea's `.gitea` layout).
+30
View File
@@ -0,0 +1,30 @@
# api/Makefile — the Rust + axum backend API.
#
# Driven directly with `make -C api <target>` (or via the root Makefile's
# `api-*` convenience targets).
CARGO ?= cargo
.PHONY: help run build test check fmt clean
help: ## List available targets
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-18s\033[0m %s\n", $$1, $$2}'
run: ## Run the API server (dev)
$(CARGO) run
build: ## Release build -> target/release/
$(CARGO) build --release
test: ## Run unit/integration tests
$(CARGO) test
check: ## Format-check + lint (clippy -D warnings)
$(CARGO) fmt --all --check && $(CARGO) clippy --all-targets -- -D warnings
fmt: ## Format Rust sources with rustfmt
$(CARGO) fmt
clean: ## Remove Cargo build artifacts
$(CARGO) clean
+46
View File
@@ -0,0 +1,46 @@
# gui/Makefile — the Odin + raylib renderer (the interactive 3D universe map).
#
# This is the Odin sub-project. It is normally invoked from the repo root via
# `make run`, `make build`, etc. (which delegate here through the root
# Makefile), but it can also be driven directly with `make -C gui <target>`.
#
# `lib/` (third-party Odin deps) lives under `gui/lib`; the `bin/` / `build/`
# output dirs live at the repo root and are referenced through `$(ROOT)`.
ODIN ?= odin
ROOT := ..
BIN := $(ROOT)/bin
BINARY := $(BIN)/desi_explorer
ODIN_FLAGS := -collection:lib=lib/local
WASM_DEFINE := RAYLIB_WASM_LIB=env.o
.PHONY: help run build build-debug build-web test clean fmt
help: ## List available targets
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-18s\033[0m %s\n", $$1, $$2}'
run: ## Run the native app
@mkdir -p lib/local
$(ODIN) run src $(ODIN_FLAGS)
build: ## Release build -> bin/desi_explorer
@mkdir -p lib/local $(BIN)
$(ODIN) build src $(ODIN_FLAGS) -o:speed -out:$(BINARY)
build-debug: ## Debug build -> bin/desi_explorer
@mkdir -p lib/local $(BIN)
$(ODIN) build src $(ODIN_FLAGS) -o:none -debug -out:$(BINARY)
build-web: ## WebAssembly build -> build/web (needs emscripten)
@scripts/build_web.sh
test: ## Run Odin unit tests
@mkdir -p lib/local
$(ODIN) test src $(ODIN_FLAGS)
clean: ## Remove build artifacts
rm -rf $(BIN) build
fmt: ## Format Odin sources with odinfmt
odinfmt src
+2 -1
View File
@@ -1,7 +1,8 @@
# Libraries
Third-party libraries for the DESI Explorer renderer live here, either as git
submodules or vendored directly and wired in via `-collection:lib=lib/local`.
submodules or vendored directly and wired in via `-collection:lib=lib/local`
(as resolved from the `gui/` directory).
- `raylib` is bundled with Odin and imported as `vendor:raylib` — it does **not**
live in this directory.
View File
View File
@@ -1,30 +1,36 @@
#!/usr/bin/env bash
# Builds the WebAssembly ("web") build of DESI Explorer with Odin
# (js_wasm32) + emscripten. Output: build/web/index.html (+ index.wasm, odin.js).
# (js_wasm32) + emscripten. Output: build/web/index.html (+ index.wasm,
# odin.js) at the repo root. Run via `make -C gui build-web`.
#
# Requires:
# - `odin` on PATH with the js_wasm32 target
# - emcc / emscripten active in PATH
# Optional:
# - ODIN_ROOT (defaults to `odin root`)
# - OUT_DIR (defaults to build/web)
# - OUT_DIR (defaults to <repo>/build/web)
set -euo pipefail
OUT_DIR="${OUT_DIR:-build/web}"
# Resolve the gui/ project root so this script works regardless of CWD.
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
GUI_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
ROOT_DIR="$(cd "${GUI_DIR}/.." && pwd)"
OUT_DIR="${OUT_DIR:-${ROOT_DIR}/build/web}"
ODIN_ROOT="${ODIN_ROOT:-$(odin root)}"
mkdir -p lib/local
mkdir -p "${GUI_DIR}/lib/local"
mkdir -p "$OUT_DIR"
# The Odin compiler emits a wasm object; raylib's C code is linked later by
# emcc. `-define:RAYLIB_WASM_LIB=env.o` stops the compiler from trying to
# link the raylib lib itself (emcc does that; it ends up in the final module).
odin build src \
odin build "${GUI_DIR}/src" \
-target:js_wasm32 \
-build-mode:obj \
-define:RAYLIB_WASM_LIB=env.o \
-o:speed \
-collection:lib=lib/local \
-collection:lib="${GUI_DIR}/lib/local" \
-out:"${OUT_DIR}/game"
# Odin's JS runtime glue; the generated module imports functions from it.
@@ -36,7 +42,7 @@ emcc \
-o "${OUT_DIR}/index.html" \
"${OUT_DIR}/game.obj" \
"${ODIN_ROOT}/vendor/raylib/wasm/libraylib.web.a" \
--shell-file scripts/web/index_template.html \
--shell-file "${GUI_DIR}/www/index_template.html" \
-sEXPORTED_RUNTIME_METHODS="['HEAPF32']" \
-sUSE_GLFW=3 \
-sWASM_BIGINT \
View File
+35
View File
@@ -0,0 +1,35 @@
# infra/Makefile — Go + Pulumi infrastructure-as-code.
#
# Driven directly with `make -C infra <target>` (or via the root Makefile's
# `infra-*` convenience targets). Targets that interact with the live cluster
# run Pulumi against the stack defined in Pulumi.yaml.
.PHONY: help preview up down refresh static test clean tidy
help: ## List available targets
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-18s\033[0m %s\n", $$1, $$2}'
preview: ## Preview infra changes against the cluster
pulumi preview
up: ## Deploy/update infra
pulumi up
down: ## Tear down the stack's resources
pulumi destroy
refresh: ## Refresh Pulumi state against the live cluster
pulumi refresh
static: ## Typecheck + vet without Pulumi
go build -o /dev/null . && go vet ./...
test: ## Run Go unit tests
go test ./...
clean: ## Remove local Go build artifact
rm -f desi-explorer-infra
tidy: ## Tidy Go modules
go mod tidy