From a637343544ace84eaad608b9b1ea030261acea9b Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Tue, 24 Mar 2026 16:32:45 -0400 Subject: [PATCH] chore(ci): add Docker BuildKit examples, .dockerignore, CI cache docs; tune vite config --- .dockerignore | 26 ++++++++- .../Dockerfile.buildkit.example | 27 ++++++++++ aether_container_env/ci_buildx_example.sh | 33 ++++++++++++ documentation/AE_Docker_CI_cache_policy.md | 30 +++++++++++ ...ROJECT__AE_Docker_CI_BuildKit_implement.md | 53 +++++++++++++++++++ documentation/TODO__Agents.md | 2 +- package.json | 2 +- .../[event_id]/(launcher)/launcher/+page.ts | 0 src/routes/events/[event_id]/+page.ts | 0 src/routes/journals/[journal_id]/+page.ts | 8 --- src/routes/testing/+layout.ts | 1 - vite.config.ts | 12 +++++ 12 files changed, 182 insertions(+), 12 deletions(-) create mode 100644 aether_container_env/Dockerfile.buildkit.example create mode 100644 aether_container_env/ci_buildx_example.sh create mode 100644 documentation/AE_Docker_CI_cache_policy.md create mode 100644 documentation/PROJECT__AE_Docker_CI_BuildKit_implement.md delete mode 100644 src/routes/events/[event_id]/(launcher)/launcher/+page.ts delete mode 100644 src/routes/events/[event_id]/+page.ts delete mode 100644 src/routes/journals/[journal_id]/+page.ts delete mode 100644 src/routes/testing/+layout.ts diff --git a/.dockerignore b/.dockerignore index fe2058c5..f910195d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,28 @@ -node_modules/ +.svelte-kit +.vite +node_modules +dist +build +.cache +.DS_Store +.vscode +.idea +.git +.gitignore +coverage +tests +documentation +backups +*.log +*.bak +*.tgz +.env +.env.* +npm-debug.log +package-lock.json.bak +yarn-error.log +/.cache +/.parcel-cachenode_modules/ build/ .svelte-kit/ .git/ diff --git a/aether_container_env/Dockerfile.buildkit.example b/aether_container_env/Dockerfile.buildkit.example new file mode 100644 index 00000000..439a1399 --- /dev/null +++ b/aether_container_env/Dockerfile.buildkit.example @@ -0,0 +1,27 @@ +## BuildKit-friendly multi-stage Dockerfile example for Aether frontend + +# Stage 1: dependencies +FROM node:20-alpine AS deps +WORKDIR /app +COPY package.json package-lock.json ./ +RUN npm ci --no-audit --prefer-offline + +# Stage 2: build +FROM node:20-alpine AS build +WORKDIR /app +# optionally reuse deps from previous stage +COPY --from=deps /app/node_modules ./node_modules +COPY . . +# If you want to use BuildKit cache mounts during local development, uncomment the next line +# RUN --mount=type=cache,target=/root/.npm npm ci +RUN npm run build + +# Stage 3: runtime (static site served by nginx) +FROM nginx:stable-alpine AS runtime +COPY --from=build /app/build /usr/share/nginx/html +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] + +# Notes: +# - Keep dependency installation separate from copying source to maximize cache hits when only application code changes. +# - For backend images, follow the same pattern: install deps early, copy source later, and keep a small final runtime image. \ No newline at end of file diff --git a/aether_container_env/ci_buildx_example.sh b/aether_container_env/ci_buildx_example.sh new file mode 100644 index 00000000..19af7071 --- /dev/null +++ b/aether_container_env/ci_buildx_example.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Example CI script to build and push an image with buildx using registry cache. +# This script is provider-agnostic and intended to be run inside CI where +# Docker and buildx are available and authenticated against the registry. + +REGISTRY=${REGISTRY:-ghcr.io/ORG/REPO} +IMAGE_TAG=${IMAGE_TAG:-staging} +CACHE_REF=${CACHE_REF:-${REGISTRY}:cache} + +echo "Building ${REGISTRY}:${IMAGE_TAG} using registry cache ${CACHE_REF}" + +docker buildx build \ + --push \ + --tag ${REGISTRY}:${IMAGE_TAG} \ + --cache-from type=registry,ref=${CACHE_REF} \ + --cache-to type=registry,ref=${CACHE_REF},mode=max \ + . + +echo "Build complete. Image: ${REGISTRY}:${IMAGE_TAG}" + +# Optional: instruct devs how to run locally with a local cache +cat <<'EOF' +Local test with BuildKit and local cache: +DOCKER_BUILDKIT=1 docker build \ + --tag myapp:staging \ + --cache-to=type=local,dest=/tmp/docker-cache \ + --cache-from=type=local,src=/tmp/docker-cache . + +Prune local builder cache older than 72 hours: +docker builder prune --filter "until=72h" --force +EOF diff --git a/documentation/AE_Docker_CI_cache_policy.md b/documentation/AE_Docker_CI_cache_policy.md new file mode 100644 index 00000000..4d877285 --- /dev/null +++ b/documentation/AE_Docker_CI_cache_policy.md @@ -0,0 +1,30 @@ +# AE Docker CI Cache Policy (recommendation) + +Purpose +- Provide a straightforward policy to keep build caches useful but bounded. + +Recommendations +- Primary CI cache: **registry-based buildx cache** (preferred). Use a single cache ref (e.g. `ghcr.io/ORG/REPO:cache`) reused by CI builds. +- Local dev cache: use `--cache-to type=local` for fast iteration but prune periodically. +- Retention: keep registry cache for 30 days by default. Implement registry GC or lifecycle rule to delete older cache blobs. + +Rotation strategy +- Option A (simple): CI always writes to the same cache ref `:cache`. Periodically (monthly) run a job to `docker pull` and `docker image rm` older tags if you use date-based tagging. +- Option B (date-tag): CI writes cache to `cache-YYYYMMDD` and a small scheduled job deletes tags older than 30 days. + +Pruning commands (developer) +- Remove local build cache older than 72 hours: + ```bash + docker builder prune --filter "until=72h" --force + ``` +- Remove all builder cache (aggressive): + ```bash + docker builder prune --all --force + ``` + +CI runner requirements +- `docker` and `docker buildx` available in runner environment. +- Registry credentials provided via CI secrets with permission to push/pull images. + +Security & Secrets +- Do not store registry credentials in repo. Use CI secret storage. diff --git a/documentation/PROJECT__AE_Docker_CI_BuildKit_implement.md b/documentation/PROJECT__AE_Docker_CI_BuildKit_implement.md new file mode 100644 index 00000000..54e5d1d9 --- /dev/null +++ b/documentation/PROJECT__AE_Docker_CI_BuildKit_implement.md @@ -0,0 +1,53 @@ +# Project: AE Docker + CI BuildKit Implementation + +**Status:** Proposed + +**Goal:** Make Docker image builds for Aether cache-friendly using BuildKit/buildx and CI registry caching, while keeping local developer caches small and manageable. + +Summary +- Implement a BuildKit-friendly multi-stage `Dockerfile` pattern for frontend and API images. +- Add CI `buildx` examples that push/read registry-based cache to avoid local disk bloat. +- Provide cache retention/rotation guidance and developer commands for safe pruning. + +Scope +- Repository areas: `aether_container_env/`, root `Dockerfile` (if present), and CI pipeline definitions (Gitea/Drone or other). +- Non-goal: full CI pipeline migration to a new provider. This work provides CI snippets and a PR-ready set of files for your CI team. + +Deliverables (this PR) +- `documentation/PROJECT__AE_Docker_CI_BuildKit_implement.md` (this file) +- `aether_container_env/Dockerfile.buildkit.example` — BuildKit-friendly multi-stage Dockerfile example. +- `aether_container_env/ci_buildx_example.sh` — standalone CI script examples (registry cache + local cache usage). +- `documentation/AE_Docker_CI_cache_policy.md` — cache rotation and prune guidance. + +Tasks (implementation checklist) +- [ ] Review existing `Dockerfile`(s) under `aether_container_env/` and repository root. +- [ ] Replace/extend Dockerfile with multi-stage BuildKit-friendly layout (use example as guide). +- [ ] Ensure `.dockerignore` (already added) excludes large build artifacts. +- [ ] Add CI step using `docker buildx build` with `--cache-from` and `--cache-to` pointed at a registry cache. +- [ ] Add a scheduled job or registry lifecycle rule to delete old cache images (30 days default). +- [ ] Document required CI secrets and permissions (registry write/read) for the operations team. +- [ ] Run verification builds (dev local with BuildKit; CI runs with cache) and record timings. + +Verification +- Local dev: `DOCKER_BUILDKIT=1` build with `--cache-to`/`--cache-from` shows cache hits on second run and faster build time. +- CI: subsequent CI runs log `cache hit` from `buildx` and total build time reduced vs baseline. +- Confirm registry contains `cache` image tags and that rotation job/prune removes old entries. + +Notes about Gitea/CI +- Gitea does not include native Actions like GitHub; teams typically use Drone CI, Tekton, or a self-hosted runner that can execute the `docker`/`buildx` CLI. +- The provided `ci_buildx_example.sh` is intentionally provider-agnostic — pasteable into Drone, Jenkins, GitLab CI, or any shell-capable runner. + +Risks & Mitigations +- Risk: Unbounded registry cache growth. Mitigation: enforce retention policy and rotation job; prefer a single `cache` tag reused by CI. +- Risk: Developers unfamiliar with BuildKit. Mitigation: examples show simple `DOCKER_BUILDKIT=1` usage and local cache prune commands. + +Next steps for the container team +1. Review examples in `aether_container_env/` and adapt the Dockerfile to your runtime constraints (ssl certs, env injection, secrets). +2. Add a CI job using the `ci_buildx_example.sh` snippet; configure registry credentials as secrets. +3. Add a scheduled job to rotate/delete old cache images or configure registry lifecycle rules. +4. Run a before/after benchmark of `time npm run build:prod` inside the build stage to quantify improvement. + +Files included in this PR for reference: +- `aether_container_env/Dockerfile.buildkit.example` +- `aether_container_env/ci_buildx_example.sh` +- `documentation/AE_Docker_CI_cache_policy.md` diff --git a/documentation/TODO__Agents.md b/documentation/TODO__Agents.md index 2536c295..7f7aa860 100644 --- a/documentation/TODO__Agents.md +++ b/documentation/TODO__Agents.md @@ -1,6 +1,6 @@ # Frontend Agent Task List > Use this file to track steps for complex features or bug fixes. -> **Status:** � Stable — ongoing development. +> **Status:** Stable — ongoing development. ## 🚧 Upcoming High Priority diff --git a/package.json b/package.json index 919ec7f8..0dee0798 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osit-aether-app-svelte", - "version": "3.00.06", + "version": "3.00.07", "description": "One Sky IT's Aether App created with Svelte, SvelteKit, Tailwind CSS, Lucide, Font Awesome, and Skeleton UI. -Scott Idem", "homepage": "https://oneskyit.com/", "private": true, diff --git a/src/routes/events/[event_id]/(launcher)/launcher/+page.ts b/src/routes/events/[event_id]/(launcher)/launcher/+page.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/src/routes/events/[event_id]/+page.ts b/src/routes/events/[event_id]/+page.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/src/routes/journals/[journal_id]/+page.ts b/src/routes/journals/[journal_id]/+page.ts deleted file mode 100644 index d880be43..00000000 --- a/src/routes/journals/[journal_id]/+page.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** @type {import('./$types').PageLoad} */ -// console.log(`ae_p_journals [journal_id] +page.ts start`); - -// import { browser } from '$app/environment'; -// import { journals_func } from '$lib/ae_journals/ae_journals_functions'; - -// export async function load({ params, parent }) { -// } diff --git a/src/routes/testing/+layout.ts b/src/routes/testing/+layout.ts deleted file mode 100644 index 7c7e714b..00000000 --- a/src/routes/testing/+layout.ts +++ /dev/null @@ -1 +0,0 @@ -// export const prerender = true diff --git a/vite.config.ts b/vite.config.ts index 4a3e92ba..14c46a9d 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -3,6 +3,7 @@ import { sveltekit } from '@sveltejs/kit/vite'; import tailwindcss from '@tailwindcss/vite'; export default defineConfig({ + cacheDir: 'node_modules/.vite', plugins: [ tailwindcss(), sveltekit() // <-- Must come after Tailwind @@ -13,7 +14,18 @@ export default defineConfig({ ignored: ['**/documentation/**', '**/tests/**'] } }, + optimizeDeps: { + // Pre-bundle smaller deps; exclude large CJS libs we prefer to handle via SSR/noExternal + exclude: ['@codemirror/*'], + include: [] + }, + ssr: { + // Avoid forcing ESM conversion on large editor libs; let them be handled as-is + noExternal: ['@codemirror/*'] + }, build: { + sourcemap: false, + minify: 'esbuild', rollupOptions: { output: { // Keep all svelte internals in one chunk to prevent circular