Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions .github/scripts/README.md
Original file line number Diff line number Diff line change
@@ -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.
105 changes: 105 additions & 0 deletions .github/scripts/increment-version.js
Original file line number Diff line number Diff line change
@@ -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 };
64 changes: 64 additions & 0 deletions .github/workflows/auto-update-version.yml.disabled
Original file line number Diff line number Diff line change
@@ -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 }}"
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
106 changes: 106 additions & 0 deletions .github/workflows/version-and-build.yml
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion apps/web/projectData.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const data = {
version: "0.1.9",
version: "0.1.10-canery-1",
};

export default data;
40 changes: 1 addition & 39 deletions apps/web/src/app/dashboard/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,14 @@ import {
PanelTopIcon,
PlusCircleIcon,
UsersIcon,
Sun,
Moon,
SettingsIcon,
InfoIcon,
CircleArrowLeftIcon,
LibraryIcon,
} 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,
Expand All @@ -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 = [
{
Expand Down Expand Up @@ -211,30 +200,3 @@ export default function DashboardSidebar({
</Sidebar>
);
}

function ModeToggle() {
const { setTheme } = useTheme();

return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" size="icon">
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
<span className="sr-only">Toggle theme</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem onClick={() => setTheme("light")}>
Light
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme("dark")}>
Dark
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme("system")}>
System
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}
Loading