Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da12b3946a | ||
|
|
41b02b9564 | ||
|
|
be85ea3093 |
No files matched your search
@@ -1,17 +1,21 @@
|
||||
name: MindSift CI & Docker Release
|
||||
|
||||
# Image tags:
|
||||
# push to dev -> :dev
|
||||
# push/merge main -> :latest
|
||||
# git tag v1.2.0 -> :v1.2.0 and :stable
|
||||
on:
|
||||
push:
|
||||
branches-ignore:
|
||||
branches:
|
||||
- dev
|
||||
- main
|
||||
tags:
|
||||
- '*'
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
build-test-push:
|
||||
name: Build, Test in Container & Push
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref != 'refs/heads/main'
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
@@ -33,9 +37,17 @@ jobs:
|
||||
# Ersetze evtl. Slashes in Branch-Namen (z.B. rc/1.1 -> rc-1.1) für valide Docker-Tags
|
||||
DOCKER_TAG=$(echo "${REF_NAME}" | sed 's#/#-#g' | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
# All tags of this run (space separated)
|
||||
case "${GITHUB_REF:-}" in
|
||||
refs/tags/*) TAGS="${DOCKER_TAG} stable" ;;
|
||||
refs/heads/main) TAGS="latest" ;;
|
||||
*) TAGS="${DOCKER_TAG}" ;;
|
||||
esac
|
||||
|
||||
echo "registry=${REGISTRY_HOST}" >> "$GITHUB_OUTPUT"
|
||||
echo "image=${IMAGE_NAME}" >> "$GITHUB_OUTPUT"
|
||||
echo "tag=${DOCKER_TAG}" >> "$GITHUB_OUTPUT"
|
||||
echo "tag=${TAGS%% *}" >> "$GITHUB_OUTPUT"
|
||||
echo "tags=${TAGS}" >> "$GITHUB_OUTPUT"
|
||||
echo "actor=${ACTOR_NAME}" >> "$GITHUB_OUTPUT"
|
||||
# Releases (tags) show the tag as version in the app header
|
||||
APP_VERSION=""
|
||||
@@ -43,7 +55,7 @@ jobs:
|
||||
refs/tags/*) APP_VERSION="${REF_NAME}" ;;
|
||||
esac
|
||||
echo "app_version=${APP_VERSION}" >> "$GITHUB_OUTPUT"
|
||||
echo "Target Docker image: ${IMAGE_NAME}:${DOCKER_TAG} (Registry: ${REGISTRY_HOST}, Actor: ${ACTOR_NAME})"
|
||||
echo "Target Docker image: ${IMAGE_NAME} tags: ${TAGS} (Registry: ${REGISTRY_HOST}, Actor: ${ACTOR_NAME})"
|
||||
|
||||
- name: Login to Gitea Container Registry
|
||||
uses: docker/login-action@v3
|
||||
@@ -54,8 +66,10 @@ jobs:
|
||||
|
||||
- name: Build & Run All Checks in Container, then Push
|
||||
run: |
|
||||
FULL_IMAGE="${{ steps.prep.outputs.image }}:${{ steps.prep.outputs.tag }}"
|
||||
echo "🚀 Building container & executing Frontend/Backend checks inside image: ${FULL_IMAGE}"
|
||||
DOCKER_BUILDKIT=1 docker build --progress=plain --build-arg APP_VERSION="${{ steps.prep.outputs.app_version }}" -t "${FULL_IMAGE}" .
|
||||
echo "✅ All checks & tests passed inside container! Pushing ${FULL_IMAGE}..."
|
||||
docker push "${FULL_IMAGE}"
|
||||
IMAGE="${{ steps.prep.outputs.image }}"
|
||||
TAG_ARGS=""
|
||||
for t in ${{ steps.prep.outputs.tags }}; do TAG_ARGS="${TAG_ARGS} -t ${IMAGE}:${t}"; done
|
||||
echo "🚀 Building container & executing Frontend/Backend checks inside image: ${IMAGE} (tags: ${{ steps.prep.outputs.tags }})"
|
||||
DOCKER_BUILDKIT=1 docker build --progress=plain --build-arg APP_VERSION="${{ steps.prep.outputs.app_version }}" ${TAG_ARGS} .
|
||||
echo "✅ All checks & tests passed inside container! Pushing..."
|
||||
for t in ${{ steps.prep.outputs.tags }}; do docker push "${IMAGE}:${t}"; done
|
||||
@@ -91,6 +91,8 @@ Stage 2 golang:1.23 go vet, go test, go build → /app/mindsift (
|
||||
Stage 3 alpine:3.21 nur Binary, ca-certificates, tzdata
|
||||
```
|
||||
|
||||
**Image-Tags (CI):** Push auf `dev` → `:dev`; Push/Merge auf `main` → `:latest`; Git-Tag `v*` (z. B. `v1.2.0`) → `:v1.2.0` und `:stable`. Andere Branches bauen nicht.
|
||||
|
||||
Die angezeigte Version (Kopf der App) setzt der Build-Parameter `APP_VERSION`: Die CI übergibt bei Git-Tags den Tag-Namen (`v0.2`), sonst zeigt die App die Version aus `frontend/package.json` mit `-dev` (`v0.2-dev`). Umgesetzt in `frontend/vite.config.ts` und `frontend/src/version.ts`.
|
||||
|
||||
Die Tests laufen beim Image-Build (Frontend: `npm run test:run`, Backend: `go test -v ./...`); ein Fehler bricht den Build ab. Frontend-Tests liegen unter `frontend/src/**/__tests__/` (Vitest + jsdom + Testing Library, Setup in `frontend/src/test/setup.ts`).
|
||||
@@ -128,7 +128,7 @@ Minimal:
|
||||
```yaml
|
||||
services:
|
||||
mindsift:
|
||||
image: git.dsit.me/sandrodach/mindsift:v0.2 # feste Version; :dev = neuester Entwicklungsstand
|
||||
image: git.dsit.me/sandrodach/mindsift:stable # oder feste Version (:v0.2); :latest = main, :dev = Entwicklungsstand
|
||||
restart: unless-stopped
|
||||
ports: ["8080:8080"]
|
||||
volumes: ["./data:/data"]
|
||||
@@ -161,7 +161,7 @@ Rufe `http://localhost:8080` auf. Beim ersten Start führt ein Assistent durch d
|
||||
* **Reverse-Proxy:** Am besten WebSocket-Upgrade und ungepufferte SSE-Streams durchreichen. Blockiert ein Proxy beides, funktioniert MindSift trotzdem über Long-Polling bzw. regelmäßige Abfragen, nur etwas träger. Beispiele für Nginx, Traefik, Caddy und Cloudflare: [Doku/reverse-proxy.md](Doku/reverse-proxy.md).
|
||||
* **Datensicherung:** Alle Daten liegen in `data/mindsift.db` (+ `-wal`/`-shm`). Sichere sie mit `sqlite3 mindsift.db ".backup 'backup.db'"` oder bei gestopptem Container. Zusätzlich gibt es einen JSON-Export pro Benutzer.
|
||||
* **Updates:** Neues Image ziehen und Container neu starten (`docker compose pull && docker compose up -d`). Das Schema wird beim Start automatisch angepasst. Die laufende Version steht im Kopf der App unter dem Namen.
|
||||
* **Image-Tags:** Jeder Git-Tag erzeugt ein gleichnamiges Image (`:v0.2`), jeder Branch eines mit dem Branch-Namen (`:dev`).
|
||||
* **Image-Tags:** `:dev` = Stand des Branches `dev`, `:latest` = Stand von `main`, `:stable` = zuletzt veröffentlichte Version. Ein Git-Tag wie `v1.2.0` erzeugt `:v1.2.0` und verschiebt `:stable` darauf.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -816,13 +816,19 @@ export const OutlinerBlock: React.FC<OutlinerBlockProps> = ({
|
||||
{block.type === 'todo' && (
|
||||
<span className="inline-flex items-center align-middle ml-1.5 gap-1 shrink-0 pointer-events-auto z-10 relative select-none">
|
||||
{block.taskId && (
|
||||
<span
|
||||
className="badge-accent text-[9px] inline-flex items-center gap-0.5 px-1.5 py-0.2 rounded font-medium shrink-0"
|
||||
title="Mit erweiterter Aufgabe synchronisiert"
|
||||
<button
|
||||
type="button"
|
||||
onMouseDown={(e) => e.stopPropagation()}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onOpenTask?.(block.taskId as string);
|
||||
}}
|
||||
className="badge-accent text-[9px] inline-flex items-center gap-0.5 px-1.5 py-0.2 rounded font-medium shrink-0 cursor-pointer hover:opacity-80"
|
||||
title="Erweiterte Aufgabe öffnen"
|
||||
>
|
||||
<CheckSquare className="w-2.5 h-2.5" />
|
||||
<span>Erweitert</span>
|
||||
</span>
|
||||
</button>
|
||||
)}
|
||||
|
||||
{canEdit && (
|
||||
@@ -861,6 +867,7 @@ export const OutlinerBlock: React.FC<OutlinerBlockProps> = ({
|
||||
type: 'todo',
|
||||
};
|
||||
onUpdateBlockRef.current(updatedBlock, true);
|
||||
onOpenTask?.(thought.id);
|
||||
} catch (err: any) {
|
||||
alert(err.message || 'Fehler beim Erstellen der erweiterten Aufgabe');
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user