Skip to content
Open
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
109 changes: 109 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
name: Release

on:
schedule:
# 14:00 UTC every Friday == 19:30 IST (UTC+5:30, no DST).
- cron: "0 14 * * 5"
workflow_dispatch:
inputs:
version:
description: "Explicit version to release without the leading 'v' (e.g. 1.0.0). Leave blank to auto-increment the patch from the latest tag."
required: false
type: string

# Needed to create tags and GitHub Releases.
permissions:
contents: write

# Never run two releases at once.
concurrency:
group: release
cancel-in-progress: false

jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout (full history + tags)
uses: actions/checkout@v4
with:
fetch-depth: 0
Comment on lines +27 to +30

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Set persist-credentials: false on checkout.

actions/checkout persists the GITHUB_TOKEN in .git/config by default. This workflow never pushes via git (the release is created through action-gh-release using the token directly), so the persisted credential is unnecessary and leaves a credential exposed to any later step.

🔒️ Proposed hardening
       - name: Checkout (full history + tags)
         uses: actions/checkout@v4
         with:
           fetch-depth: 0
+          persist-credentials: false
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Checkout (full history + tags)
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Checkout (full history + tags)
uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
🧰 Tools
🪛 zizmor (1.26.1)

[warning] 27-30: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 27 - 30, The checkout step in the
release workflow is persisting the GITHUB_TOKEN in git config unnecessarily.
Update the existing actions/checkout@v4 configuration to disable credential
persistence by setting persist-credentials to false while keeping the
full-history/tag fetch settings unchanged.

Source: Linters/SAST tools


- name: Determine next version and changelog
id: meta
env:
OVERRIDE: ${{ inputs.version }}
run: |
set -euo pipefail

# Latest semver tag (highest version, not most recent by date).
PREV_TAG="$(git tag -l 'v*.*.*' --sort=-v:refname | head -n1)"

if [ -n "${OVERRIDE:-}" ]; then
NEXT_VERSION="${OVERRIDE#v}"
elif [ -z "$PREV_TAG" ]; then
# First ever release.
NEXT_VERSION="0.1.0"
else
BASE="${PREV_TAG#v}"
MAJOR="${BASE%%.*}"
REST="${BASE#*.}"
MINOR="${REST%%.*}"
PATCH="${REST##*.}"
NEXT_VERSION="${MAJOR}.${MINOR}.$((PATCH + 1))"
fi
NEXT_TAG="v${NEXT_VERSION}"

# Count commits since the last release. If nothing changed, skip
# (unless an explicit version override was supplied).
if [ -n "$PREV_TAG" ]; then
CHANGES="$(git rev-list "${PREV_TAG}..HEAD" --count)"
else
CHANGES="$(git rev-list HEAD --count)"
fi

if [ -n "$PREV_TAG" ] && [ "$CHANGES" -eq 0 ] && [ -z "${OVERRIDE:-}" ]; then
echo "No changes since ${PREV_TAG}; skipping release."
echo "release=false" >> "$GITHUB_OUTPUT"
exit 0
fi

# Don't clobber an existing tag/release.
if git rev-parse -q --verify "refs/tags/${NEXT_TAG}" >/dev/null; then
echo "Tag ${NEXT_TAG} already exists; skipping."
echo "release=false" >> "$GITHUB_OUTPUT"
exit 0
fi

# Changelog = the diff of commits since the previous release.
if [ -n "$PREV_TAG" ]; then
RANGE="${PREV_TAG}..HEAD"
HEADER="## Changes since ${PREV_TAG}"
else
RANGE="HEAD"
HEADER="## Changes"
fi

{
echo "$HEADER"
echo
git log --no-merges --pretty=format:'- %s (%h)' $RANGE
echo
} > changelog.md

echo "Releasing ${NEXT_TAG}"
cat changelog.md

echo "release=true" >> "$GITHUB_OUTPUT"
echo "tag=${NEXT_TAG}" >> "$GITHUB_OUTPUT"

