diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml deleted file mode 100644 index 904ccb6..0000000 --- a/.github/workflows/changelog.yml +++ /dev/null @@ -1,101 +0,0 @@ -name: "Changelog" - -on: - push: - branches: - - main - paths: - - 'apps/**' - - 'packages/**' - pull_request: - paths: - - 'apps/**' - - 'packages/**' - -permissions: - contents: write - packages: write - pull-requests: write - -jobs: - changelog: - name: Changelog - if: github.event_name != 'pull_request' - runs-on: ubuntu-24.04 - - outputs: - skipped: ${{ steps.changelog.outputs.skipped }} - tag: ${{ steps.changelog.outputs.tag }} - clean_changelog: ${{ steps.changelog.outputs.clean_changelog }} - version: ${{ steps.changelog.outputs.version }} - - env: - PR_BRANCH: release-ci-${{ github.run_id }} - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Create Branch - run: | - git checkout -b ${{ env.PR_BRANCH }} || git checkout ${{ env.PR_BRANCH }} - - - name: Create Changelog - uses: TriPSs/conventional-changelog-action@v6 - id: changelog - with: - github-token: ${{ github.token }} - git-user-name: "github-actions[bot]" - git-user-email: "github-actions[bot]@users.noreply.github.com" - git-branch: ${{ env.PR_BRANCH }} - skip-git-pull: true - output-file: CHANGELOG.md - create-summary: true - - - name: Create Changelog PR - if: steps.changelog.outputs.skipped == 'false' - run: | - gh pr create --base main --head ${{ env.PR_BRANCH }} --title 'chore(release): ${{ steps.changelog.outputs.tag }} [skip-ci]' --body "${{ steps.changelog.outputs.clean_changelog }}" - env: - GH_TOKEN: ${{ github.token }} - - - name: Approve Changelog PR - if: steps.changelog.outputs.skipped == 'false' - run: | - gh pr review --approve ${{ env.PR_BRANCH }} - env: - GH_TOKEN: ${{ secrets.GH_TOKEN_ANDREJ }} - - - name: Merge Changelog PR - if: steps.changelog.outputs.skipped == 'false' - run: | - gh pr merge --squash --auto --delete-branch ${{ env.PR_BRANCH }} - env: - GH_TOKEN: ${{ secrets.GH_TOKEN_ANDREJ }} - - release: - name: Release - needs: changelog - if: github.event_name != 'pull_request' && needs.changelog.outputs.skipped == 'false' - runs-on: ubuntu-24.04 - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Create Release - uses: softprops/action-gh-release@v2 - with: - token: ${{ secrets.GH_TOKEN_ANDREJ }} - tag_name: ${{ needs.changelog.outputs.tag }} - prerelease: false - draft: false - files: bin/* - generate_release_notes: true - name: ${{ needs.changelog.outputs.tag }} - body: | -
- 🤖 Autogenerated Conventional Changelog - ${{ needs.changelog.outputs.clean_changelog }} -
\ No newline at end of file diff --git a/apps/api/Dockerfile b/apps/api/Dockerfile index 36cd439..de088a1 100644 --- a/apps/api/Dockerfile +++ b/apps/api/Dockerfile @@ -1,4 +1,4 @@ -FROM --platform=$BUILDPLATFORM node:lts-slim AS base +FROM --platform=$BUILDPLATFORM node:22-slim AS base WORKDIR /app COPY package.json . diff --git a/apps/web/.env.production b/apps/web/.env.production new file mode 100644 index 0000000..4bf50f4 --- /dev/null +++ b/apps/web/.env.production @@ -0,0 +1 @@ +VITE_API_URL=KANEO_API_URL \ No newline at end of file diff --git a/apps/web/Dockerfile b/apps/web/Dockerfile index 4f39503..6df1b0b 100644 --- a/apps/web/Dockerfile +++ b/apps/web/Dockerfile @@ -1,4 +1,4 @@ -FROM node:20-alpine AS builder +FROM node:22-alpine AS builder RUN npm install -g bun @@ -26,6 +26,9 @@ COPY --from=builder /app/apps/web/dist /usr/share/nginx/html COPY apps/web/nginx.conf /etc/nginx/conf.d/default.conf +COPY apps/web/env.sh /docker-entrypoint.d/env.sh +RUN chmod +x /docker-entrypoint.d/env.sh + EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/apps/web/env.sh b/apps/web/env.sh new file mode 100644 index 0000000..4ebbd3c --- /dev/null +++ b/apps/web/env.sh @@ -0,0 +1,9 @@ +#!/bin/sh +for i in $(env | grep KANEO_) +do + key=$(echo $i | cut -d '=' -f 1) + value=$(echo $i | cut -d '=' -f 2-) + echo $key=$value + + find /usr/share/nginx/html -type f \( -name '*.js' -o -name '*.css' \) -exec sed -i "s|${key}|${value}|g" '{}' + +done \ No newline at end of file diff --git a/apps/web/index.html b/apps/web/index.html index 7bd8c80..413099d 100644 --- a/apps/web/index.html +++ b/apps/web/index.html @@ -5,6 +5,15 @@ + Kaneo diff --git a/apps/web/src/routes/__root.tsx b/apps/web/src/routes/__root.tsx index 8ab9152..a34581c 100644 --- a/apps/web/src/routes/__root.tsx +++ b/apps/web/src/routes/__root.tsx @@ -1,20 +1,40 @@ +import TanStackRouterDevtools from "@/tanstack/router"; import type { LoggedInUser } from "@/types/user"; import type { QueryClient } from "@tanstack/react-query"; import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; -import { Outlet, createRootRouteWithContext } from "@tanstack/react-router"; -import { TanStackRouterDevtools } from "@tanstack/router-devtools"; +import { + Outlet, + createRootRouteWithContext, + redirect, +} from "@tanstack/react-router"; export const Route = createRootRouteWithContext<{ queryClient: QueryClient; user: LoggedInUser | null | undefined; }>()({ component: RootComponent, + async beforeLoad({ context: { user }, location }) { + const isRouteUnprotected = location.pathname.includes("auth"); + const isOnDashboard = location.pathname.includes("dashboard"); + + if (user === null && !isRouteUnprotected) { + throw redirect({ + to: "/auth/sign-in", + }); + } + + if (user && !isOnDashboard) { + throw redirect({ + to: "/dashboard", + }); + } + }, }); function RootComponent() { return ( <> -
+
diff --git a/apps/web/src/tanstack/router.tsx b/apps/web/src/tanstack/router.tsx new file mode 100644 index 0000000..05df440 --- /dev/null +++ b/apps/web/src/tanstack/router.tsx @@ -0,0 +1,12 @@ +import React from "react"; + +const TanStackRouterDevtools = + process.env.NODE_ENV === "production" + ? () => null + : React.lazy(() => + import("@tanstack/router-devtools").then((res) => ({ + default: res.TanStackRouterDevtools, + })), + ); + +export default TanStackRouterDevtools; diff --git a/compose.yml b/compose.yml index ed91b44..dfea5d4 100644 --- a/compose.yml +++ b/compose.yml @@ -1,20 +1,49 @@ -version: '3.8' - services: - api: - image: ghcr.io/kaneo-app/api:latest - environment: - - JWT_ACCESS=jwt_secret_goes_here + traefik: + image: "traefik:v3.3" + container_name: "traefik" + command: + - "--providers.docker=true" + - "--entryPoints.web.address=:80" + - "--entryPoints.websecure.address=:443" ports: - - "1337:1337" + - "80:80" + - "443:443" + + networks: + - traefik-net volumes: - - .:/app + - "/var/run/docker.sock:/var/run/docker.sock:ro" + + backend: + image: ghcr.io/kaneo-app/api:latest + labels: + - "traefik.enable=true" + - "traefik.http.routers.backend.rule=Host(`demo-api.kaneo.app`)" + - "traefik.http.routers.backend.entrypoints=web" + environment: + JWT_ACCESS: "change_me" + networks: + - traefik-net restart: unless-stopped - web: - image: ghcr.io/kaneo-app/web:latest - ports: - - "80:80" + frontend: + build: + context: . + dockerfile: ./apps/web/Dockerfile + container_name: "kaneo-web" + environment: + KANEO_API_URL: "change_me" + labels: + - "traefik.enable=true" + - "traefik.http.routers.frontend.rule=Host(`demo.kaneo.app`)" + - "traefik.http.routers.frontend.entrypoints=web" depends_on: - - api - restart: unless-stopped \ No newline at end of file + - backend + restart: unless-stopped + networks: + - traefik-net + +networks: + traefik-net: + driver: bridge \ No newline at end of file