ci: include dagger and nix build files for admin app
Build Admin / build (push) Failing after 28s Details

This commit is contained in:
Seth Call 2026-03-09 22:11:54 -05:00
parent 6451787b89
commit 2edb7f029e
11 changed files with 241 additions and 42 deletions

1
admin/ci/.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
/sdk/** linguist-generated

4
admin/ci/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/sdk
/**/node_modules/**
/**/.pnpm-store/**
/.env

52
admin/ci/bun.lock Normal file
View File

@ -0,0 +1,52 @@
{
"lockfileVersion": 1,
"workspaces": {
"": {
"name": "jamkazam-admin-ci",
"dependencies": {
"chokidar": "^3.6.0",
"typescript": "5.9.3",
},
"devDependencies": {
"@types/node": "^20.0.0",
},
},
},
"packages": {
"@types/node": ["@types/node@20.19.37", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw=="],
"anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="],
"binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="],
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
"chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="],
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
"glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
"is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="],
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
"normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="],
"picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="],
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
}
}

10
admin/ci/package.json Normal file
View File

@ -0,0 +1,10 @@
{
"name": "jamkazam-admin-ci",
"version": "1.0.0",
"dependencies": {
"chokidar": "^3.6.0"
,"typescript":"5.9.3"},
"devDependencies": {
"@types/node": "^20.0.0"
}
,"type":"module"}

View File

@ -43,6 +43,19 @@ export class Admin {
return `Shipped ${version}`;
}
/**
* Generate a unique tag based on CalVer + User + Source Digest
*/
@func()
async devTag(source: Directory): Promise<string> {
const hash = await source.digest();
const shortHash = hash.split(":")[1].substring(0, 8);
const d = new Date();
const calVer = `${d.getFullYear()}.${(d.getMonth() + 1)}.${d.getDate()}-${d.getHours()}${d.getMinutes()}`;
const user = process.env.USER || "unknown";
return `${calVer}-${user}-${shortHash}`;
}
private async buildWithNix(source: Directory, platform: Platform): Promise<Container> {
// 1. Start with a Nix-enabled container
let builder = dag.container({ platform })
@ -52,6 +65,7 @@ export class Admin {
// 2. Build the image tarball via Nix
// Add a dummy env var to bust cache if needed
.withEnvVariable("CACHE_BUST", new Date().getTime().toString())
.withEnvVariable("TIMESTAMP", new Date().getTime().toString())
.withExec(["nix", "--extra-experimental-features", "nix-command flakes", "build", ".#appImageTarball", "--out-link", "result-tarball"]);
try {

13
admin/ci/tsconfig.json Normal file
View File

@ -0,0 +1,13 @@
{
"compilerOptions": {
"target": "ES2022",
"moduleResolution": "Node",
"experimentalDecorators": true,
"strict": true,
"skipLibCheck": true,
"paths": {
"@dagger.io/dagger": ["./sdk/index.ts"],
"@dagger.io/dagger/telemetry": ["./sdk/telemetry.ts"]
}
}
}

31
admin/ci/watch.ts Normal file
View File

@ -0,0 +1,31 @@
import chokidar from "chokidar";
import { execSync } from "child_process";
// Configuration
const WATCH_PATHS = ["app/**/*.rb", "spec/**/*.rb", "config/**/*.rb", "db/schema.rb"];
const DAGGER_CLI = "dagger call";
console.log("🚀 SOTA Rails Watcher Started. Monitoring for changes...");
const watcher = chokidar.watch(WATCH_PATHS, {
ignored: /(^|[\/\])\../, // ignore dotfiles
persistent: true,
});
watcher.on("change", (path) => {
console.log(`
📄 File changed: ${path}`);
if (path.endsWith("_spec.rb") || path.startsWith("app/")) {
console.log("🧪 Running Targeted RSpec via Dagger...");
try {
execSync(`${DAGGER_CLI} validate --source=.`, { stdio: "inherit" });
} catch (e) {
console.error("❌ Test failed.");
}
}
if (path.startsWith("config/deploy")) {
console.log("🚢 Infrastructure change detected. Skipping full deploy in dev loop.");
}
});

8
admin/dagger.json Normal file
View File

@ -0,0 +1,8 @@
{
"name": "admin",
"engineVersion": "v0.20.1",
"sdk": {
"source": "typescript"
},
"source": "ci"
}

View File

@ -73,13 +73,15 @@
libxslt.dev
jemalloc
vips
tzdata
cacert
bash
coreutils
git
gnumake
gcc
pkg-config
binutils
nodejs
];
};
@ -88,6 +90,7 @@
export PATH=${allDeps}/bin:$PATH
export LD_LIBRARY_PATH=${allDeps}/lib:$LD_LIBRARY_PATH
export PKG_CONFIG_PATH=${allDeps}/lib/pkgconfig
export TZDIR=/share/zoneinfo
cd /jam-cloud/admin
@ -98,13 +101,24 @@
echo "💎 Installing gems..."
bundle install
echo "🎨 Precompiling assets..."
SECRET_KEY_BASE_DUMMY=1 bundle exec rails assets:precompile
echo "🚀 Starting Rails..."
exec bundle exec rails server -b 0.0.0.0
'';
appImage = pkgs.dockerTools.buildLayeredImage {
name = "jamkazam-admin-v3";
appImage = pkgs.dockerTools.buildImage {
name = "jamkazam-admin";
tag = "local";
copyToRoot = [
allDeps
start-jam-admin
pkgs.libyaml.dev
pkgs.openssl.dev
pkgs.postgresql_16.lib
pkgs.zlib.dev
];
config = {
Cmd = [ "${start-jam-admin}/bin/start-jam-admin" ];
Env = [
@ -113,17 +127,12 @@
"RAILS_ENV=production"
"RAILS_SERVE_STATIC_FILES=true"
"PKG_CONFIG_PATH=${allDeps}/lib/pkgconfig"
"TZDIR=/share/zoneinfo"
"SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt"
"JAM_VERSION=0.0.1"
];
ExposedPorts = { "3000/tcp" = {}; };
};
contents = [
allDeps
start-jam-admin
pkgs.libyaml.dev
pkgs.openssl.dev
pkgs.postgresql_16.lib
pkgs.zlib.dev
];
};
in {
inherit appImage;

View File

@ -2,72 +2,107 @@ set shell := ["bash", "-c"]
NIX := "/nix/var/nix/profiles/default/bin/nix"
# Start local backing services (one-time, no boot persistence)
# Start local backing services
infra:
@echo "🐰 Starting RabbitMQ..."
brew services run rabbitmq || true
@echo "💾 Starting Redis..."
brew services run redis || true
@echo "✅ Local infra is running. Use 'brew services list' to verify."
@echo "✅ Local infra is running."
# Setup environment
setup:
@echo "🔧 Installing SOTA stack dependencies..."
cd ci && ~/.bun/bin/bun install
@if [ ! -f dagger.json ]; then \
echo "Initializing Dagger module..."; \
dagger init --sdk=typescript --source=ci; \
fi
# Start coding natively (Track 1)
watch:
~/.bun/bin/bun run ci/watch.ts
# Enter the native Nix development environment
shell:
{{NIX}} develop
# Fast native validation in Dagger (Track 2)
validate:
dagger call --progress=plain validate --source=.
# Build local ARM64 image via Dagger and export to OrbStack
build:
@echo "🔨 Building image via Dagger..."
@rm -f ./admin.tar
dagger call --progress=plain build-local --source=. export --path=./admin.tar
@echo "🧹 Cleaning up old Docker artifacts to free space..."
docker system prune -f
@echo "📦 Loading image into Docker..."
build tag="latest":
#!/bin/bash
set -e
echo "🔨 Building image via Dagger..."
rm -f ./admin.tar
dagger call --progress=plain build-local --source=. export --path=./admin.tar
echo "📦 Loading image into Docker..."
LOAD_OUTPUT=$(docker load < ./admin.tar)
echo "$LOAD_OUTPUT"
IMAGE_ID=$(echo "$LOAD_OUTPUT" | awk '/Loaded image ID: sha256:/ {print $4}' | cut -d: -f2)
if [ -z "$IMAGE_ID" ]; then
IMAGE_ID=$(echo "$LOAD_OUTPUT" | grep -oE '[0-9a-f]{12,}' | tail -n 1)
IMAGE_ID=$(echo "$LOAD_OUTPUT" | grep -oE '[0-9a-f]{12,}' | tail -n 1)
fi
if [ -z "$IMAGE_ID" ]; then
echo "❌ Failed to extract image ID from docker load output."
exit 1
fi
echo "Tagging $IMAGE_ID as jamkazam-admin:local-v2..."
docker tag "$IMAGE_ID" jamkazam-admin:local-v2
rm ./admin.tar
echo "✅ Image loaded as 'jamkazam-admin:local-v2'"
# Run Rails server natively using the Nix shell (SOTA Inner Loop)
echo "🏷️ Tagging $IMAGE_ID as jamkazam-admin:{{tag}}..."
docker tag "$IMAGE_ID" jamkazam-admin:{{tag}}
echo "✅ Image loaded as 'jamkazam-admin:{{tag}}'"
# Run Rails server natively
dev: infra
{{NIX}} develop --command bash -c "bundle install && bundle exec rails server"
# Run the local image in OrbStack, connected to host infra
# Smart Run: Detects changes, builds if needed, then runs
run:
#!/bin/bash
set -e
echo "🔍 Checking for source changes..."
TAG=$(dagger call --quiet dev-tag --source=. | tr -d '\n' | tr -d '"')
echo "🏷️ Current Source Tag: $TAG"
if ! docker image inspect jamkazam-admin:$TAG >/dev/null 2>&1; then
echo "✨ Source changed or image missing. Building..."
just build "$TAG"
else
echo "🚀 Source unchanged. Using cached image."
fi
docker run -it --rm \
-p 3000:3000 \
-p 0.0.0.0:3333:3000 \
-v {{invocation_directory()}}/..:/jam-cloud \
-w /jam-cloud/admin \
-e DATABASE_URL="postgres://postgres:postgres@host.orb.internal:5432/jam" \
-e REDIS_URL="redis://host.orb.internal:6379/1" \
-e RABBITMQ_URL="amqp://guest:guest@host.orb.internal:5672" \
-e RAILS_MASTER_KEY=$RAILS_MASTER_KEY \
jamkazam-admin:local-v2
-e SECRET_KEY_BASE=${SECRET_KEY_BASE:-dummy_secret_key_base_for_sanity_check} \
-e AWS_KEY=$AWS_ACCESS_KEY_ID \
-e AWS_SECRET=$AWS_SECRET_ACCESS_KEY \
jamkazam-admin:$TAG
# The Big Red Button
ship:
@echo "🚀 Shipping to Production..."
dagger call ship --source=. --kubeconfig=file:$KUBECONFIG --registry="your-registry.io"
# Purge everything to reclaim disk space
clean: clean-docker clean-dagger clean-nix clean-rails
@echo "🧹 All systems cleaned."
rm -f *.tar result-tarball
# Aggressive Docker prune (including volumes and unused images)
clean-docker:
@echo "🐳 Cleaning Docker (Images + Volumes)..."
docker system prune -a -f || true
docker volume prune -f || true
# Prune Dagger cache specifically
clean-dagger:
@echo "🗡️ Cleaning Dagger cache..."
dagger core engine prune || true
# Also remove the dagger engine container if it's hanging on to space
docker rm -f $(docker ps -a -q --filter "name=dagger-engine") || true
# Hard-vacuum Nix store
clean-nix:
{{NIX}}-collect-garbage -d
{{NIX}}-store --gc
{{NIX}}-store --optimise
clean-rails:
rm -rf log/*.log tmp/*

22
dagger.json Normal file
View File

@ -0,0 +1,22 @@
{
"name": "jam-cloud",
"engineVersion": "v0.20.1",
"sdk": {
"source": "typescript"
},
"dependencies": [
{
"name": "admin",
"source": "admin"
},
{
"name": "web",
"source": "web"
},
{
"name": "websocket-gatewaysocket-gateway",
"source": "websocket-gateway"
}
],
"source": "ci"
}