- name: Create GitHub Release
if: steps.meta.outputs.release == 'true'
uses: softprops/action-gh-release@v2
with:
# Creates this tag at the checked-out commit if it doesn't exist.
# GitHub automatically attaches the full source (zip + tar.gz).
tag_name: ${{ steps.meta.outputs.tag }}
name: ${{ steps.meta.outputs.tag }}
body_path: changelog.md
make_latest: "true"
1,097 changes: 517 additions & 580 deletions bun.lock

Large diffs are not rendered by default.

90 changes: 45 additions & 45 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "draw",
"private": true,
"version": "0.0.0",
"version": "0.1.0",
"type": "module",
"scripts": {
"dev": "vite",
Expand All @@ -10,54 +10,54 @@
"preview": "vite preview"
},
"dependencies": {
"@excalidraw/excalidraw": "^0.18.0",
"@excalidraw/mermaid-to-excalidraw": "^1.1.2",
"@hookform/resolvers": "^3.9.1",
"@radix-ui/react-dropdown-menu": "^2.1.2",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.4",
"@sentry/react": "^8.42.0",
"@supabase/supabase-js": "^2.47.2",
"@tanstack/react-query": "^5.62.3",
"@tanstack/react-router": "^1.87.0",
"bun": "^1.1.42",
"@excalidraw/excalidraw": "^0.18.1",
"@excalidraw/mermaid-to-excalidraw": "^2.2.2",
"@hookform/resolvers": "^5.4.0",
"@radix-ui/react-dropdown-menu": "^2.1.19",
"@radix-ui/react-label": "^2.1.11",
"@radix-ui/react-slot": "^1.3.0",
"@radix-ui/react-tooltip": "^1.2.11",
"@sentry/react": "^10.63.0",
"@supabase/supabase-js": "^2.110.0",
"@tanstack/react-query": "^5.101.2",
"@tanstack/react-router": "^1.170.17",
"bun": "^1.3.14",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"dayjs": "^1.11.13",
"hono": "^4.6.14",
"lucide-react": "^0.511.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-hook-form": "^7.54.0",
"sonner": "^1.7.1",
"tailwind-merge": "^2.5.5",
"tailwindcss-animate": "^1.0.7",
"zod": "^3.23.8",
"zustand": "^4.5.5"
"dayjs": "^1.11.21",
"hono": "^4.12.27",
"lucide-react": "^1.23.0",
"react": "^19.2.7",
"react-dom": "^19.2.7",
"react-hook-form": "^7.81.0",
"sonner": "^2.0.7",
"tailwind-merge": "^3.6.0",
"zod": "^4.4.3",
"zustand": "^5.0.14"
},
"devDependencies": {
"@eslint/js": "^9.16.0",
"@tanstack/eslint-plugin-query": "^5.62.1",
"@tanstack/router-plugin": "^1.86.0",
"@types/bun": "^1.1.14",
"@types/node": "^22.10.1",
"@types/react": "^18.3.14",
"@types/react-dom": "^18.3.2",
"@vitejs/plugin-react-swc": "^3.7.2",
"autoprefixer": "^10.4.20",
"eslint": "^9.16.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-react-hooks": "^5.1.0",
"eslint-plugin-react-refresh": "^0.4.16",
"globals": "^15.13.0",
"@eslint/js": "^10.0.1",
"@tailwindcss/postcss": "^4.3.2",
"@tanstack/eslint-plugin-query": "^5.101.2",
"@tanstack/router-plugin": "^1.168.19",
"@types/bun": "^1.3.14",
"@types/node": "^26.1.0",
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react-swc": "^4.3.1",
"eslint": "^10.6.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-react-hooks": "^7.1.1",
"eslint-plugin-react-refresh": "^0.5.3",
"globals": "^17.7.0",
"install": "^0.13.0",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm nothing references the `install` package.
rg -nP "require\(['\"]install['\"]\)|from ['\"]install['\"]" .

Repository: macintushar/draw

Length of output: 154


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- package.json excerpt ---'
cat -n package.json | sed -n '40,65p'

echo
echo '--- plain-text references to "install" (filtered to likely relevant paths) ---'
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/.git/**' --glob '!package-lock.json' --glob '!pnpm-lock.yaml' --glob '!yarn.lock' '\binstall\b' .

echo
echo '--- package.json dependency entries ---'
python3 - <<'PY'
import json
from pathlib import Path
pkg = json.loads(Path('package.json').read_text())
for section in ('dependencies', 'devDependencies', 'optionalDependencies', 'peerDependencies'):
    deps = pkg.get(section, {})
    if 'install' in deps:
        print(section, deps['install'])
PY

Repository: macintushar/draw

Length of output: 2141


Remove the stray install dependency. install doesn’t appear to be used anywhere; remove it from package.json and the lockfile to avoid unnecessary supply-chain surface.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` at line 53, Remove the stray install dependency from
package.json and update the lockfile accordingly. The dependency is unused, so
delete the install entry from the dependencies section and regenerate or edit
the lockfile so it no longer references it, keeping the change consistent with
the package manifest.

"postcss": "^8.4.49",
"prettier": "3.3.3",
"prettier-plugin-tailwindcss": "^0.6.9",
"tailwindcss": "^3.4.16",
"typescript": "^5.7.2",
"typescript-eslint": "^8.17.0",
"vite": "^5.4.11"
"postcss": "^8.5.16",
"prettier": "3.9.4",
"prettier-plugin-tailwindcss": "^0.8.0",
"tailwindcss": "^4.3.2",
"tw-animate-css": "^1.4.0",
"typescript": "^6.0.3",
"typescript-eslint": "^8.62.1",
"vite": "^8.1.3"
}
}
3 changes: 1 addition & 2 deletions postcss.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
"@tailwindcss/postcss": {},
},
};
4 changes: 2 additions & 2 deletions src/components/ProfileDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { Button } from "@/components/ui/button";
import { useTheme } from "@/components/theme-provider";
import ProfileItem from "@/components/ProfileItem";

import { Github, LogOut, Moon, Sun, SunMoon, User } from "lucide-react";
import { GitBranch, LogOut, Moon, Sun, SunMoon, User } from "lucide-react";

import { timeMessage } from "@/lib/utils";

Expand Down Expand Up @@ -106,7 +106,7 @@ export default function ProfileDropdown() {
</DropdownMenuGroup>
<DropdownMenuSeparator />
<a href={GITHUB_REPO_URL} rel="noreferrer noopener" target="_blank">
<ProfileItem Icon={Github} text="GitHub" />
<ProfileItem Icon={GitBranch} text="GitHub" />
</a>
<DropdownMenuSeparator />
<ProfileItem
Expand Down
8 changes: 5 additions & 3 deletions src/index.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@import "tailwindcss";
@import "tw-animate-css";
@config "../tailwind.config.ts";

@custom-variant dark (&:is(.dark *));
Comment on lines +1 to +5

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Update stylelint to recognize Tailwind v4 at-rules.

Stylelint flags @config (Line 3) and @custom-variant (Line 5) as unknown at-rules via scss/at-rule-no-unknown. These are valid Tailwind v4 directives, so this will produce persistent CI/editor lint noise (and may fail lint gates) unless the stylelint config allowlists them.

🔧 Suggested stylelint config update
 rules: {
   "scss/at-rule-no-unknown": [
     true,
     {
-      ignoreAtRules: [/* existing entries */],
+      ignoreAtRules: [
+        "tailwind",
+        "apply",
+        "layer",
+        "config",
+        "custom-variant",
+        "theme",
+        "utility",
+        "source",
+        /* existing entries */
+      ],
     },
   ],
 },
🧰 Tools
🪛 Stylelint (17.14.0)

[error] 3-3: Unexpected unknown at-rule "@config" (scss/at-rule-no-unknown)

(scss/at-rule-no-unknown)


[error] 5-5: Unexpected unknown at-rule "@custom-variant" (scss/at-rule-no-unknown)

(scss/at-rule-no-unknown)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/index.css` around lines 1 - 5, Stylelint is flagging Tailwind v4
directives as unknown at-rules in the stylesheet; update the stylelint
configuration to allowlist the Tailwind-specific directives used in
src/index.css. Adjust the rule that powers scss/at-rule-no-unknown so it ignores
`@config` and `@custom-variant` (and any other Tailwind v4 at-rules already present
in the stylesheet), keeping the change in the stylelint config rather than the
CSS itself.

Source: Linters/SAST tools


@layer base {
@font-face {
Expand Down
Loading
Loading