From 764e88a68b3b9663e8bc8ca42bbedb14c0db1b2b Mon Sep 17 00:00:00 2001 From: Nishanth Date: Wed, 15 Jul 2026 22:18:43 +0530 Subject: [PATCH 1/2] desktop(ui): show app version in the sidebar footer Adds AppVersionLabel (reads getVersion via the updater lib, desktop-only) under the user menu, so the running version is visible outside Settings. Co-Authored-By: Claude Opus 4.8 --- .../components/desktop/app-version-label.tsx | 33 +++++++++++++++++++ .../src/components/sidebar/app-sidebar.tsx | 2 ++ 2 files changed, 35 insertions(+) create mode 100644 apps/desktop-ui/src/components/desktop/app-version-label.tsx diff --git a/apps/desktop-ui/src/components/desktop/app-version-label.tsx b/apps/desktop-ui/src/components/desktop/app-version-label.tsx new file mode 100644 index 00000000..12174ffa --- /dev/null +++ b/apps/desktop-ui/src/components/desktop/app-version-label.tsx @@ -0,0 +1,33 @@ +"use client"; + +import { useEffect, useState } from "react"; + +import { isDesktop } from "@/lib/desktop/is-desktop"; + +/** + * Subtle running-app-version line for the sidebar footer. Reads the version + * baked into the bundle (tauri.conf.json) via the updater lib. Desktop-only — + * renders nothing on web. + */ +export function AppVersionLabel() { + const [version, setVersion] = useState(""); + + useEffect(() => { + if (!isDesktop()) return; + void import("@/lib/desktop/updater").then(async (m) => { + try { + setVersion(await m.currentAppVersion()); + } catch { + // version API unavailable — just don't show it + } + }); + }, []); + + if (!isDesktop() || !version) return null; + + return ( +

+ MyDevTools v{version} +

+ ); +} diff --git a/apps/desktop-ui/src/components/sidebar/app-sidebar.tsx b/apps/desktop-ui/src/components/sidebar/app-sidebar.tsx index b1fc12fa..6d90a059 100644 --- a/apps/desktop-ui/src/components/sidebar/app-sidebar.tsx +++ b/apps/desktop-ui/src/components/sidebar/app-sidebar.tsx @@ -15,6 +15,7 @@ import { import { NavGroup } from './nav-group' import { NavUser } from './nav-user' import { FeedbackDialog } from '@/components/feedback-dialog' +import { AppVersionLabel } from '@/components/desktop/app-version-label' import { Logo } from '../logo' import { SidebarMenu, SidebarMenuButton, SidebarMenuItem } from '@/components/ui/sidebar' import { LayoutDashboard, Sparkles } from 'lucide-react' @@ -191,6 +192,7 @@ export function AppSidebar({ ...props }: React.ComponentProps) { + From e1dff87ba9cb46e81bfd72c6d62c8d3cd71a58b6 Mon Sep 17 00:00:00 2001 From: Nishanth Date: Wed, 15 Jul 2026 22:18:43 +0530 Subject: [PATCH 2/2] ci(release): mirror artifacts to public releases repo for auto-update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Source repo is private, so its release assets 404 for the public — the updater endpoint and website button can't reach them. Add a CI step that mirrors the DMG + .app.tar.gz + .sig + latest.json to a public releases repo (URLs in latest.json rewritten; signature stays valid), and point the updater endpoint + download button at that public repo. Requires: public repo mydevtools-tech/mydevtools-releases and a RELEASES_TOKEN secret (contents:write on both repos). Co-Authored-By: Claude Opus 4.8 --- .github/workflows/release.yml | 40 +++++++++++++++++++ apps/desktop/src-tauri/tauri.conf.json | 2 +- .../components/download-desktop-button.tsx | 4 +- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8575a229..75919777 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -89,3 +89,43 @@ jobs: args: ${{ matrix.args }} updaterJsonPath: latest.json updaterJsonKeepUniversal: true + + # The source repo is private, so its release assets 404 for the public. + # Mirror the built artifacts to a PUBLIC releases repo that the updater + # endpoint and the website download button point at. + - name: Mirror release to public repo + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # read the private release + RELEASES_TOKEN: ${{ secrets.RELEASES_TOKEN }} # write to the public repo + PUBLIC_REPO: mydevtools-tech/mydevtools-releases + run: | + set -euo pipefail + VERSION="$(node -p "require('./apps/desktop/src-tauri/tauri.conf.json').version")" + TAG="v$VERSION" + BUNDLE="apps/desktop/src-tauri/target/universal-apple-darwin/release/bundle" + DMG="$(ls "$BUNDLE"/dmg/*.dmg)" + TARGZ="$(ls "$BUNDLE"/macos/*.app.tar.gz)" + SIG="$(ls "$BUNDLE"/macos/*.app.tar.gz.sig)" + + # Pull tauri's generated latest.json from the private release. + GH_TOKEN="$GITHUB_TOKEN" gh release download "$TAG" \ + --repo "$GITHUB_REPOSITORY" --pattern latest.json --dir . --clobber + + # Repoint its asset URLs at the public repo. The minisign signature + # signs the file bytes, not the URL, so it stays valid. + node -e ' + const fs = require("fs"); + const src = process.env.GITHUB_REPOSITORY, dst = process.env.PUBLIC_REPO; + const j = JSON.parse(fs.readFileSync("latest.json", "utf8")); + for (const k of Object.keys(j.platforms || {})) + j.platforms[k].url = j.platforms[k].url.split(src).join(dst); + fs.writeFileSync("latest.json", JSON.stringify(j, null, 2)); + ' + + # Create the public release (once) and upload all four assets. + if ! GH_TOKEN="$RELEASES_TOKEN" gh release view "$TAG" --repo "$PUBLIC_REPO" >/dev/null 2>&1; then + GH_TOKEN="$RELEASES_TOKEN" gh release create "$TAG" --repo "$PUBLIC_REPO" \ + --title "MyDevTools $TAG" --notes "MyDevTools desktop $TAG" + fi + GH_TOKEN="$RELEASES_TOKEN" gh release upload "$TAG" --repo "$PUBLIC_REPO" \ + --clobber "$DMG" "$TARGZ" "$SIG" latest.json diff --git a/apps/desktop/src-tauri/tauri.conf.json b/apps/desktop/src-tauri/tauri.conf.json index 57d3d237..0d47dfda 100644 --- a/apps/desktop/src-tauri/tauri.conf.json +++ b/apps/desktop/src-tauri/tauri.conf.json @@ -31,7 +31,7 @@ } }, "updater": { - "endpoints": ["https://github.com/itsmeakhil/mydevtools/releases/latest/download/latest.json"], + "endpoints": ["https://github.com/mydevtools-tech/mydevtools-releases/releases/latest/download/latest.json"], "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEIwQTI5NjQwRjg5MjgwNjQKUldSa2dKTDRRSmFpc0Rqc21XWGdNSGVPNlp4YVlVV0JWdFpJVk9kYzBIdkx2MUFHNHZWc1VKUmsK" } }, diff --git a/apps/web/src/components/download-desktop-button.tsx b/apps/web/src/components/download-desktop-button.tsx index 12427216..85d96185 100644 --- a/apps/web/src/components/download-desktop-button.tsx +++ b/apps/web/src/components/download-desktop-button.tsx @@ -11,7 +11,9 @@ import { Button } from "@/components/ui/button"; * across releases without editing the site. Falls back to the releases page if * the API is unreachable or no asset is found yet. */ -const REPO = "itsmeakhil/mydevtools"; +// Public releases-mirror repo (source repo is private, so its release assets +// aren't publicly downloadable). CI mirrors the DMG + latest.json here. +const REPO = "mydevtools-tech/mydevtools-releases"; const RELEASES_PAGE = `https://github.com/${REPO}/releases/latest`; type Asset = { name: string; browser_download_url: string };