diff --git a/.github/scripts/README.md b/.github/scripts/README.md
new file mode 100644
index 0000000..1676062
--- /dev/null
+++ b/.github/scripts/README.md
@@ -0,0 +1,39 @@
+# CI Scripts
+
+This directory contains scripts used by GitHub Actions workflows to automate various tasks.
+
+## increment-version.js
+
+Automatically increments the version number in `apps/web/projectData.ts`.
+
+### Usage
+
+```bash
+node .github/scripts/increment-version.js
+```
+
+### Version Increment Logic
+
+The script handles different version formats intelligently:
+
+1. **Suffixed versions** (e.g., `"0.1.10-canary-1"` → `"0.1.10-canary-2"`)
+ - Increments the number after the final dash
+
+2. **Semantic versions** (e.g., `"0.1.10"` → `"0.1.11"`)
+ - Increments the patch version (third number)
+
+3. **Fallback pattern** - Increments the last number found in the version string
+
+### Outputs
+
+When run in GitHub Actions, the script sets these outputs:
+- `current`: The previous version number
+- `new`: The new incremented version number
+
+### Integration
+
+This script is used by the "Auto Update Version and Build" workflow (`version-and-build.yml`) to automatically increment the version on every push to the main branch, then build and tag a Docker image with the new version.
+
+### Prevention of Infinite Loops
+
+The workflow is designed to skip execution when the commit message contains "🤖 Auto-increment version" to prevent infinite loops of version updates.
\ No newline at end of file
diff --git a/.github/scripts/increment-version.js b/.github/scripts/increment-version.js
new file mode 100644
index 0000000..2c8d28b
--- /dev/null
+++ b/.github/scripts/increment-version.js
@@ -0,0 +1,105 @@
+#!/usr/bin/env node
+
+import fs from "fs";
+import path from "path";
+import { fileURLToPath, pathToFileURL } from "url";
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+const PROJECT_DATA_PATH = path.join(__dirname, "../../apps/web/projectData.ts");
+
+function incrementVersion(version) {
+ // Handle different version formats:
+ // "0.1.10-canery-1" -> "0.1.10-canery-2"
+ // "0.1.10" -> "0.1.11"
+ // "1.2.3-alpha-5" -> "1.2.3-alpha-6"
+
+ // Pattern 1: ends with -number (e.g., "0.1.10-canery-1")
+ const dashNumberPattern = /^(.+-)(\d+)$/;
+ const dashMatch = version.match(dashNumberPattern);
+
+ if (dashMatch) {
+ const prefix = dashMatch[1];
+ const number = parseInt(dashMatch[2], 10);
+ return `${prefix}${number + 1}`;
+ }
+
+ // Pattern 2: semantic version (e.g., "0.1.10" or "1.2.3")
+ const semverPattern = /^(\d+)\.(\d+)\.(\d+)(.*)$/;
+ const semverMatch = version.match(semverPattern);
+
+ if (semverMatch) {
+ const major = parseInt(semverMatch[1], 10);
+ const minor = parseInt(semverMatch[2], 10);
+ const patch = parseInt(semverMatch[3], 10);
+ const suffix = semverMatch[4] || "";
+ return `${major}.${minor}.${patch + 1}${suffix}`;
+ }
+
+ // Fallback: find the last number in the string and increment it
+ const lastNumberPattern = /^(.*?)(\d+)([^\d]*)$/;
+ const lastNumberMatch = version.match(lastNumberPattern);
+
+ if (lastNumberMatch) {
+ const prefix = lastNumberMatch[1];
+ const number = parseInt(lastNumberMatch[2], 10);
+ const suffix = lastNumberMatch[3];
+ return `${prefix}${number + 1}${suffix}`;
+ }
+
+ // If no number found, append .1
+ return `${version}.1`;
+}
+
+function updateProjectData() {
+ try {
+ // Read the current file
+ const content = fs.readFileSync(PROJECT_DATA_PATH, "utf8");
+
+ // Extract current version using regex
+ const versionPattern = /version:\s*["']([^"']+)["']/;
+ const match = content.match(versionPattern);
+
+ if (!match) {
+ throw new Error("Could not find version property in projectData.ts");
+ }
+
+ const currentVersion = match[1];
+ const newVersion = incrementVersion(currentVersion);
+
+ // Replace the version in the content
+ const newContent = content.replace(
+ versionPattern,
+ `version: "${newVersion}"`,
+ );
+
+ // Write back to file
+ fs.writeFileSync(PROJECT_DATA_PATH, newContent, "utf8");
+
+ console.log(`Version updated from ${currentVersion} to ${newVersion}`);
+
+ // Output for GitHub Actions (using modern format)
+ if (process.env.GITHUB_OUTPUT) {
+ fs.appendFileSync(
+ process.env.GITHUB_OUTPUT,
+ `current=${currentVersion}\n`,
+ );
+ fs.appendFileSync(process.env.GITHUB_OUTPUT, `new=${newVersion}\n`);
+ } else {
+ // Fallback for local testing
+ console.log(`current=${currentVersion}`);
+ console.log(`new=${newVersion}`);
+ }
+ } catch (error) {
+ console.error("Error updating version:", error.message);
+ process.exit(1);
+ }
+}
+
+// Run if this script is executed directly
+if (import.meta.url === pathToFileURL(process.argv[1]).href) {
+ updateProjectData();
+}
+
+export { incrementVersion, updateProjectData };
diff --git a/.github/workflows/auto-update-version.yml.disabled b/.github/workflows/auto-update-version.yml.disabled
new file mode 100644
index 0000000..0dadbc8
--- /dev/null
+++ b/.github/workflows/auto-update-version.yml.disabled
@@ -0,0 +1,64 @@
+name: Auto Update Version
+
+on:
+ push:
+ branches:
+ - master
+ - main
+ workflow_dispatch:
+
+jobs:
+ update-version:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ # Skip if the commit message contains the auto-increment marker to prevent infinite loops
+ if: "!contains(github.event.head_commit.message, '🤖 Auto-increment version')"
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+ fetch-depth: 0
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: "20"
+
+ - name: Update version using Node.js script
+ id: version_update
+ run: |
+ # Make script executable
+ chmod +x .github/scripts/increment-version.js
+
+ # Run the version increment script
+ node .github/scripts/increment-version.js
+
+ # Display updated file
+ echo "Updated projectData.ts:"
+ cat apps/web/projectData.ts
+
+ - name: Check for changes
+ id: git_status
+ run: |
+ if [ -n "$(git status --porcelain)" ]; then
+ echo "changes=true" >> $GITHUB_OUTPUT
+ else
+ echo "changes=false" >> $GITHUB_OUTPUT
+ fi
+
+ - name: Commit and push changes
+ if: steps.git_status.outputs.changes == 'true'
+ run: |
+ git config --local user.email "action@github.com"
+ git config --local user.name "GitHub Action"
+ git add apps/web/projectData.ts
+ git commit -m "🤖 Auto-increment version to ${{ steps.version_update.outputs.new }} [skip ci]"
+ git push
+
+ - name: Output version info
+ run: |
+ echo "Previous version: ${{ steps.version_update.outputs.current }}"
+ echo "New version: ${{ steps.version_update.outputs.new }}"
diff --git a/.github/workflows/build_docker_image.yml b/.github/workflows/build_docker_image.yml.disabled
similarity index 90%
rename from .github/workflows/build_docker_image.yml
rename to .github/workflows/build_docker_image.yml.disabled
index 086faa5..51c00a6 100644
--- a/.github/workflows/build_docker_image.yml
+++ b/.github/workflows/build_docker_image.yml.disabled
@@ -17,6 +17,8 @@ jobs:
permissions:
contents: read
packages: write
+ # Only run if not triggered by the auto-increment commit
+ if: "!contains(github.event.head_commit.message, '🤖 Auto-increment version')"
steps:
- name: Checkout repository
diff --git a/.github/workflows/version-and-build.yml b/.github/workflows/version-and-build.yml
new file mode 100644
index 0000000..e09064e
--- /dev/null
+++ b/.github/workflows/version-and-build.yml
@@ -0,0 +1,106 @@
+name: Auto Update Version and Build
+
+on:
+ push:
+ branches:
+ - master
+ - main
+ workflow_dispatch:
+
+env:
+ REGISTRY: ghcr.io
+ IMAGE_NAME: ${{ github.repository }}
+
+jobs:
+ update-version-and-build:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ packages: write
+ # Skip if the commit message contains the auto-increment marker to prevent infinite loops
+ if: "!contains(github.event.head_commit.message, '🤖 Auto-increment version')"
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+ fetch-depth: 0
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: "20"
+
+ - name: Update version using Node.js script
+ id: version_update
+ run: |
+ # Make script executable
+ chmod +x .github/scripts/increment-version.js
+
+ # Run the version increment script
+ node .github/scripts/increment-version.js
+
+ # Display updated file
+ echo "Updated projectData.ts:"
+ cat apps/web/projectData.ts
+
+ - name: Check for changes
+ id: git_status
+ run: |
+ if [ -n "$(git status --porcelain)" ]; then
+ echo "changes=true" >> $GITHUB_OUTPUT
+ else
+ echo "changes=false" >> $GITHUB_OUTPUT
+ fi
+
+ - name: Commit version changes
+ if: steps.git_status.outputs.changes == 'true'
+ run: |
+ git config --local user.email "action@github.com"
+ git config --local user.name "GitHub Action"
+ git add apps/web/projectData.ts
+ git commit -m "🤖 Auto-increment version to ${{ steps.version_update.outputs.new }}"
+ git push
+
+ - name: Log in to the Container registry
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Extract metadata (tags, labels) for Docker
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
+ tags: |
+ type=raw,value=latest
+ type=raw,value=${{ steps.version_update.outputs.new }}
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=sha,prefix=
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Build and push Docker image
+ uses: docker/build-push-action@v5
+ with:
+ context: .
+ push: true
+ tags: ${{ steps.meta.outputs.tags }}
+ labels: ${{ steps.meta.outputs.labels }}
+ cache-from: type=gha
+ cache-to: type=gha,mode=max
+
+ - name: Output summary
+ run: |
+ echo "## Version Update Summary" >> $GITHUB_STEP_SUMMARY
+ echo "- Previous version: ${{ steps.version_update.outputs.current }}" >> $GITHUB_STEP_SUMMARY
+ echo "- New version: ${{ steps.version_update.outputs.new }}" >> $GITHUB_STEP_SUMMARY
+ echo "- Docker image built with tags:" >> $GITHUB_STEP_SUMMARY
+ echo " - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" >> $GITHUB_STEP_SUMMARY
+ echo " - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version_update.outputs.new }}" >> $GITHUB_STEP_SUMMARY
diff --git a/apps/web/projectData.ts b/apps/web/projectData.ts
index cd207cd..b015ed5 100644
--- a/apps/web/projectData.ts
+++ b/apps/web/projectData.ts
@@ -1,5 +1,5 @@
const data = {
- version: "0.1.9",
+ version: "0.1.10-canery-1",
};
export default data;
diff --git a/apps/web/src/app/dashboard/sidebar.tsx b/apps/web/src/app/dashboard/sidebar.tsx
index f13de2f..71110d0 100644
--- a/apps/web/src/app/dashboard/sidebar.tsx
+++ b/apps/web/src/app/dashboard/sidebar.tsx
@@ -5,8 +5,6 @@ import {
PanelTopIcon,
PlusCircleIcon,
UsersIcon,
- Sun,
- Moon,
SettingsIcon,
InfoIcon,
CircleArrowLeftIcon,
@@ -14,14 +12,7 @@ import {
} from "lucide-react";
import { Button } from "@/components/ui/button";
import Image from "next/image";
-import {
- DropdownMenu,
- DropdownMenuContent,
- DropdownMenuItem,
- DropdownMenuLabel,
- DropdownMenuSeparator,
- DropdownMenuTrigger,
-} from "@/components/ui/dropdown-menu";
+import { ModeToggle } from "@/components/mode-toggle";
import Link from "next/link";
import {
Sidebar,
@@ -39,8 +30,6 @@ import {
import { authClient } from "@/lib/auth-client";
import { useRouter } from "next/navigation";
import type { Route } from "next";
-import { useTheme } from "next-themes";
-import { useEffect } from "react";
const items = [
{
@@ -211,30 +200,3 @@ export default function DashboardSidebar({
);
}
-
-function ModeToggle() {
- const { setTheme } = useTheme();
-
- return (
-