Infra: Worker/Garage/Test-Runner
- docker-compose.yml: explizite Build-Targets (runner/migrate) — Ursache für "npx not found" bei garage-provision war das Default-Target (letzte Stage = Garage-Image ohne Node); worker startet npm run worker:mail; Defaults craftvia - Coolify-Compose: incident-inbound-worker und sync-policy-templates entfernt, Rollen-/Bucket-/Image-Namen auf craftvia - Dockerfile: seed/ und docs/wizard-uebergabe entfernt, messages/ im Runner - npm: Name craftvia, Scripts test (scripts/run-tests.ts) und gate, ISMS-Pakete entfernt (handlebars, marked, sanitize-html, @xyflow/react, @dagrejs/dagre, html-to-image, imapflow, mailparser, exceljs, @dnd-kit/core) - .env-Beispiele, launch.json (craftvia-dev), CI-Kommentare umbenannt Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,16 +8,16 @@
|
||||
# - Vorher an der Registry angemeldet: docker login "$REGISTRY_HOST"
|
||||
#
|
||||
# Aufruf (im Repo-Root, auf dem gewünschten Commit ausgecheckt):
|
||||
# REGISTRY=git.certvia.de/msolarczek TAG=$(git rev-parse --short HEAD) ./scripts/build-and-push-images.sh
|
||||
# REGISTRY=registry.example.com/craftvia TAG=$(git rev-parse --short HEAD) ./scripts/build-and-push-images.sh
|
||||
#
|
||||
# Env-Variablen:
|
||||
# REGISTRY Image-Präfix (Default: git.certvia.de/msolarczek)
|
||||
# REGISTRY Image-Präfix (Default: registry.example.com/craftvia)
|
||||
# TAG Image-Tag (Default: kurzer Git-SHA des aktuellen HEAD)
|
||||
# PLATFORM Zielplattform (Default: linux/amd64 — passend zum Prod-Host)
|
||||
# ALSO_MAIN wenn "true": zusätzlich das bewegliche Tag :main setzen/pushen
|
||||
set -euo pipefail
|
||||
|
||||
REGISTRY="${REGISTRY:-git.certvia.de/msolarczek}"
|
||||
REGISTRY="${REGISTRY:-registry.example.com/craftvia}"
|
||||
TAG="${TAG:-$(git rev-parse --short HEAD)}"
|
||||
PLATFORM="${PLATFORM:-linux/amd64}"
|
||||
ALSO_MAIN="${ALSO_MAIN:-false}"
|
||||
@@ -43,13 +43,13 @@ build_one() {
|
||||
|
||||
# migrate + runner teilen sich die teuren Stages deps/builder (npm ci + next build).
|
||||
# Sequentiell auf demselben Host -> zweiter Build nutzt den Layer-Cache des ersten.
|
||||
build_one runner certvia-app
|
||||
build_one migrate certvia-migrate
|
||||
build_one garage certvia-garage
|
||||
build_one runner craftvia-app
|
||||
build_one migrate craftvia-migrate
|
||||
build_one garage craftvia-garage
|
||||
|
||||
echo
|
||||
echo ">> Push ..."
|
||||
for name in certvia-app certvia-migrate certvia-garage; do
|
||||
for name in craftvia-app craftvia-migrate craftvia-garage; do
|
||||
docker push "$REGISTRY/$name:$TAG"
|
||||
[ "$ALSO_MAIN" = "true" ] && docker push "$REGISTRY/$name:main" || true
|
||||
done
|
||||
|
||||
@@ -10,7 +10,7 @@ import "dotenv/config";
|
||||
* betriebsbereiten Zustand her:
|
||||
* 1. Layout: dem Node einmalig Zone + Kapazität zuweisen und anwenden (ohne Layout
|
||||
* lehnt Garage jeden Schreibzugriff mit „no capacity" ab).
|
||||
* 2. Bucket `S3_BUCKET` (Default isms-documents) anlegen.
|
||||
* 2. Bucket `S3_BUCKET` (Default craftvia-documents) anlegen.
|
||||
* 3. Access-Key deterministisch IMPORTIEREN — aus S3_ACCESS_KEY/S3_SECRET_KEY der
|
||||
* Coolify-Env, damit App-Env und Garage denselben Schlüssel teilen (kein
|
||||
* Nachpflegen erzeugter Keys).
|
||||
@@ -58,7 +58,7 @@ function readCfg(): Cfg | null {
|
||||
}
|
||||
const accessKeyId = process.env.S3_ACCESS_KEY?.trim();
|
||||
const secretKey = process.env.S3_SECRET_KEY?.trim();
|
||||
const bucket = process.env.S3_BUCKET?.trim() || "isms-documents";
|
||||
const bucket = process.env.S3_BUCKET?.trim() || "craftvia-documents";
|
||||
if (!accessKeyId || !secretKey) {
|
||||
throw new Error(
|
||||
"GARAGE_ADMIN_TOKEN ist gesetzt, aber S3_ACCESS_KEY/S3_SECRET_KEY fehlen. " +
|
||||
@@ -210,7 +210,7 @@ async function ensureKey(cfg: Cfg): Promise<void> {
|
||||
const imported = await admin(cfg, "POST", "/v1/key/import", {
|
||||
accessKeyId: cfg.accessKeyId,
|
||||
secretAccessKey: cfg.secretKey,
|
||||
name: "isms-app",
|
||||
name: "craftvia-app",
|
||||
});
|
||||
if (imported.status === 200) {
|
||||
log(`Access-Key ${cfg.accessKeyId} importiert.`);
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Test-Runner: führt alle `scripts/test-*.ts` nacheinander via tsx aus und liefert eine
|
||||
* Zusammenfassung + Exit-Code (≠ 0, sobald ein Test scheitert).
|
||||
*
|
||||
* Voraussetzungen: lokale Infra (Postgres/Redis/Garage) läuft, `.env` gesetzt, Datenbank
|
||||
* migriert und geseedet (`npx prisma migrate deploy && npx prisma db seed`).
|
||||
*
|
||||
* Lauf: npm run test (alle)
|
||||
* npm run test -- mail tenant (nur Tests, deren Name einen der Filter enthält)
|
||||
*/
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { readdirSync } from "node:fs";
|
||||
import { join, dirname } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const SCRIPTS_DIR = dirname(fileURLToPath(import.meta.url));
|
||||
const filters = process.argv.slice(2);
|
||||
|
||||
const tests = readdirSync(SCRIPTS_DIR)
|
||||
.filter((f) => /^test-.+\.ts$/.test(f))
|
||||
.filter((f) => filters.length === 0 || filters.some((flt) => f.includes(flt)))
|
||||
.sort();
|
||||
|
||||
if (tests.length === 0) {
|
||||
console.error("Keine Tests gefunden.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const results: { name: string; ok: boolean; ms: number }[] = [];
|
||||
for (const file of tests) {
|
||||
const started = Date.now();
|
||||
console.log(`\n━━━ ${file} ━━━`);
|
||||
const run = spawnSync(process.execPath, ["--import", "tsx", join(SCRIPTS_DIR, file)], {
|
||||
stdio: "inherit",
|
||||
env: process.env,
|
||||
});
|
||||
results.push({ name: file, ok: run.status === 0, ms: Date.now() - started });
|
||||
}
|
||||
|
||||
const failed = results.filter((r) => !r.ok);
|
||||
console.log("\n══════════ Test-Zusammenfassung ══════════");
|
||||
for (const r of results) console.log(`${r.ok ? "✓" : "✗"} ${r.name.padEnd(36)} ${(r.ms / 1000).toFixed(1)}s`);
|
||||
console.log(`\n${results.length - failed.length}/${results.length} Testskripte grün${failed.length ? ` — ${failed.length} fehlgeschlagen` : ""}.`);
|
||||
process.exit(failed.length ? 1 : 0);
|
||||
Reference in New Issue
Block a user