diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f459274 --- /dev/null +++ b/.gitignore @@ -0,0 +1,44 @@ +# ── Backend ────────────────────────────────── +/backend/api +/backend/seed +*.test +*.out +coverage.html +go.work +go.work.sum +vendor/ + +# ── Web ────────────────────────────────────── +/web/node_modules/ +/web/.svelte-kit/ +/web/build/ +/web/.output/ +/web/vite.config.js.timestamp-* +/web/vite.config.ts.timestamp-* + +# ── App ────────────────────────────────────── +/app/.dart_tool/ +/app/build/ +/app/.flutter-plugins +/app/.flutter-plugins-dependencies + +# ── Shared ─────────────────────────────────── +.env +.env.local +.env.*.local +!.env.example +!.env.test +.idea/ +.vscode/ +*.swp +*.swo +*~ +.DS_Store +Thumbs.db +/tmp/ +/dist/ +*.exe +*.exe~ +*.dll +*.so +*.dylib diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..b18efa5 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,150 @@ +stages: [lint, test, build, docker, deploy] + +variables: + REGISTRY: registry.itsh.dev + BACKEND_IMAGE: registry.itsh.dev/vikingowl/marktvogt.de/backend + WEB_IMAGE: registry.itsh.dev/vikingowl/marktvogt.de/web + +# ── Backend ───────────────────────────────────────────────────────────────── + +backend:lint: + stage: lint + image: golang:1.26-alpine + variables: + GOPRIVATE: marktvogt.de/* + before_script: + - apk add --no-cache git + - GOTOOLCHAIN=local go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.1.6 + script: + - cd backend && golangci-lint run ./... + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' + changes: [backend/**/*] + - if: '$CI_COMMIT_BRANCH == "main"' + changes: [backend/**/*] + +backend:test: + stage: test + image: golang:1.26-alpine + variables: + GOPRIVATE: marktvogt.de/* + before_script: + - apk add --no-cache git gcc musl-dev + script: + - cd backend && CGO_ENABLED=1 go test ./... -v -count=1 -race + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' + changes: [backend/**/*] + - if: '$CI_COMMIT_BRANCH == "main"' + changes: [backend/**/*] + +backend:build: + stage: build + image: golang:1.26-alpine + variables: + GOPRIVATE: marktvogt.de/* + before_script: + - apk add --no-cache git + script: + - cd backend && CGO_ENABLED=0 go build -ldflags="-s -w" -o /dev/null ./cmd/api + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' + changes: [backend/**/*] + - if: '$CI_COMMIT_BRANCH == "main"' + changes: [backend/**/*] + +backend:docker: + stage: docker + image: docker:27 + services: + - docker:27-dind + variables: + DOCKER_TLS_CERTDIR: "/certs" + before_script: + - docker login -u "$REGISTRY_USER" -p "$REGISTRY_PASSWORD" $REGISTRY + script: + - docker build -f backend/deploy/Dockerfile -t "$BACKEND_IMAGE:${CI_COMMIT_SHORT_SHA}" backend/ + - docker push "$BACKEND_IMAGE:${CI_COMMIT_SHORT_SHA}" + rules: + - if: '$CI_COMMIT_BRANCH == "main"' + changes: [backend/**/*] + +backend:deploy: + stage: deploy + image: alpine/helm:4.1 + before_script: + - mkdir -p ~/.kube + - echo "$KUBECONFIG_DATA" > ~/.kube/config + - chmod 600 ~/.kube/config + script: + - | + helm upgrade --install marktvogt-backend ./backend/deploy/helm/ \ + --namespace tenant-2 \ + --set image.tag="${CI_COMMIT_SHORT_SHA}" \ + --set smtp.host="$SMTP_HOST" \ + --set smtp.user="$SMTP_USER" \ + --set smtp.password="$SMTP_PASSWORD" \ + --set ai.apiKey="$AI_API_KEY" \ + --set ai.agentSimple="$AI_AGENT_SIMPLE" \ + --set turnstile.secretKey="$TURNSTILE_SECRET_KEY" \ + --rollback-on-failure --wait=watcher --timeout 5m + needs: [backend:docker] + rules: + - if: '$CI_COMMIT_BRANCH == "main"' + changes: [backend/**/*] + +# ── Web ────────────────────────────────────────────────────────────────────── + +web:lint: + stage: lint + image: node:25-alpine + variables: + PUBLIC_API_BASE_URL: https://api.marktvogt.de + before_script: + - npm install -g pnpm@10 + - cd web && pnpm install --frozen-lockfile + script: + - cd web && pnpm run format:check && pnpm run lint && pnpm run check + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' + changes: [web/**/*] + - if: '$CI_COMMIT_BRANCH == "main"' + changes: [web/**/*] + +web:docker: + stage: docker + image: docker:27 + services: + - docker:27-dind + variables: + DOCKER_TLS_CERTDIR: "/certs" + before_script: + - docker login -u "$REGISTRY_USER" -p "$REGISTRY_PASSWORD" $REGISTRY + script: + - | + docker build -f web/Dockerfile \ + --build-arg PUBLIC_API_BASE_URL=https://api.marktvogt.de \ + --build-arg PUBLIC_TURNSTILE_SITE_KEY=0x4AAAAAACjLCV-78Ql1oTPz \ + -t "$WEB_IMAGE:${CI_COMMIT_SHORT_SHA}" web/ + - docker push "$WEB_IMAGE:${CI_COMMIT_SHORT_SHA}" + rules: + - if: '$CI_COMMIT_BRANCH == "main"' + changes: [web/**/*] + +web:deploy: + stage: deploy + image: alpine/helm:4.1 + before_script: + - mkdir -p ~/.kube + - echo "$KUBECONFIG_DATA" > ~/.kube/config + - chmod 600 ~/.kube/config + script: + - | + helm upgrade --install marktvogt-web ./web/deploy/helm/ \ + --namespace tenant-2 \ + --set image.tag="${CI_COMMIT_SHORT_SHA}" \ + --rollback-on-failure --wait=watcher --timeout 5m + needs: [web:docker] + rules: + - if: '$CI_COMMIT_BRANCH == "main"' + changes: [web/**/*] diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..031ad51 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,65 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + exclude: ^(backend|web)/deploy/helm/templates/ + - id: check-json + exclude: ^web/tsconfig\.json$ + - id: check-merge-conflict + - id: check-added-large-files + - id: no-commit-to-branch + args: ['--branch', 'main'] + + - repo: https://github.com/golangci/golangci-lint + rev: v2.1.6 + hooks: + - id: golangci-lint + files: ^backend/ + args: ['--config', 'backend/.golangci.yml'] + + - repo: local + hooks: + - id: go-fmt + name: go fmt + entry: bash -c 'cd backend && gofmt -w .' + language: system + files: ^backend/.*\.go$ + pass_filenames: false + + - id: go-vet + name: go vet + entry: bash -c 'cd backend && go vet ./...' + language: system + files: ^backend/.*\.go$ + pass_filenames: false + + - id: go-mod-tidy + name: go mod tidy + entry: bash -c 'cd backend && go mod tidy' + language: system + files: ^backend/go\.(mod|sum)$ + pass_filenames: false + + - id: prettier + name: prettier + entry: bash -c 'cd web && pnpm run format:check' + language: system + files: ^web/ + pass_filenames: false + + - id: eslint + name: eslint + entry: bash -c 'cd web && pnpm run lint' + language: system + files: ^web/ + pass_filenames: false + + - id: svelte-check + name: svelte-check + entry: bash -c 'cd web && pnpm run check' + language: system + files: ^web/ + pass_filenames: false diff --git a/backend/.gitignore b/backend/.gitignore deleted file mode 100644 index 3566f2b..0000000 --- a/backend/.gitignore +++ /dev/null @@ -1,43 +0,0 @@ -# Binaries -*.exe -*.exe~ -*.dll -*.so -*.dylib -/backend -/api -/seed - -# Test binary -*.test - -# Coverage -*.out -coverage.html - -# Go workspace -go.work -go.work.sum - -# IDE -.idea/ -.vscode/ -*.swp -*.swo -*~ - -# OS -.DS_Store -Thumbs.db - -# Environment -.env -.env.local -.env.*.local - -# Vendor (we use modules) -vendor/ - -# Build output -/dist/ -/tmp/ diff --git a/backend/.pre-commit-config.yaml b/backend/.pre-commit-config.yaml deleted file mode 100644 index f337a56..0000000 --- a/backend/.pre-commit-config.yaml +++ /dev/null @@ -1,23 +0,0 @@ -repos: - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 - hooks: - - id: trailing-whitespace - - id: end-of-file-fixer - - id: check-yaml - exclude: ^deploy/helm/templates/ - - id: check-merge-conflict - - id: check-added-large-files - - - repo: https://github.com/golangci/golangci-lint - rev: v2.1.6 - hooks: - - id: golangci-lint - - - repo: https://github.com/tekwizely/pre-commit-golang - rev: v1.0.0-rc.1 - hooks: - - id: go-fmt-repo - - id: go-vet-repo-mod - - id: go-mod-tidy - - id: go-build-mod diff --git a/backend/.woodpecker.yml b/backend/.woodpecker.yml deleted file mode 100644 index 3b62025..0000000 --- a/backend/.woodpecker.yml +++ /dev/null @@ -1,78 +0,0 @@ -when: - - event: [push, pull_request] - -steps: - lint: - image: golang:1.26-alpine - commands: - - apk add --no-cache git - - GOTOOLCHAIN=local go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.1.6 - - golangci-lint run ./... - - test: - image: golang:1.26-alpine - commands: - - apk add --no-cache git gcc musl-dev - - CGO_ENABLED=1 go test ./... -v -count=1 -race - - build: - image: golang:1.26-alpine - commands: - - apk add --no-cache git - - CGO_ENABLED=0 go build -ldflags="-s -w" -o /dev/null ./cmd/api - - # Build and push immutable SHA-tagged image on main branch only - docker: - image: woodpeckerci/plugin-docker-buildx - settings: - repo: registry.itsh.dev/vikingowl/marktvogt.de/backend - tags: - - "${CI_COMMIT_SHA:0:8}" - dockerfile: deploy/Dockerfile - registry: registry.itsh.dev - username: - from_secret: registry_user - password: - from_secret: registry_password - when: - - event: push - branch: main - - # Deploy via Helm using the exact SHA tag just pushed - deploy: - image: alpine/helm:4.1 - environment: - KUBECONFIG_DATA: - from_secret: kubeconfig - SMTP_HOST: - from_secret: smtp_host - SMTP_USER: - from_secret: smtp_user - SMTP_PASSWORD: - from_secret: smtp_password - AI_API_KEY: - from_secret: ai_api_key - AI_AGENT_SIMPLE: - from_secret: ai_agent_simple - TURNSTILE_SECRET_KEY: - from_secret: turnstile_secret_key - commands: - - mkdir -p ~/.kube - - echo "$KUBECONFIG_DATA" > ~/.kube/config - - chmod 600 ~/.kube/config - - | - helm upgrade --install marktvogt-backend ./deploy/helm/ \ - --namespace tenant-2 \ - --set image.tag="${CI_COMMIT_SHA:0:8}" \ - --set smtp.host="$SMTP_HOST" \ - --set smtp.user="$SMTP_USER" \ - --set smtp.password="$SMTP_PASSWORD" \ - --set ai.apiKey="$AI_API_KEY" \ - --set ai.agentSimple="$AI_AGENT_SIMPLE" \ - --set turnstile.secretKey="$TURNSTILE_SECRET_KEY" \ - --rollback-on-failure \ - --wait=watcher \ - --timeout 5m - when: - - event: push - branch: main diff --git a/backend/go.mod b/backend/go.mod index a6e8c05..4588d3e 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -3,6 +3,7 @@ module marktvogt.de/backend go 1.26 require ( + github.com/VikingOwl91/mistral-go-sdk v1.3.0 github.com/gin-gonic/gin v1.11.0 github.com/go-playground/validator/v10 v10.30.1 github.com/golang-jwt/jwt/v5 v5.3.1 @@ -13,7 +14,6 @@ require ( golang.org/x/crypto v0.48.0 golang.org/x/oauth2 v0.35.0 golang.org/x/time v0.14.0 - somegit.dev/vikingowl/mistral-go-sdk v0.1.0 ) require ( diff --git a/backend/go.sum b/backend/go.sum index a38e4bb..1a8b57d 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -1,3 +1,5 @@ +github.com/VikingOwl91/mistral-go-sdk v1.3.0 h1:OkTsodDE5lmdf7p2cwScqD2vIk8sScQ2IGk65dUjuz0= +github.com/VikingOwl91/mistral-go-sdk v1.3.0/go.mod h1:f4emNtHUx2zSqY3V0LBz6lNI1jE6q/zh+SEU+/hJ0i4= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ= @@ -113,5 +115,3 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -somegit.dev/vikingowl/mistral-go-sdk v0.1.0 h1:VrTa6iTo3D4TK/URUgXLWNqdvT5/28R9tbXM/gQiGCM= -somegit.dev/vikingowl/mistral-go-sdk v0.1.0/go.mod h1:pN7nQdOIYYEMRdwye5cSfymtwhZJHd+caK6J69Z4XMY= diff --git a/backend/internal/pkg/ai/client.go b/backend/internal/pkg/ai/client.go index 69407bf..f78da70 100644 --- a/backend/internal/pkg/ai/client.go +++ b/backend/internal/pkg/ai/client.go @@ -5,9 +5,9 @@ import ( "fmt" "time" - "somegit.dev/vikingowl/mistral-go-sdk" - "somegit.dev/vikingowl/mistral-go-sdk/chat" - "somegit.dev/vikingowl/mistral-go-sdk/conversation" + "github.com/VikingOwl91/mistral-go-sdk" + "github.com/VikingOwl91/mistral-go-sdk/chat" + "github.com/VikingOwl91/mistral-go-sdk/conversation" ) type Client struct { diff --git a/web/.gitignore b/web/.gitignore deleted file mode 100644 index 3b462cb..0000000 --- a/web/.gitignore +++ /dev/null @@ -1,23 +0,0 @@ -node_modules - -# Output -.output -.vercel -.netlify -.wrangler -/.svelte-kit -/build - -# OS -.DS_Store -Thumbs.db - -# Env -.env -.env.* -!.env.example -!.env.test - -# Vite -vite.config.js.timestamp-* -vite.config.ts.timestamp-* diff --git a/web/.pre-commit-config.yaml b/web/.pre-commit-config.yaml deleted file mode 100644 index 6042a3a..0000000 --- a/web/.pre-commit-config.yaml +++ /dev/null @@ -1,36 +0,0 @@ -repos: - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 - hooks: - - id: trailing-whitespace - - id: end-of-file-fixer - - id: check-yaml - exclude: ^deploy/helm/templates/ - - id: check-json - exclude: ^tsconfig\.json$ - - id: check-merge-conflict - - id: no-commit-to-branch - args: ['--branch', 'main'] - - - repo: local - hooks: - - id: prettier - name: prettier - entry: pnpm run format:check - language: system - pass_filenames: false - stages: [pre-commit] - - - id: eslint - name: eslint - entry: pnpm run lint - language: system - pass_filenames: false - stages: [pre-commit] - - - id: svelte-check - name: svelte-check - entry: pnpm run check - language: system - pass_filenames: false - stages: [pre-commit] diff --git a/web/.woodpecker.yml b/web/.woodpecker.yml deleted file mode 100644 index 94e95d2..0000000 --- a/web/.woodpecker.yml +++ /dev/null @@ -1,57 +0,0 @@ -when: - - event: [push, pull_request] - -steps: - lint: - image: node:25-alpine - environment: - PUBLIC_API_BASE_URL: https://api.marktvogt.de - commands: - - npm install -g pnpm@10 - - pnpm install --frozen-lockfile - - pnpm run format:check - - pnpm run lint - - pnpm run check - when: - - event: [push, pull_request] - - # Build and push immutable SHA-tagged image on main branch only - docker: - image: woodpeckerci/plugin-docker-buildx - settings: - repo: registry.itsh.dev/vikingowl/marktvogt.de/web - tags: - - '${CI_COMMIT_SHA:0:8}' - dockerfile: Dockerfile - registry: registry.itsh.dev - username: - from_secret: registry_user - password: - from_secret: registry_password - build_args: - - PUBLIC_API_BASE_URL=https://api.marktvogt.de - - PUBLIC_TURNSTILE_SITE_KEY=0x4AAAAAACjLCV-78Ql1oTPz - when: - - event: push - branch: main - - # Deploy via Helm using the exact SHA tag just pushed - deploy: - image: alpine/helm:4.1 - environment: - KUBECONFIG_DATA: - from_secret: kubeconfig - commands: - - mkdir -p ~/.kube - - echo "$KUBECONFIG_DATA" > ~/.kube/config - - chmod 600 ~/.kube/config - - | - helm upgrade --install marktvogt-web ./deploy/helm/ \ - --namespace tenant-2 \ - --set image.tag="${CI_COMMIT_SHA:0:8}" \ - --rollback-on-failure \ - --wait=watcher \ - --timeout 5m - when: - - event: push - branch: main